Skip to content

Sprint C16b: catalog DDL builders — new_for_ddl + chainable setters#33

Merged
AdaWorldAPI merged 1 commit into
mainfrom
claude/beautiful-gates-dJo0u
Jun 2, 2026
Merged

Sprint C16b: catalog DDL builders — new_for_ddl + chainable setters#33
AdaWorldAPI merged 1 commit into
mainfrom
claude/beautiful-gates-dJo0u

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Summary

Adds DDL-friendly constructors and chainable setters to catalog::TableDefinition / catalog::schema::FieldDefinition / catalog::schema::IndexDefinition so external codegen tools can build typed canonical forms purely for DDL emission via ToSql, without needing in-DB allocation or pub(crate) access to internal fields.

18/18 new tests green. No new dependencies. No Cargo.lock changes. No edits to kvs/lance/*, sql/statements/*, runtime layers, or existing impl blocks (new methods live in dedicated impl blocks beside the existing ones). Single commit, atomic.

Downstream consumer and motivation

This is the upstream-side foundation for AdaWorldAPI/openproject-nexgen-rs's codegen pipeline. Nexgen's C16a (already merged: AdaWorldAPI/openproject-nexgen-rs#20) landed a mirror-layout op-surreal-ast crate that duplicated catalog's struct shapes because:

  • surrealdb-core::sql::statements::DefineTableStatement is pub(crate) — not importable
  • catalog::TableDefinition IS pub but fields are pub(crate) and the constructor demands runtime IDs (namespace_id, database_id, table_id) + fills cache UUIDs

With this PR landed, nexgen's planned C16c sprint switches mirror→canonical: From<op_surreal_ast::TableDefinition> for catalog::TableDefinition impls + render through the canonical catalog::* path. The mirror crate is then deletable.

See .claude/op-codegen-bridge/README.md for the full initiative context, scope, and what was deliberately deferred.

API added

// catalog/table.rs
impl TableDefinition {
    pub fn new_for_ddl(name: impl Into<TableName>) -> Self;
    pub fn with_schemafull(self, v: bool) -> Self;
    pub fn with_drop(self, v: bool) -> Self;
    pub fn with_comment(self, v: Option<String>) -> Self;
    pub fn with_table_type(self, v: TableType) -> Self;
    pub fn with_view(self, v: Option<ViewDefinition>) -> Self;
    pub fn with_permissions(self, v: Permissions) -> Self;
}

// catalog/schema/field.rs
impl FieldDefinition {
    pub fn new_for_ddl(name: Idiom, table: TableName) -> Self;
    pub fn with_kind(self, v: Option<Kind>) -> Self;
    pub fn with_flexible(self, v: bool) -> Self;
    pub fn with_readonly(self, v: bool) -> Self;
    pub fn with_value(self, v: Option<Expr>) -> Self;
    pub fn with_assert(self, v: Option<Expr>) -> Self;
    pub fn with_computed(self, v: Option<Expr>) -> Self;
    pub fn with_comment(self, v: Option<String>) -> Self;
    pub fn with_reference(self, v: Option<Reference>) -> Self;
}

// catalog/schema/index.rs
impl IndexDefinition {
    pub fn new_for_ddl(name: impl Into<String>,
                       table_name: impl Into<TableName>,
                       cols: Vec<Idiom>) -> Self;
    pub fn with_comment(self, v: Option<String>) -> Self;
}

new_for_ddl constructors supply dummy zero IDs (NamespaceId(0), DatabaseId(0), TableId(0)) and Uuid::now_v7() cache timestamps. The dummy IDs do not appear in rendered SurrealQL — pinned by new_for_ddl_does_not_leak_table_id_into_render.

Each new impl block is annotated #[allow(dead_code)] with a rationale comment: pub items have no in-crate caller (they exist as the public ergonomic surface for external surrealdb-core consumers); the #[cfg(test)] ddl_builder_tests modules exercise every method, but the dead_code lint runs on the non-test build target where no caller is visible.

Deliberately deferred

Setters whose parameter types are pub(crate) and need a public-API decision:

Type Used by Sprint
Permission FieldDefinition::{select,create,update}_permission auth sprint
DefineDefault FieldDefinition::default computed-fields sprint
Index variants Uniq/Hnsw/FullText/Count IndexDefinition::index unique-index sprint (for has_one) + vector-index sprint
ChangeFeed TableDefinition::changefeed runtime config, not codegen

For typical Rails-mapped schema codegen the slots covered here are sufficient. The with_changefeed setter that was in the original draft triggered a private-in-public warning and was dropped — see the rationale comment in catalog/table.rs.

Tests — 18/18 green

$ cargo test -p surrealdb-core --lib ddl_builder_tests
test result: ok. 18 passed; 0 failed; 0 ignored; 1825 filtered out; finished in 0.00s

TableDefinition (8):

  • new_for_ddl_does_not_leak_table_id_into_render — dummy IDs invisible in DDL
  • builder_output_equals_struct_literal_output — strongest invariant: builder = literal modulo cache UUIDs
  • with_schemafull_round_trips, with_drop_round_trips, with_comment_round_trips, with_table_type_round_trips
  • new_for_ddl_supplies_dummy_ids_and_now_caches — verifies IDs at zero, cache UUIDs non-nil
  • chained_builders_preserve_all_set_values — multi-builder chain integrity

FieldDefinition (6):

  • new_for_ddl_defaults_to_no_kind_and_no_constraints
  • new_for_ddl_carries_name_and_table_through_to_sql
  • with_kind_round_trips, with_flexible_and_readonly_round_trip, with_comment_round_trips
  • builder_output_equals_struct_literal_output

IndexDefinition (4):

  • new_for_ddl_defaults_to_non_unique_idx
  • new_for_ddl_carries_name_table_and_cols_to_sql
  • multi_column_index_renders_all_columns
  • with_comment_round_trips

Preflight

Tool Status
cargo check -p surrealdb-core --no-default-features exit 0, 25 warnings — all pre-existing, none reference my edits (verified by grep -E 'catalog/(table|schema/field|schema/index).rs' on the warnings)
cargo test -p surrealdb-core --lib ddl_builder_tests 18 passed; 0 failed
cargo fmt Skipped on tree level — stable rustfmt reformats 20+ unrelated files due to upstream's nightly-only rustfmt.toml options (same caveat that ndarray fork's AGENTS.md documents). My 3 files are hand-formatted in upstream tab style.
cargo audit / cargo deny / cargo clippy -- -D warnings Not run in container (cargo-make not installed). Recommend running the full canonical battery before merge.

Files changed

Path Change
.claude/op-codegen-bridge/README.md new — initiative notes, scope, deferred items
.claude/board/AGENT_LOG.md +1 entry (append-only, via tee -a)
surrealdb/core/src/catalog/table.rs + DDL-builder impl block + 8 tests
surrealdb/core/src/catalog/schema/field.rs + DDL-builder impl block + 6 tests
surrealdb/core/src/catalog/schema/index.rs + DDL-builder impl block + 4 tests

Zero edits to: kvs/lance/*, sql/statements/*, kvs/, iam/, any runtime/transaction layer, or any existing impl TableDefinition / impl FieldDefinition / impl IndexDefinition block. New methods live in dedicated impl blocks beside the originals so identifying / reverting / extending the surface is mechanical.

Verified pin-compatibility (AdaWorldAPI ecosystem)

While preparing this PR I verified the fork's existing pins against the AdaWorldAPI ecosystem-wide constraints:

Dependency Pin in fork Constraint
Rust toolchain 1.95 (rust-toolchain.toml) 1.95
lance =7.0.0 (exact) 7.0.0
lance-index =7.0.0 (exact) 7.0.0
lancedb =0.30.0 (exact) 0.30.0
arrow-array 58 58
arrow-schema 58 58
ndarray AdaWorldAPI git fork, hpc-extras feature matches
datafusion not directly referenced (transitive via lance) n/a

No version-pin changes needed in this PR.

Summary by CodeRabbit

  • New Features

    • Added fluent builder APIs for constructing table, field, and index definitions externally for DDL rendering without requiring in-database runtime IDs.
  • Tests

    • Added tests validating builder correctness and SQL output integrity.

Adds DDL-friendly constructors and chainable setters to
catalog::TableDefinition / catalog::schema::FieldDefinition /
catalog::schema::IndexDefinition so external codegen tools can build
typed canonical forms purely for DDL emission via ToSql, without
needing in-DB allocation or pub(crate) access to internal fields.

Background and downstream consumer

The first consumer is AdaWorldAPI/openproject-nexgen-rs C16a, which
landed a mirror-layout op-surreal-ast crate (PR #20, merged). With
this PR landed here, the planned nexgen C16c sprint switches from
mirror-layout to canonical: From<op_surreal_ast::*> for catalog::*
impls + render through the canonical catalog::* path. Until then,
nexgen's mirror keeps the two layouts in lockstep.

See .claude/op-codegen-bridge/README.md for the initiative context,
scope of this sprint, and what was deliberately deferred.

API added

  TableDefinition (catalog/table.rs):
    pub fn new_for_ddl(name: impl Into<TableName>) -> Self
    pub fn with_schemafull(self, v: bool) -> Self
    pub fn with_drop(self, v: bool) -> Self
    pub fn with_comment(self, v: Option<String>) -> Self
    pub fn with_table_type(self, v: TableType) -> Self
    pub fn with_view(self, v: Option<ViewDefinition>) -> Self
    pub fn with_permissions(self, v: Permissions) -> Self

  FieldDefinition (catalog/schema/field.rs):
    pub fn new_for_ddl(name: Idiom, table: TableName) -> Self
    pub fn with_kind(self, v: Option<Kind>) -> Self
    pub fn with_flexible(self, v: bool) -> Self
    pub fn with_readonly(self, v: bool) -> Self
    pub fn with_value(self, v: Option<Expr>) -> Self
    pub fn with_assert(self, v: Option<Expr>) -> Self
    pub fn with_computed(self, v: Option<Expr>) -> Self
    pub fn with_comment(self, v: Option<String>) -> Self
    pub fn with_reference(self, v: Option<Reference>) -> Self

  IndexDefinition (catalog/schema/index.rs):
    pub fn new_for_ddl(name, table_name, cols: Vec<Idiom>) -> Self
    pub fn with_comment(self, v: Option<String>) -> Self

Each impl block is annotated #[allow(dead_code)] with a rationale
comment: pub items have no in-crate caller (they exist as the public
ergonomic surface for external surrealdb-core consumers); the
#[cfg(test)] ddl_builder_tests modules exercise them but dead_code
lints the non-test build target.

Deliberately deferred

Setters whose parameter types are pub(crate) (Permission, the four
Permission slots on FieldDefinition, DefineDefault, ChangeFeed, Index
variants beyond Idx) require a public-API decision and follow in
dedicated sprints when downstream actually needs them. For typical
Rails-mapped schema codegen the slots covered here are sufficient.

The single warning the original draft triggered
(with_changefeed exposed pub(crate) ChangeFeed) was dropped — see
the rationale comment in catalog/table.rs.

Tests

  cargo test -p surrealdb-core --lib ddl_builder_tests
    → 18 passed; 0 failed (1825 other tests filtered out)

  TableDefinition (8):
    new_for_ddl_does_not_leak_table_id_into_render
    builder_output_equals_struct_literal_output
    with_schemafull_round_trips
    with_drop_round_trips
    with_comment_round_trips
    with_table_type_round_trips
    new_for_ddl_supplies_dummy_ids_and_now_caches
    chained_builders_preserve_all_set_values

  FieldDefinition (6):
    new_for_ddl_defaults_to_no_kind_and_no_constraints
    new_for_ddl_carries_name_and_table_through_to_sql
    with_kind_round_trips
    with_flexible_and_readonly_round_trip
    with_comment_round_trips
    builder_output_equals_struct_literal_output

  IndexDefinition (4):
    new_for_ddl_defaults_to_non_unique_idx
    new_for_ddl_carries_name_table_and_cols_to_sql
    multi_column_index_renders_all_columns
    with_comment_round_trips

The "builder_output_equals_struct_literal_output" tests are the
strongest invariant: the builder is a pure ergonomic wrapper,
semantically identical to a raw struct construction modulo cache
UUIDs (which don't appear in DDL output).

Preflight

  cargo check -p surrealdb-core --no-default-features → exit 0
    25 warnings, all pre-existing (verified by filtering on my files —
    no warnings reference my edits). My code adds no new warnings.

  cargo fmt skipped on the tree level — stable rustfmt reformats
    20+ files due to upstream's nightly-only rustfmt.toml options
    (same caveat ndarray fork's AGENTS.md documents). My 3 files are
    hand-formatted in upstream tab style.

  cargo audit / cargo deny / cargo clippy not run in this container
    (cargo-make not installed). Recommend running the full canonical
    battery before merge.

Files changed

  .claude/op-codegen-bridge/README.md            new — initiative notes
  .claude/board/AGENT_LOG.md                     +1 entry (append-only)
  surrealdb/core/src/catalog/table.rs            +DDL-builder impl block + 8 tests
  surrealdb/core/src/catalog/schema/field.rs     +DDL-builder impl block + 6 tests
  surrealdb/core/src/catalog/schema/index.rs     +DDL-builder impl block + 4 tests

No edits to: kvs/lance/*, sql/statements/*, runtime/transaction layers,
existing impl TableDefinition / FieldDefinition / IndexDefinition
blocks (new methods live in dedicated impl blocks beside the existing
ones). No new dependencies. No Cargo.lock changes.

https://claude.ai/code/session_01PBTGaPCSnnt6u3pjXpbLwY
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces DDL-builder APIs across three catalog type definitions. TableDefinition, FieldDefinition, and IndexDefinition each gain new_for_ddl() constructors and chainable with_* setters to build canonical SQL-renderable objects externally without in-DB runtime ID allocation. Comprehensive tests verify that dummy IDs do not leak into rendered SQL and that builder output matches direct construction.

Changes

DDL Builder API and Tests

Layer / File(s) Summary
Initiative documentation and planning
.claude/op-codegen-bridge/README.md, .claude/board/AGENT_LOG.md
README describes the op-codegen-bridge initiative, problem statement, new API shape, scope boundaries, and downstream consumer (op-surreal-ast). AGENT_LOG records the session changes for the DDL-builder work.
TableDefinition DDL builder and tests
surrealdb/core/src/catalog/table.rs
TableDefinition gains new_for_ddl() constructor initializing dummy namespace/database/table IDs and default state, plus chainable with_* setters for schemafull, drop, comment, table_type, view, and permissions. Tests verify dummy IDs do not appear in ToSql output, builder-produced instances match struct-literal construction, and each setter round-trips correctly.
FieldDefinition DDL builder and tests
surrealdb/core/src/catalog/schema/field.rs
FieldDefinition introduces new_for_ddl() constructor and eight chainable with_* setters for kind, flexible, readonly, value, assert, computed, comment, and reference. Tests confirm defaults, SQL output includes provided name and table, round-trip behavior for each setter, and equivalence with struct-literal construction.
IndexDefinition DDL builder and tests
surrealdb/core/src/catalog/schema/index.rs
IndexDefinition adds new_for_ddl() constructor and with_comment() setter. Tests validate builder defaults (id=0, Index::Idx, prepare_remove=false), name/table/column preservation in rendered SQL, multi-column handling, and comment round-tripping.

Sequence Diagram

sequenceDiagram
  participant Caller
  participant TableDefinition
  participant FieldDefinition
  participant IndexDefinition
  participant ToSql
  Caller->>TableDefinition: new_for_ddl("my_table")
  TableDefinition-->>Caller: TableDef with dummy IDs
  Caller->>FieldDefinition: new_for_ddl(field_name, table_name)
  FieldDefinition-->>Caller: FieldDef with defaults
  Caller->>FieldDefinition: with_kind(Kind::String)
  FieldDefinition-->>Caller: updated FieldDef
  Caller->>IndexDefinition: new_for_ddl(index_name, table_name, cols)
  IndexDefinition-->>Caller: IndexDef with defaults
  Caller->>IndexDefinition: with_comment("indexed on id")
  IndexDefinition-->>Caller: updated IndexDef
  Caller->>ToSql: to_sql() on all definitions
  ToSql-->>Caller: rendered DDL without dummy IDs
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 From catalog seeds three types now grow,
With builders that chainable flows bestow—
No IDs to leak, just DDL so clean,
The finest SQL schema ever seen!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Sprint C16b: catalog DDL builders — new_for_ddl + chainable setters' directly and accurately describes the main change: adding DDL-oriented constructors and chainable builder methods to catalog types.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/beautiful-gates-dJo0u

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8ffe4088c4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +161 to +162
pub fn new_for_ddl(name: impl Into<TableName>) -> Self {
Self::new(NamespaceId(0), DatabaseId(0), TableId(0), name.into())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Export the new DDL builders from catalog

For downstream codegen users, this constructor is still unreachable: catalog::table and catalog::schema are private modules, and catalog/mod.rs only re-exports these definitions with pub(crate) use schema::{..., *} and pub(crate) use table::* (checked lines 17-19 and 33-37). As a result, external crates cannot name surrealdb_core::catalog::TableDefinition/FieldDefinition/IndexDefinition, so the newly added public builder API cannot be used outside this crate despite being added for that purpose.

Useful? React with 👍 / 👎.

Comment on lines +238 to +239
pub fn with_reference(mut self, v: Option<Reference>) -> Self {
self.reference = v;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid a private type in the reference setter

If the field builders are exported for the intended external consumers, this setter remains unusable because Reference is imported from crate::expr::reference::Reference, whose definition is pub(crate) (checked surrealdb/core/src/expr/reference.rs:10). Downstream crates therefore cannot construct or even name the Option<Reference> argument needed to set references, so this part of the advertised DDL API needs a public wrapper/type decision or should be deferred like the other private-parameter setters.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.claude/op-codegen-bridge/README.md:
- Line 48: The README lists `changefeed` as in-scope but the implementation
intentionally omits support for ChangeFeed (it is pub(crate) and omitted in
TableDefinition's DDL-builder and AGENT_LOG at line 307), so remove `changefeed`
from the in-scope list; update the backtick-delimited list (`comment`,
`table_type`, `view`, `permissions`, `changefeed`) to exclude `changefeed` so it
reads `comment`, `table_type`, `view`, `permissions`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a282448a-9e2e-499c-b163-026419f1f242

📥 Commits

Reviewing files that changed from the base of the PR and between 0d3632f and 8ffe408.

📒 Files selected for processing (5)
  • .claude/board/AGENT_LOG.md
  • .claude/op-codegen-bridge/README.md
  • surrealdb/core/src/catalog/schema/field.rs
  • surrealdb/core/src/catalog/schema/index.rs
  • surrealdb/core/src/catalog/table.rs


In-scope:
- `TableDefinition`: `new_for_ddl` + setters for `schemafull`, `drop`,
`comment`, `table_type`, `view`, `permissions`, `changefeed`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove changefeed from the in-scope list.

The implementation deliberately omits with_changefeed because ChangeFeed is pub(crate) (see the rationale comment at the end of the TableDefinition DDL-builder impl block in table.rs). The AGENT_LOG entry at line 307 also confirms changefeed was skipped alongside other pub(crate) types.

📝 Proposed fix
 - `TableDefinition`: `new_for_ddl` + setters for `schemafull`, `drop`,
-  `comment`, `table_type`, `view`, `permissions`, `changefeed`
+  `comment`, `table_type`, `view`, `permissions`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
`comment`, `table_type`, `view`, `permissions`, `changefeed`
`comment`, `table_type`, `view`, `permissions`
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/op-codegen-bridge/README.md at line 48, The README lists
`changefeed` as in-scope but the implementation intentionally omits support for
ChangeFeed (it is pub(crate) and omitted in TableDefinition's DDL-builder and
AGENT_LOG at line 307), so remove `changefeed` from the in-scope list; update
the backtick-delimited list (`comment`, `table_type`, `view`, `permissions`,
`changefeed`) to exclude `changefeed` so it reads `comment`, `table_type`,
`view`, `permissions`.

@AdaWorldAPI AdaWorldAPI merged commit 0c54640 into main Jun 2, 2026
1 check passed
AdaWorldAPI pushed a commit to AdaWorldAPI/openproject-nexgen-rs that referenced this pull request Jun 2, 2026
Makes nexgen's rust-version explicit so it matches the AdaWorldAPI
ecosystem-wide pin. Until now, nexgen relied on the container's
default rustc — recently 1.94.1, silently diverging from
AdaWorldAPI/surrealdb (1.95) and AdaWorldAPI/ndarray (1.95.0).

What landed:

  rust-toolchain.toml (new):
    channel = "1.95"
    components = ["rustfmt", "clippy"]

    Comment explains the no-patch-in-channel rule (mirrors the same
    caveat surrealdb fork's rust-toolchain.toml carries: "1.95.1" etc.
    is not a valid toolchain identifier and breaks rust-analyzer).

  Cargo.toml [workspace.package]:
    rust-version = "1.95"

    Cargo-canonical place to declare MSRV; per-crate opt-in via
    `rust-version.workspace = true` (none use it yet).

Why now: planned C16c sprint (the consumer-side bridge to surrealdb's
catalog DDL builders, depending on AdaWorldAPI/surrealdb#33 being
merged) adds a surrealdb-core path-dep, which requires rust 1.95.
Pinning nexgen first means C16c lands without a toolchain surprise.

Verification:

  rustup auto-installed 1.95 when the toolchain pin landed:
    $ rustc --version
    rustc 1.95.0 (59807616e 2026-04-14)

  All 72 codegen-family tests green on 1.95:
    op-codegen-bucket     7
    op-codegen-projection 26
    op-codegen-pipeline   15 (9 lib + 6 integration)
    op-cli                7
    op-surreal-ast        17

  No code changes — purely the toolchain config. The 72 tests landing
  green prove the change is non-breaking.

Cross-ecosystem pin status (AdaWorldAPI):

  surrealdb         1.95     rust-toolchain.toml             ✓
  ndarray           1.95.0   rust-toolchain.toml             ✓
  openproject-nexgen-rs  1.95  rust-toolchain.toml + Cargo  ✓ (this sprint)
  lance-graph       presumed 1.95, not verified this sprint   ?

Minor patch-version difference between surrealdb (no patch) and
ndarray (patch) flagged for a future ecosystem-pin sweep — not
in-scope here.

Lance / arrow / datafusion / lancedb: nexgen has zero direct deps on
these today. They enter via surrealdb-core if/when C16c adds the dep.
Verified the surrealdb fork's pins (rust 1.95, lance =7.0.0,
lance-index =7.0.0, lancedb =0.30.0, arrow 58, datafusion 53
transitive via lance, ndarray hpc-extras for crate::simd::*) are
already on-spec in
AdaWorldAPI/surrealdb claude/beautiful-gates-dJo0u commit 07b1e2a.

Files changed:
  rust-toolchain.toml                              new
  Cargo.toml                                       +1 line (rust-version)
  .claude/sprints/c16d-toolchain-pin/STATE         new (sprint notes)

https://claude.ai/code/session_01PBTGaPCSnnt6u3pjXpbLwY
@AdaWorldAPI

Copy link
Copy Markdown
Owner Author

Pin verification — full table

Verifying the fork is on-spec for the AdaWorldAPI ecosystem pinning rule. Concrete evidence for each constraint:

Rust toolchain

$ cat rust-toolchain.toml
[toolchain]
channel = "1.95"
components = ["rustfmt", "clippy"]
targets = ["wasm32-unknown-unknown"]

Lance + LanceDB (exact pins via = prefix)

$ grep -E '^(lance|lance-index|lancedb) *=' surrealdb/core/Cargo.toml
lance = { version = "=7.0.0", optional = true }
lance-index = { version = "=7.0.0", optional = true }
lancedb = { version = "=0.30.0", optional = true }

Arrow 58 (semver range)

$ grep -E '^arrow-(array|schema)' surrealdb/core/Cargo.toml
arrow-array = { version = "58", optional = true }
arrow-schema = { version = "58", optional = true }

$ grep -A1 '^name = "arrow-array"' Cargo.lock
name = "arrow-array"
version = "58.3.0"

Datafusion 53 (transitive via lance, resolver-locked)

$ grep -A1 '^name = "datafusion"$' Cargo.lock
name = "datafusion"
version = "53.1.0"

datafusion is not a direct dep. Lance 7.0.0's transitive resolution pulls in datafusion = "53.1.0". Adding a direct datafusion = "=53.x.y" pin would be ecosystem-redundant — bumping lance is the only path to a different datafusion.

ndarray (AdaWorldAPI git fork — both workspace dep + patch.crates-io)

After commit c158624 on this branch, both ndarray references now carry an exact rev:

# Cargo.toml line 156 — workspace dep
ndarray = { version = "0.17",
            git = "https://github.com/AdaWorldAPI/ndarray.git",
            rev = "0129b5c80cee8d88fdae97be813524328e4d025a",
            default-features = false,
            features = ["std", "hpc-extras"] }

# Cargo.toml line 513 — patch.crates-io (for transitive ndarray = "0.17.x"
# consumers like `ort` via the optional `ml` feature)
[patch.crates-io]
ndarray = { git = "https://github.com/AdaWorldAPI/ndarray.git",
            rev = "0129b5c80cee8d88fdae97be813524328e4d025a" }

Before c158624 both entries were unrev'd — cargo update could have drifted them to the fork's main HEAD between sessions. Now lockstep-pinned to the same commit, so the workspace dep and the patch-routed transitive both resolve to the same ndarray crate.

crate::simd::* polyfill — concrete usage sites in surrealdb-core

The hpc-extras feature activates ndarray::simd::* (runtime-dispatched to simd_avx2.rs / simd_avx512.rs / simd_neon.rs / simd_amx.rs / simd_wasm.rs / simd_scalar.rs via a LazyLock capability table in ndarray::simd_caps). Consumption is active in surrealdb/core/src/idx/trees/vector.rs:

Line Kernel Type
267 (design note) HNSW vector index built on F64x8 comment
414 CPU detection cached once dispatch glue
421 L2 (Euclidean) distance use ndarray::simd::F64x8;
444, 450 L1 (Manhattan) distance use ndarray::simd::F64x8;
469, 475 L∞ (Chebyshev) distance use ndarray::simd::F64x8;
496 Pearson correlation use ndarray::simd::F64x8;

Gated by the vector-hpc feature flag. Compile-time route to the SIMD code paths; no extra deps pulled.

Cross-repo consistency

Repo Rust pin Source
AdaWorldAPI/surrealdb 1.95 rust-toolchain.toml
AdaWorldAPI/ndarray 1.95.0 (with patch) rust-toolchain.toml (minor inconsistency with this fork's no-patch rule)
AdaWorldAPI/openproject-nexgen-rs 1.95 (just landed in PR #21) rust-toolchain.toml + [workspace.package].rust-version

The full matrix + verification recipe is captured for future sessions at .claude/knowledge/adaworldapi-pinning.md on this branch (commit 2186d6d).


Posted as a pin-verification audit trail so reviewers can confirm the spec-match without re-grepping. Happy to tighten further (e.g. arrow-array = "=58.3.0" exact, or direct datafusion = "=53.1.0") if those would be preferred — the current state matches the stated AdaWorldAPI constraints ("lance 7.0.0, lanceDb 0.30, datafusion 53, arrow 58") literally.

AdaWorldAPI added a commit that referenced this pull request Jun 3, 2026
Follow-up to PR #33: AdaWorldAPI pin docs + ndarray rev pin
AdaWorldAPI pushed a commit that referenced this pull request Jun 17, 2026
The bridge has been pinned at the stranded
`claude/op-surreal-ast-field-types-stacked` branch since the
D-AR-5.2 work first went up as nexgen-rs#29. That PR landed on a
stacked branch instead of main and never made it back, so the
nexgen-rs `main` diverged from the bridge's view for several
sprints.

The D-AR-5.2 work has now re-landed via nexgen-rs#36 (Kind
variants + field_type consumer), and nexgen-rs `main` carries
significant downstream improvements:

- FK direction gating (#33) — only `belongs_to` emits a column
- Polymorphic FK fallback (#30) — `option<any>` for unknown
  targets
- Singularization tightening (#34, #35, #37) — fixes corpus
  quirks like `phases→Phase`, `children→Child`,
  `job_status→JobStatus`, `:big_integer→Decimal`
- Phantom-table guard + order-independent ASSERTs (#27/#28/#26)
- Rails type aliases (#37)

The bridge's `From<ast::Kind> for catalog::Kind` impl already
matches the 7 scalar variants the new main carries, so the bump
is mechanical — `cargo check --features op-bridge` passes with
no source changes needed.

Updates Cargo.lock to the new rev (44550a87 — the merge commit
of nexgen-rs#37 on main).
AdaWorldAPI pushed a commit that referenced this pull request Jun 17, 2026
The 16 existing tests cover individual mapping primitives
(`Kind::String → CatalogKind::String`, `Option<T> → Either(None, T)`,
ASSERT lowering in isolation, etc.). What was missing: a single
test that exercises every nexgen-rs-producer feature together
through `bridge_schema`, which is the actual ingress point for
downstream ingestors.

Build one `ast::Schema` containing a `WorkPackage` table with all
four kinds of fields the producer side now emits:

- `subject` : `option<string>` + `ASSERT $value != NONE`
  (typed scalar with validates_presence — both Kind + assert
   flow through D-AR-6.2/6.3)
- `position` : `option<int>` (typed scalar, no assert)
- `project_id` : `option<record<Project>>`
  (belongs_to FK after the #33 direction-gating)
- `assignable_id` : `option<any>`
  (polymorphic FK after the #30 fallback)
- A companion `idx_WorkPackage_project_id` index
- A table comment with AR-shape annotations

Assertions probe the catalog SQL render (the internal field
accessors are `pub(crate)`) and check each feature is preserved:
typed kinds present, ASSERT clauses render for validated
fields only, record-link semantics carry the target table,
polymorphic fallback renders as `any`, index name preserved.

This locks the bridge contract against drift as the producer
side keeps evolving — a single broken arm in `From<ast::*>` would
fail this test loudly. 17 tests pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants