Skip to content

feat(query): column-list INSERT and column DEFAULT#30

Merged
nevzheng merged 2 commits into
mainfrom
feat/default
Jun 14, 2026
Merged

feat(query): column-list INSERT and column DEFAULT#30
nevzheng merged 2 commits into
mainfrom
feat/default

Conversation

@nevzheng

Copy link
Copy Markdown
Owner

DEFAULT + column-list INSERT

  • INSERT accepts an explicit column list (INSERT INTO t (a, c) ...) and short positional rows; columns not supplied fall back to their DEFAULT, then NULL if nullable, else error.
  • A column's DEFAULT is bound at CREATE TABLE and stored on the field as a JSON-serialized expression, so the storage layer stays free of any query-layer type. At INSERT it's deserialized and evaluated per row (so a future volatile default like now()/uuid_v4() generates a fresh value each row).
  • Defaults are constant expressions — the binder rejects column references (no scope) and subqueries, matching Postgres. No function whitelist needed; the bind+eval gate is the restriction.

Test migration (spec-tests-over-Rust mandate)

  • Moved SQL-statement DDL/DML tests out of tests/ddl.rs (23 → 4) into specs driven through the real server: ddl/schema.slt, insert.slt.
  • tests/ddl.rs keeps only what spec can't express (catalog seeding, schema field/nullable introspection, OR REPLACE internals, stored integer-width assertion).
  • planner.rs (plan shape), volcano.rs (direct plans), sql/mod.rs (parser API) correctly stay in Rust.

Coverage

default.slt covers typed-literal (UUID/DATE/TIME/NUMERIC/BOOLEAN/INTERVAL), expression (CAST/::/COALESCE/CASE/GREATEST), and UUID defaults; column-list mapping; per-row fill across multi-row inserts; rejected cases. clippy -D warnings + fmt clean; full workspace + 14 spec files green.

🤖 Generated with Claude Code

nevzheng added 2 commits June 13, 2026 18:10
INSERT now accepts an explicit column list (`INSERT INTO t (a, c) ...`)
and short positional rows; columns not supplied fall back to their
DEFAULT, then NULL if nullable, else error.

A column's DEFAULT is bound at CREATE TABLE and stored on the field as a
JSON-serialized expression, so the storage layer stays free of any
query-layer type. At INSERT the default is deserialized and evaluated
per row (so a future volatile default like now()/uuid_v4() generates a
fresh value each row). Defaults are constant expressions — the binder
rejects column references (no scope) and subqueries, matching Postgres.

Covered by default.slt (typed-literal, expression, and UUID defaults;
column-list mapping; per-row fill; rejected cases). Drops two ddl.rs
tests whose behavior the feature intentionally changes.
Per the "spec tests for anything SQL-shaped" mandate, migrate the
exec-SQL-and-assert tests out of tests/ddl.rs into .slt specs driven
through the real server:

- ddl/schema.slt: CREATE SCHEMA create/use, default-project shorthand,
  IF NOT EXISTS idempotency, rejected forms, CREATE TABLE error paths,
  OR REPLACE on a missing table.
- insert.slt: NULL into NOT NULL / nullable, narrowing range check.

tests/ddl.rs keeps only what spec can't express: catalog seeding, schema
field/nullable introspection, OR REPLACE schema-swap internals, and the
stored integer-width assertion after coercion (23 tests -> 4). Existing
round-trip/filter/type-mismatch/duplicate cases were already covered by
ddl/create_replace.slt and smoke.slt.
@nevzheng
nevzheng merged commit bcd60e0 into main Jun 14, 2026
5 checks passed
@nevzheng
nevzheng deleted the feat/default branch June 14, 2026 01:17
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.

1 participant