This guide is for architects who design object structures (OT) and data tables (DT).
It contains:
- a quick design path
- a detailed, step-by-step implementation guide
- practical rules and pitfalls confirmed by platform behavior
- Prepare project languages (if translated physical columns are required).
- Design object structure (OT): columns, flags, optional parent/reference behavior.
- Generate OT (physical PostgreSQL table).
- Design DT for the OT (one OT can have multiple DTs).
- Generate DT.
- Assign DT to specific objects.
Important:
- Data never exists without an object.
- Objects can exist without data.
- If project languages are needed for translated physical columns, configure them before the first OT/DT generation.
- Define project scope and object hierarchy.
- Prepare project languages (if translated columns are required).
- Create object structure with required object metadata columns.
- Generate object structure.
- Create one or more data tables for that structure.
- Generate data tables.
- Assign a data table to each object that should store data.
If you need translated physical columns:
- configure project languages before first OT/DT generation
- choose mandatory/default/fallback behavior
- verify locale set matches your expected API/UI usage
If project languages are introduced late, schema behavior is more constrained and migration can be disruptive.
Define:
- object hierarchy model (root + children)
- whether objects can have data
- whether private objects are allowed
- whether history and access tables are needed
Required object column category:
Common optional categories:
- description
- identifiers
- additional metadata
- file content + file metadata columns
OT defines object metadata and hierarchy.
Core OT column types:
DISPLAY_NAME (required)
DESCRIPTION
ADDITIONAL_DATA
SIMPLE_OBJECT_IDENTIFIER
COMPLEX_OBJECT_IDENTIFIER
FILE
FILE_FILENAME (metadata column for FILE)
FILE_SIZE (metadata column for FILE)
OT unique and required constraints:
- Required types:
DISPLAY_NAME
- Unique types:
DISPLAY_NAME, DESCRIPTION
Object table flags:
NO_HISTORY_TABLE
NO_ACCESS_TABLE
PARENT_RECURSIVE
PARENT_OPTIONAL
DATA_ALLOWED
DATA_REQUIRED
SETTINGS_ALLOWED
PRIVATE_ALLOWED
PRIVATE_SUGGESTED
ENUM
Important semantic rules:
ENUM hides objects in browse and disables data usage.
DATA_REQUIRED requires DATA_ALLOWED.
PRIVATE_ALLOWED cannot be combined with NO_ACCESS_TABLE.
Generation creates physical PostgreSQL tables and constraints.
After generation:
- object rows can be created
- validation and key rules are enforced by database constraints
- some structural changes become restricted and may require migration strategy
Define:
- time semantics (primary time)
- major values for primary telemetry/signals
- minor/additional values for secondary payload
- metadata columns (quality, min/max)
- optional connected-column behavior for enum/bitmask visualization
DT stores changing measurements/events for objects.
Core DT column types:
PRIMARY_TIME (required)
MAJOR_VALUE_ANALOG
MAJOR_VALUE_DISCRETE
MINOR_VALUE
VALUE_QUALITY (metadata)
ADDITIONAL_DATA
VALUE_IDENTIFIER (part of primary key)
VALUE_MIN (metadata)
VALUE_MAX (metadata)
DT unique and required constraints:
- Required types:
PRIMARY_TIME
- Unique types:
PRIMARY_TIME, VALUE_IDENTIFIER
Generation creates physical PostgreSQL data storage.
Key result:
- data write path enforces min/max/regex/nullability rules directly in PostgreSQL
An object can switch assigned data table only with data lifecycle awareness.
Important rule:
- before switching to a different table, existing data for that object in the old table must be removed
This prevents cross-table ambiguity for object-owned datasets.
¶ Connected columns, enums, and bitmasks
Connected column type:
NONE
BITMASK_BITS
ENUM_VALUES
Connected columns are soft semantic links from DT columns to OT identifier columns. They are resilient to object set evolution and are useful for enum/bitmask rendering.
Practical pattern:
- Source DT value holds numeric enum/bitmask payload.
- Connected column points to OT identifier values.
- Existing referenced values are rendered textually.
- Missing references remain visible numerically.
¶ Values and String constants
- OBJECT_REFERENCE = 0 - Reference to other generic object
- ENUM_REFERENCE = 1 - Reference to other enum object
- BOOL = 2
- SMALL_INT = 3
- INT = 4
- BIG_INT = 5 - Beware of internal BIG_INT/DOUBLE conversions in scripts
- REAL = 6
- DOUBLE = 7
- VARCHAR = 8
- TEXT = 9
- NUMERIC_BITFIELD = 10 - Internally represented by int, expected to serve as bitfield
- BITFIELD = 12 - Internally represented by bitfield
- JSON_BINARY = 14
- DATE = 16
- TIME = 17
- TIME_TIMEZONE = 18 - Time with timezone
- DATETIME = 19
- DATETIME_TIMEZONE = 20 - Datetime with timezone
- BYTE_ARRAY = 21 - Binary data
- IP_ADDRESS = 23
- UUID = 24
Notes:
OBJECT_REFERENCE and ENUM_REFERENCE are structurally equivalent at database level; UI interpretation differs.
OBJECT_REFERENCE is shown as object link.
ENUM_REFERENCE is shown as enum-like name + numeric id.
- DATA_SOURCE = 0 - Data table has column for data authors
- TIME_SERIES = 1 - Neccessary for using Timescale DB extension
TIME_SERIES is enabled by default.
- DISCONNECT_VALUE = "disconnect_value"
- DISCONNECT_TIMEOUT = "disconnect_timeout"
DISCONNECT_VALUE and DISCONNECT_TIMEOUT are used together to insert a gap marker when data source inactivity exceeds timeout.
¶ Data table column types
- PRIMARY_TIME = 0 - Primary time column for timescale DB
- MAJOR_VALUE_ANALOG = 2 - Fast-changing values (e.g. temperature, pressure)
- MAJOR_VALUE_DISCRETE = 3 - Slowly-changing values (e.g. state, error, quality, running)
- MINOR_VALUE = 4 - Other auxiliary value (e.g. array of integers, reference to other object/enum, state, small JSON)
- VALUE_QUALITY = 5 - Quality of the row if this column is not a meta column (target meta column is null). Quality of the target value column otherwise
- ADDITIONAL_DATA = 6 - Other metadata (e.g. original message, position, JSON, binary data)
- VALUE_IDENTIFIER = 7 - part of primary key, can be used to filter (e.g. type, variable_id, device_id)
- VALUE_MIN = 100 - Minimum value of the target major value column (always meta column, always hat the same datatype)
- VALUE_MAX = 101 - Maximum value of the target major value column (always meta column, always has the same datatype)
¶ Data table column flags
- OPTIONAL = 0 - Nullable data type
- ARRAY_VALUE = 1 - Array of data types
- REGEX_CASE_SENSITIVE = 2 - Validate case sensitive Regex
- REGEX_NEGATION = 3 - Use !~ in regex validation instead of ~
- MIN_EXCLUDED = 4 - Use > instead of >= in minimum validation
- MAX_EXCLUDED = 5 - Use < instead of <= in minimum validation
Validation limits and regex rules are enforced in generated PostgreSQL schema.
¶ Data table column settings
- UNIT = "unit"
- MIN_EXPECTED_VALUE = "min_expected_value" - Not validated, just expected.
- MAX_EXPECTED_VALUE = "max_expected_value" - Not validated, just expected.
¶ OT column flags
Object table column flags:
OPTIONAL
AUTOINCREMENT
TRANSLATED
ARRAY_VALUE
REGEX_CASE_SENSITIVE
REGEX_NEGATION
MIN_EXCLUDED
MAX_EXCLUDED
Key restrictions:
TRANSLATED cannot be combined with ARRAY_VALUE.
AUTOINCREMENT cannot be combined with ARRAY_VALUE.
Templates can both speed up design and enforce required structure.
Template version lifecycle:
INACTIVE
ACTIVE
DEPRECATED
Practical behavior:
- Active version is visible for normal selection.
- Deprecated version can remain usable and can define a replacement target version.
- Once template-based structures are generated and actively used, changes are intentionally constrained.
¶ Wizard behavior (template and non-template)
When creating OT/DT through wizard:
- template mode: you add template columns and choose specification variants
- required template columns must be completed first
- after required columns, you can finish or continue with optional columns
- when template policy allows it, custom extra columns can be added
Without template:
- wizard offers reasonable default types and data types
- architect is responsible for consistency and future compatibility
Unique combination allows additional unique constraints beyond the primary key.
Example concept:
- combination group A enforces uniqueness on column A
- combination group B enforces uniqueness on columns B + C
Optional parent participation can be included in combinations where model needs hierarchical uniqueness.
Most entities use soft-delete first and hard-delete later. For low-level infrastructure entities this may differ.