Overview

The Elastic Database is a hierarchical object database where:

  • Objects (class instances) are stored directly in the database
  • Collections are named containers holding objects of a type
  • Subcollections are nested within objects via LIST members
  • CID (Collection ID) uniquely identifies each collection
  • OID (Object ID) uniquely identifies each object within a collection

Hierarchy Structure

Database Root
├── Collection: Users (CID: 1)
│   ├── Object: TT_User (OID: 1)
│   │   ├── Fields: Type, Login, Email...
│   │   ├── Subcollection: Orgs (links)
│   │   └── Subcollection: Projects
│   │       └── Object: TT_Project
│   │           └── Subcollection: Tasks
│   └── Object: TT_User (OID: 2)
│
├── Collection: Orgs (CID: 2)
│   └── Object: TT_Org (OID: 1)
│       ├── Fields: Name, AdminOid...
│       ├── Subcollection: Users (member links)
│       └── Subcollection: Partitions

Schema Definition

The database schema is defined declaratively through class annotations:

// Main collection class - creates "Users" collection
class attrib(db_col, Users) TT_User : public SB_User {
public:
    variant attrib(db, d_DWORD)    Type;           // Field: 32-bit int
    variant attrib(db, d_string)   Login;          // Field: string
    variant attrib(db, d_string)   Email;          // Field: string
    variant attrib(db, LIST)       Orgs;           // Subcollection
    variant attrib(db, LIST)       Projects;       // Subcollection
    variant attrib(db, BINARY)     Avatar;         // Binary data
}

// Another main collection - creates "Orgs" collection
class attrib(db_col, Orgs) TT_Org {
public:
    variant attrib(db, d_string)   Name;           // Field
    variant attrib(db, d_DWORD)    AdminOid;       // Reference to user
    variant attrib(db, LIST)       Users;          // Subcollection (members)
    variant attrib(db, LIST)       Partitions;     // Subcollection
}

// Embedded class (no db_col - stored in LIST subcollections)
class TT_Project : public SB_Object {
    variant attrib(db, d_string)   Name;
    variant attrib(db, LIST)       Tasks;          // Sub-subcollection
}

Field Attributes

AttributeDescription
attrib(db_col, Name)Class-level: binds class to main collection
attrib(db, d_DWORD)32-bit unsigned integer field
attrib(db, d_QWORD)64-bit unsigned integer field
attrib(db, d_string)String field
attrib(db, LIST)Subcollection (nested objects)
attrib(db, BINARY)Binary data field

Reference Attributes

For linking objects across collections:

// Paired reference (CID + OID to another object)
variant attrib(db_ref_cid, Users) UserCid;
variant attrib(db_ref_oid, Users) UserOid;

// Reference to OID in a global/main collection
variant attrib(db_glob_ref, Users) UserOid;

// Reference to just a collection CID
variant attrib(db_col_ref) CollectionCid;

Control Object

Every collection has a control object at obj_id=1 (class SB_Control):

class SB_Control {
    variant attrib(db, d_DWORD)    LastOid;        // Last object ID
    variant attrib(db, d_DWORD)    OwnerCid;       // Parent collection
    variant attrib(db, d_DWORD)    OwnerOid;       // Owner object
    variant attrib(db, LIST)       SecondColCid;   // Child collections
}

Query DSL

EPL has an embedded DSL for database operations inside elastic{} blocks:

SELECT

variant Obj, Cids, Oids, Err;

// By collection name
elastic{
    SELECT obj: obj1 FROM Users WHERE Login="admin"
           TO &Obj CID_OUT &Cids OID_OUT &Oids ERR_OUT &Err;
}

// By collection ID
elastic{
    SELECT obj: obj1 FROM cid:<Cid> WHERE obj_id=<id> TO &Obj;
}

// Access subcollection
elastic{
    SELECT obj: obj1 FROM cid:<Cid>.oid:<Oid>.mm:Projects TO &Obj;
}

INSERT

variant Obj = NewObject;
variant Cids, Oids, Err;

elastic{
    INSERT <ClassName> INTO cid:<Cid> OBJECT &Obj
           CID_OUT &Cids OID_OUT &Oids WAIT_FOR_END ERR_OUT &Err;
}

// Into subcollection
elastic{
    INSERT TT_Project INTO cid:<Cid>.oid:<Oid>.mm:Projects
           OBJECT &Obj OID_OUT &Oids WAIT_FOR_END;
}

UPDATE

variant Obj = ModifiedObject;
variant Err;

elastic{
    UPDATE cid:<Cid> SET OBJECT &Obj WHERE obj_id=<oid> ERR_OUT &Err;
}

// No transaction mode
elastic{
    UPDATE cid:<Cid> SET OBJECT &Obj WHERE obj_id=<oid> NO_TRANS ERR_OUT &Err;
}

// Update specific fields
elastic{
    UPDATE cid:<Cid> SET Name="NewName", Status=1 WHERE obj_id=<oid>;
}

CREATE COLLECTION / SUBCOLLECTION

// Create main collection
elastic{
    CREATE COLLECTION Users;
}

// Create subcollection
elastic{
    CREATE SUBCOLLECTION cid:<ParentCid>.oid:<ParentOid>.mm:Projects
           CID_OUT &Cids ERR_OUT &Err;
}

CREATE TEMPLATE

// Define object schema
elastic{
    CREATE TEMPLATE TT_User, DWORD, Type, string, Login, string, Email, LIST, Projects;
}

Other Commands

// Show collections
elastic{ SHOW COLLECTIONS TO &Output; }

// Show templates
elastic{ SHOW TEMPLATES TO &Output; }

// Delete object
elastic{ DELETE FROM cid:<Cid> WHERE obj_id=<Oid>; }

// Binary data access
elastic{ OPEN_BIN cid:<Cid>.oid:<Oid>.mm:Avatar TO &hFile; }
elastic{ CLOSE_BIN <hFile>; }

Database Creation with TDbProcessor

include_file "$Studio/Sys/TDbProcessor.epl";

TDbProcessor @Proc;
Proc->DirTo = GetCurScriptDir() . "/";
Proc->ClassDir[0] = Proc->DirTo . "Classes/";
Proc->Path = GetCurScriptDir() . "/main.orn";
Proc->Create();  // Scans classes, creates collections & templates

TDbProcessor performs:

  1. Scans class directories for .epl files
  2. Reads attrib(db_col, Name) → Creates main collections
  3. Reads attrib(db, type) → Creates templates (field schemas)
  4. Executes CREATE COLLECTION and CREATE TEMPLATE commands