Az include/elib/vir.pm egy deklaratív SQL-lekérdezés generátor / OLAP réteg a VIR (riportok, lekérdezések, kimutatások) számára. A modulok metaadatban leírják, milyen táblák, mezők és dimenziók érhetők el, a motor pedig ebből rak össze SELECT … FROM … JOIN … WHERE … GROUP BY lekérdezéseket — opcionálisan crosstab (pivot) táblával.
A elib::vir absztrakt ősosztály: az _init alapból die „Absztrakt”-tal áll meg, a leszármazottak (pl. dok::szamla::vir, dok::bank::vir — 19+ modulnak van saját vir.pm-je) töltik fel a $self→{meta}-t és a $self→{lists}-et.
A fájl négy package-et tartalmaz:
| Package | Szerep |
elib::vir | Absztrakt ős: query-generálás a metaadatból |
elib::vir::generated | Futásidőben összerakott vir-objektum + relációs-algebra API (filter/project/aggr/join) |
elib::vir::table | Tábla- (vagy al-lekérdezés-) leíró, ami beépíthető a generated-be |
elib::vir::join | UNUSED, csak váz |
Minden mező egy csoportba (groupname) tartozik — ez a tengelyek és mértékek tipológiája:
| Csoport | Szerep | Példa (számla) |
id | egyedi azonosító mezők | szlafej.id, szlaszam, tetelid |
partition | dimenzió / bontási tengely | tipus, partner, cikk_kategoria |
time | idő-dimenzió | datum, teljdat, fizhat |
value | mérték (számolható) | ossz_netto, ossz_afa |
check | logikai szűrőmező | — |
A meta→{tables} írja le a táblákat és hogyan joinolnak egymáshoz:
primary — az elsődleges (FROM-) tábla (pontosan egy)jointo — melyik már bejoinolt táblához csatlakozikjoinon / joinusing — a join-feltételjoin_type — LEFT (alapértelmezés) / INNER / …tablecalc — opcionális callback, ami al-lekérdezést generál tábla helyett
A $self→{lists} névvel ellátott nézetek, amelyek a fenti mezőkből választanak ki egy adott listához használt halmazt (pl. ertekesitesek_aggr).
Konstrukciókor a _generate_trivials automatikusan legyárt minden time mezőből _month / _year / _year_month partíciókat (substr(datum::text, …)-szal), és minden id-ból egy _view partíciót. A havi/éves bontás így „ingyen” elérhető. (A date_project metódussal egyedi idő-partíció is definiálható.)
Ez a motor szíve. Az $alter paraméter mezőnként vezérli, mi történjen az adott mezővel.
process_field_group végigmegy az id / partition / time / value / check csoportokon, és mezőnként dönt:
$alter érték | Jelentés | ||||
1 | sima oszlop | ||||
group | GROUP BY tengely | ||||
sum / min / max / textcat_all | aggregátum | ||||
count | darabszám | ||||
split_day\ | week\ | month\ | quarter\ | year | date_trunc-os időbontás |
Segédmetódusok:
_add_field — az SQL-kifejezés (sum(…) AS mezo)_add_list_field — a megjelenítendő oszlop metaadata (label, type, hidden, listformat); a label végét lokalizált szóval toldja meg (pl. „összesen”, „havi bontás”)_group_field — a GROUP BY kifejezés
calc_tables az $alter→{where} és a tábla-gráf alapján építi a FROM … JOIN … részt. Iteratív: amíg van olyan tábla, aminek a jointo-ja már be van joinolva, hozzáfűzi. Van egy 100-as limit (a szerzők saját HACK SMELL jelölésével) a végtelen ciklus ellen.
Visszatérés: { query, fields, debug }.
Ha $alter→{crosstable} meg van adva, a query köré PostgreSQL crosstab(…) hívást rak (tablefunc extension), és dinamikusan generálja az oszlopdefiníciókat egy „columns” segéd-query eredményéből. Ez a pivot/kimutatás.
| Metódus | Visszatérés |
generate_query | nyers SQL string |
generate_query_for_list | lista-felülethez illeszkedő struktúra: Tables / Mezok / AllKeys |
generate_vir | jelenleg undef (csonk) |
A elib::vir::generated (@ISA=('elib::vir')) egy futásidőben, dinamikusan összerakott vir-objektum, ami relációs-algebra-szerű műveleteket ad. Minden művelet új generated példányt ad vissza (immutábilis, láncolható):
| Metódus | Művelet |
filter(todo⇒'keep'\|'drop', fields⇒[…]) | mezők szűrése |
project(…) | új származtatott mezők hozzáadása |
aggr($todo, $where) | aggregálás: GROUP BY-ra állítja a mezőket, a value-kat összegezhetővé teszi |
where($where) | szűrőfeltétel (az aggr-ra épül) |
left_join_table / inner_join_table / gen_join_table | két vir-objektum összejoinolása (vir⇒, joinon⇒, jointo⇒, rename_left/right⇒) |
revir / get_table / get_meta | nézetből visszatabularizált meta vagy elib::vir::table (al-lekérdezésként újra felhasználható) |
A state mező (meta / aggr) és az _assert őrzi, hogy a műveletek csak a megengedett állapotban fussanak (csak $SYS{devel} alatt aktív).
A _add_meta egyesíti több forrás metaadatát (a join-okhoz), rename-mel a mezőnév-, field-, label- és label_prefix-ütközések feloldására.
Egy tábla (vagy al-lekérdezés expr⇒-rel) leírója, describe(…)-szal feltöltve:
_tablify — minden mezőre rányomja a tábla-aliast (as_table vagy table)get_meta — olyan meta-struktúrát ad, amit a generated be tud kebeleznimerge_desc — descriptor adatszerkezetek mergelése (copy-paste elkerülésére)Ez teszi lehetővé, hogy egy korábban generált query-t al-lekérdezésként egy új vir építőelemeként használjunk.
A dok::szamla::vir::_init tölti fel a metaadatot:
$meta->{tables}={ szlafej => { table=>'szlafej', primary=>1 }, szlatet => { table=>'szlatet', jointo=>'szlafej', joinon=>'szlafej.szlaszam=szlatet.szlaszam', type=>'1N' }, ... }; $meta->{id} = { id=>{...}, szlaszam=>{...}, tetelid=>{...} }; $meta->{partition} = { tipus=>{...}, partner=>{...}, cikk_kategoria=>{...} }; $meta->{time} = { datum=>{...}, teljdat=>{...}, fizhat=>{...} }; $meta->{value} = { ossz_netto=>{ field=>'szlafej.ossz_netto', me=>'szlafej.penznem', ... }, ... }; $self->{lists} = { ertekesitesek_aggr=>{ tables=>[...], id=>[...], partition=>[...], time=>[...], value=>[...] }, ... };
A kód tele van a fejlesztők saját SMELL / HACK jelöléseivel és kikommentált debug-sorokkal (#debug(…); use devel;). Ezek a szerzők kétségei, nem hibák, de jelzik, hogy egyes részek (pl. a calc_tables limit-hack, a where az aggr-ra hackelve) tudottan ideiglenesek.
Generálva kódelemzésből — include/elib/vir.pm (r22049, 2025-04-30).