netbadb-types
Shared IDs, physical types, and semantic types
Architecture
NetbaDB keeps application-language concerns at the frontend boundary. A Go, Rust, or future schema frontend produces the same Canonical Schema IR. The core does not inspect Go types or application Rust structs.
The following pipeline is the stable architectural surface:
Application language schema
↓
Language frontend / SDK
↓
Canonical Schema IR
↓
Parser → HIR + type checking
↓
Typed Relational IR
↓
Optimizer / Planner
↓
Executor
↓
Transaction boundary
↓
StorageThe current path is synchronous. The query language is a deliberately small native subset and does not claim full SQL compatibility. The core does not depend on Go, a network runtime, JSON execution IR, or application-specific Rust structs.
Rust Schema API
↓
SELECT / JOIN / ORDER BY / GROUP BY + typed DML
↓
Typed HIR
↓
Logical query / DML statement plan
↓
Scan + nested-loop join + sort + grouped aggregate
↓
Join / filter / sort / aggregate / projection / limit + mutation
↓
Heap
↓
Transaction lifecycle + versioned WAL
↓
Buffer pool (guards, pinning, dirty writeback)
↓
Slotted pages
↓
Page manager / database filenetbadb-schema stores database meaning in explicit Rust structs, independent of any application language. A column has a stable ColumnId, a name, a TypeSpec (physical type plus optional semantic name), nullability, and primary-key metadata.
Schema::new is the fallible construction path and delegates to Schema::validate. Validation rejects duplicate table/column IDs and names, empty names, and empty semantic-type names. Canonical names are frontend-independent UTF-8 identities; equality is exact and case-sensitive.
Each validated TableDef has canonical encoding version 1: it starts with NBTS, then an explicit little-endian version, table identity, and columns in declaration order. SHA-256 over those bytes is the 32-byte SchemaFingerprint. Rust enum discriminants, struct layout, Debug output, and map iteration order do not participate.
The current query subset is compiled as follows:
source → AST → resolved / type-checked HIR → logical plan → physical plan
HIR owns source-level resolution and semantic type checking. Relational IR owns relational meaning and column provenance. The planner selects sequential scans and a correctness-first nested-loop for logical INNER JOIN. The executor evaluates typed expressions against rows from storage.
Layers pass IDs and owned values. They do not spread long-lived references to pages, frames, or tuples into the planner, executor, or catalog.
In the graph, A → B means A depends on B. Lower layers must not depend on higher-level policy. In particular, storage must not depend on the planner or executor, and the executor must not depend on an SDK.
Shared IDs, physical types, and semantic types
Language-independent Canonical Schema IR
Small typed-query AST and parser
Name resolution and nominal type checking
Typed logical relational IR
AST → HIR → logical plan
Logical plan → physical plan, including IndexScan
SDK Schema Spec v1 parsing and fingerprints
Stable schema-driven SQL diagnostics
Catalog and plan inspection DTOs
Protocol v1 binary wire contract
Synchronous Protocol v1 remote client
Sessions, authorization, and blocking TCP runtime
Schema Spec validation and Go source generation
Typed B+Tree ordering, nodes, codecs, and splits
Transactions, WAL, pages, buffer pool, heap, and persistent B+Tree
Synchronous physical-plan execution
Native embedded Database API
Embedded and remote application façade
Standalone manifest-driven TCP server
Offline local inspection CLI
Go is an application language, not an implementation language. The support boundary is:
Rust: native core, embedded SDK, and Protocol v1 remote client Go: independent Protocol v1 client and generated typed bindings
sdk/go is an independent standard-library client. Generated bindings validate result order, names, physical and semantic types, and nullability. They do not generate SQL or query-builder APIs.
Correctness, explicit invariants, and type safety take precedence over convenience. Features are introduced as complete, testable vertical slices. Unimplemented components are not represented as finished APIs.