DotTalk++ / x64base is a DBMS — it owns its storage, its indexes, its locking and its recovery — and it is also an RDBMS: it stores relations, declares relationships between them, and answers questions with relational algebra rather than only with cursor navigation.
Both halves are stated here with their evidence, and so is the boundary. A system that claims the word "relational" without saying where it stops is selling, not documenting.
The DBMS half
| Capability | What it means here |
|---|---|
| Storage engine | Its own DBF-family formats including the 64-bit x64 dialect — real binary field types, 64-bit record addressing, and a memo store with its own object model. See DBF_64 Specification. |
| Indexing | Native CDX and CNX containers, single-tag INX, and an LMDB-backed ordered key store, with tags resolved to fields at build time. See CDX and LMDB Indexing. |
| Concurrency | Cross-process cooperative record and table locks, pid-stamped, with stale-owner recovery. |
| Transactions | Buffered writes with COMMIT / ROLLBACK and a durable redo log under TABLE BUFFER PERSISTENT. Scoped, not a full-ACID claim — see ACID and the Glass-Box Engine. |
| Catalogs | The engine's own metadata tables describe its commands, functions, messages and workspaces — the map drawn in the same ink as the territory. |
| Sessions and scope | Work areas, workspaces that own their own path environment, and a durable workspace identity. See Workspaces. |
The relational half
A relation here is an ordinary table, and relationships between them are expressed two different ways on purpose.
Declared, navigational — RelTalk. REL ADD parent child ON key establishes an
edge in advance; REL JOIN walks it and emits one tuple per leaf combination.
The question it answers is "where do I go from here?". See
RelTalk.
Undeclared, set-oriented — SQLsel. A SQLSEL statement names its own tables
and ON columns, reads no REL or SET RELATION state at all, and answers
"which rows satisfy this?". It carries the operators a relational engine is
expected to have:
- selection and projection,
DISTINCT,ORDER BY,LIMIT INNER,LEFT,RIGHT,FULLandCROSSjoinsCOUNT,SUM,AVG,MIN,MAXwithGROUP BYandHAVINGUNION,UNION ALL,INTERSECT,EXCEPTIN (<select>)and[NOT] EXISTS (<select>)subqueries- expression projection, so
TRIM(LNAME)is a column INSERT,UPDATE,DELETEwith single-table transactions
Neither surface replaces the other. One follows a structure you asserted about your data; the other asks a question that stands on its own.
How the relational claim is checked
Every SQLsel regression compares its result sets against an in-process SQLite oracle over identical data in the same run — not against a recorded expectation. That distinction is the point: a stored expectation only proves our reader agrees with our writer, and a shared misunderstanding passes. An independent engine answering the same question over the same rows does not.
Six of those specs run on every REGRESSION ALL; seven more are explicit-run.
See Regression and Proof Testing and
SQLsel and SQL Conformance.
Where it stops, stated plainly
Referential integrity is not enforced on write. Relations are declared for traversal, not as constraints. Deleting a parent does not refuse, cascade, or null out its children. This is the sharpest gap between x64base and a constraint-enforcing RDBMS, and it is a design position rather than an oversight — but a reader should not infer enforcement from the word "relational".
Also absent, and each refused rather than silently approximated:
- Cross-table atomic commit. An explicit transaction accepts one target table.
- Stored
NULLthrough DML.SQLSEL INSERT/UPDATErefuse a null rather than coercing a blank. Stored nulls themselves do exist — VFP-flavour tables carry a real_NullFlagsbit, byte-verified against files Visual FoxPro wrote — but the DML path does not write one. - Subqueries over a joined outer scope.
- The bare
SELECT ...form without theSQLSELprefix. - Memo-field DML.
Produced absence and stored absence are also kept apart deliberately: an
unmatched outer-join row renders <UNMATCHED>, never a blank that could be
mistaken for data and never a null that would claim more than the join knows.