Pročitano iz izvora (GEngine\src, GTehnobiro\src) i iz same baze, 23. septembra 2026.
Šema baze je napisana u Javi, ne u SQL-u. Jedna tabela = jedna Java klasa. Iz istog opisa kolona nastaju: CREATE TABLE, SELECT, tabela na ekranu, forma za unos, validacija, štampa i Excel izvoz. Najbliža poznata stvar je Oracle Forms ili MS Access — samo napisan u kući.
gjava/db/sys/SysTable.java — „tabela tabela":
public class SysTable extends DbtObject
{
public static GColumnString TABLE = new GColumnString("Tabela", 50, GColumnHeader.CAN_BE_NULL_NO);
public static GColumnString NAZIV = new GColumnString("Opis", 40);
public static GColumnInteger LEVEL = new GColumnInteger("Level", 2, EDITABLE_NO, CAN_BE_NEGATIVE_NO);
public static GColumnString ID = new GColumnString("Id", 50 + 80, GFKey.PRIMARY,
CAN_BE_NULL_NO, SHOWABLE_NEVER);
public SysTable()
{
super("SysTable");
setTitle("Табела");
getInfo().setVersion(1, 1, 15);
addColumn(TABLE); addColumn(NAZIV); addColumn(PACKAGE); addColumn(LEVEL); addColumn(ID);
setRDCItem(NAZIV);
}
}Kolona nije string u upitu nego objekat sa tipom, dužinom i pravilima (CAN_BE_NULL_NO, EDITABLE_NO, PRIMARY, SHOWABLE_NEVER).
Dokaz da baza nastaje iz koda: u MySQL-u je systable.Id tipa char(130), a u Javi stoji 50 + 80 (TABLENAMESIZE + PACKAGENAMESIZE). Baza je doslovno otisak klase.
gjava/data/GMySqlDatabase.java:119:
String createString = "CREATE TABLE " + pDataSource.getName();
for (int i = 0; i < pDataSource.getColumnCount(); i++) {
GColumnHeader ch = pDataSource.getColumn(i);
if (ch.getDataType().equals(GDataType.INTEGER)) createString += " bigint(" + ch.getLength() + ")";
if (ch.getDataType().equals(GDataType.STRING)) createString += " char(" + ch.getLength() + ")";
if (ch.getDataType().equals(GDataType.TEXT)) createString += " text";
if (ch.isIncrementalKey()) createString += " serial";
}Akcija u ekranu „(Ре)креирај табелу" radi Class.forName("paket.Tabela").newInstance() pa ovo.
⚠️ Zamka koja briše podatke.dbtCreateprvo zovedbtDelete, a to jeDROP TABLE IF EXISTS(GMySqlDatabase.java:239). Na popunjenoj tabeli „(Ре)креирај" briše sve. Kolona se dodaje ručnimALTER TABLE ... ADD COLUMN. Engine i sam tako radi kad dodaje polje (GMySqlDatabase.java:435). Migracije šeme ne postoji — postoji samo „napravi iz nule".
| sloj | gde živi | primer |
|---|---|---|
| struktura | Java klasa | SysTable.java |
| registar | ekran „Табела", puni se iz klasa | GDbtPool.refreshSysTable |
| podešavanja | u bazi | SysTableEditableColumn(L) — koje su kolone vidljive/editabilne |
Zato dve instalacije mogu imati isti kod, a različite ekrane. Otuda i upit SHOW KEYS FROM systableeditablecolumn koji se vidi u tragu svakog otvaranja ekrana (GDataSource2d.java:993).
GDataSourceLevel00 (155 linija) implements GInfoable
└ Level05 → Level10
└ Level20 (587 linija) redovi i kolone; GRowDataSource, GColumnProvider, GExcelDataSource
└ Level30
└ Level40/50 implements GMenuCallable ← poziv bez GUI-ja
└ GDataSource
├ GDataSource1d jedan zapis
└ GDataSource2d tabela (redovi)GDataSourceLevel20.getColumn, GDataSource2d.getRowCount i columnExists su najčešći pozivi u celom programu — svaka ćelija prolazi kroz metapodatke. To je cena ovog dizajna (vidi Cortiveo tracer).
public class Data extends MemDbtObject // db.tehnobiro.Data
public class MemDbtObject extends DbtObject // gjava.db — razlika je samo GDataServer.Type.MEMORYMemDbtObject je ista tabela, samo u memoriji. Zato paketna štampa (OTPsoft) čita .txt fajl u ObrazacH/ObrazacL i nad tim radi isti kod za štampu, filtriranje i prikaz kao da je baza. To je isti razlog zbog kog postoje GEngineAccess i GEngineExcel.
GDataSource2d.java:364-425:
dbt.setPermanentFilter(...) // trajno ogranicenje (engine/program)
dbt.setFilter(...) // programski filter ← koristi ovaj iz koda
dbt.setUserFilter(...) // ono sto korisnik ukuca u ekranuSva tri se AND-uju, pa programski filter ne gazi korisnikov. Upotreba:
dbt.setFilter(new GFilterItem("ClientStranaCount", GRelation.GE, 6));
dbt.addFilter(new GFilterItem("ClientStranaCount", GRelation.LE, 10));
dbt.loadData();GRelation: EQ NE GT GE LT LE SW (počinje) EW (završava) $$ (sadrži) EQ$ (broj znakova).
Filter radi i nad memorijskim podacima — GDataDriverMemory.java:42-55 skuplja sva tri sloja i primenjuje mData.rowInFilter(i, mFilter).
definition 718 redova definitioninputh 696 definitioninputl 36153
definitionprinth 673 definitionprintl 6874 obrazacprinth 32
systable 44 syslog 22492 entitet 0 ← praznadefinitionprintl.IdMaster → definitionprinth.Id ON UPDATE CASCADE.entitet* tabele su prazne — univerzalni identitet postoji kao podsistem, ali se ne koristi.utf8_unicode_ci.Engine (gjava/print/GPrintJob.java:432-505) već zna boju:
GColor lItemColorForeground = p.mColorForeground;
Color savedColor = mGraphics.getColor();
if (lItemColorForeground != null) mGraphics.setColor(lItemColorForeground);
...
mGraphics.setColor(savedColor); // vrati staru bojuAplikativni generator3 (DataHPrint, DataHPrintBaseUtilities) ima svoj PrintItem i radi mGraphics.setFont(textFont) — bez boje. Kolone elementa štampe (definitionprintl):
Tip, FieldName, Opis, StranaRb, RelativeY, PrnX, PrnY, PrnWidth, PrnHeight,
FontName, FontBold, FontItalic, FontSize, Umetanje, RowSpacing, Poravnanje, UgaoBoje nema. Dodavanje boje u 4 koraka:
generator3/DefinitionPrintL.java — npr. new GColumnString("Boja", 9) za #RRGGBBALTER TABLE definitionprintl ADD COLUMN Boja char(9) ... AFTER FontSize — ne „(Ре)креирај"DataHPrintBaseUtilities.addPrintItem: dbt.getString("Boja") → poneti kroz PrintItemDataHPrint (oko linije 235): setColor pre crtanja, vratiti staru — prepisati iz GPrintJobObrazac već postoji u kući; ne izmišlja se ništa novo.