modules-forms-vtables.md 4.22 KB

Modules, forms, virtual tables

The three core nouns of xly's metadata model. A reader who internalises these can navigate the rest of the framework. The vocabulary is not always consistent in the codebase — same concept, different names in different files — so part of this page is reconciling the synonyms.

Module

The unit of "a configurable thing in the system".

  • One row per module in gdsmodule.
  • Carries the URL fragment (sName), display names (sChinese, sEnglish, sBig5), tree position (sParentId, sAllId), product edition (sVersionFlowId, see Slice 2), optional CRUD procedure names (sSaveProName, sDeleteProName, sProcName, sCalcProName, sSaveProNameBefore).
  • 1,358 rows in the current live DB.

The Java codebase calls this concept "module", "model", "models", and "modle" (typo, common). The variable sModelsId and method getModelConfigByModleId both take a module sId, despite the naming. See the naming caution in Slice 1.

Form

The screen layout for a module — header + N field definitions.

  • Master: one row per form in gdsconfigformmaster. Carries the backing object (sTbName), backing-object type (sType{table, view, proc}), default SQL fragments (sSqlStr, sWhere, sOrder), grid behaviour (bGrd, iPageSize), jurisdiction column.
  • Slave: one row per field in gdsconfigformslave. Carries the field name (sName — matches a column in the backing object), control type (sControlName), display labels, validation rules, default value, dropdown SQL, button instructions.
  • A module is linked to its form via gdsconfigformmaster.sParentId = gdsmodule.sId — semantic FK, no enforcement. (Note: gdsmodule.sFormId exists but is empty for most modules and is not the canonical link.)
  • 2,022 master rows, 159,371 slave rows in the current live DB.

The form is the user-visible artefact: when a PM "creates a screen" in BACK, what they're really doing is INSERTing a gdsconfigformmaster row plus 5-50 gdsconfigformslave rows.

Virtual table

xly's term (and table prefix) for a "table" that is itself defined as metadata, not as a CREATE TABLE statement.

Virtual tables are how PMs declare "I want this kind of thing" without asking an engineer. Most virtual tables back to a real physical table (the framework supports the migration step, or it pre-creates a generic "wide" table the PM populates), but the abstraction the runtime sees is the metadata declaration, not the underlying storage.

This is distinct from a database view: a virtual table is metadata; a view is a CREATE VIEW SQL object. Both can back a form (via gdsconfigformmaster.sType = 'table' or 'view'). See Slice 3 for the view-backed case.

How they fit together

gdsmodule  (module, 1 row)
   └── (joined via sParentId)
       gdsconfigformmaster  (form-master, 1 row per form)
          ├── gdsconfigformslave  (fields, N rows)
          ├── gdsconfigformcustomslave  (per-tenant fields, N or 0)
          └── gdsconfigformuserslave    (per-user tweaks, N or 0)

gdsmodule.sName   →  registered route in  gdsroute  (URL whitelist)
gdsmodule.sFormId →  (mostly empty — historical)

Every form has exactly one module. Every module should have at most one form, but a few have several gdsconfigformmaster rows pointing at the same sParentId — those represent screens with multiple panels or sub-tabs.

Three nouns, one engine

The runtime — BusinessBaseController and BusinessBaseServiceImpl, documented in Slice 1 — knows how to render any module / form / virtual-table combination. There is no per-module Java code. PMs creating new modules are creating new rows; they are not creating new code paths.