feat(ddl): DEFAULT clause, DROP TABLE/INDEX, ALTER TABLE#86
Merged
Conversation
Honour `DEFAULT <literal>` on column definitions. Literal expressions only — text, integer, real, boolean, NULL, and unary +/- on numerics. Function calls and other non-literal expressions are rejected at CREATE TABLE time so users see the limit upfront. Default fires only when the column is omitted from INSERT (matches SQLite — explicit NULL is preserved as NULL). Persists through save and reopen via `table_to_create_sql` emitting the DEFAULT clause and `parse_create_sql` propagating it back into Column. Refactors `CreateQuery::new`'s per-column body into a free `parse_one_column` helper so ALTER TABLE ADD COLUMN can reuse the same column-shape parsing in a follow-up commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirror SQLite's DROP semantics on the in-memory engine: - DROP TABLE [IF EXISTS] <name>; — single target, rejects the reserved catalog name `sqlrite_master`. The dropped table's secondary/HNSW/FTS indexes ride along with the Table struct. - DROP INDEX [IF EXISTS] <name>; — single target. Walks every table looking across all three index families. Refuses to drop auto-indexes (`sqlrite_autoindex_*` from PK / UNIQUE columns) — same rule SQLite enforces. The full-rebuild-on-save pager naturally cascades drops: the next `save_database` call regenerates `sqlrite_master` from current state and simply doesn't write rows for the dropped objects. Pages previously occupied become orphans on disk (no free-list yet — file size doesn't shrink until a future VACUUM lands). Replaces the existing `process_command_unsupported_statement_test` which used DROP TABLE as the canary; switched to CREATE VIEW since DROP TABLE now executes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implement the four SQLite-style ALTER TABLE sub-operations, one per statement: - ALTER TABLE [IF EXISTS] <t> RENAME TO <new>; - ALTER TABLE [IF EXISTS] <t> RENAME COLUMN <old> TO <new>; - ALTER TABLE [IF EXISTS] <t> ADD COLUMN <coldef>; - ALTER TABLE [IF EXISTS] <t> DROP COLUMN <col>; RENAME TO updates `tb_name`, every secondary index's `table_name`, and any auto-index whose name embedded the old table name. RENAME COLUMN re-keys row storage, fixes up the `primary_key` pointer if the renamed column was the PK, and updates dependent indexes (secondary / HNSW / FTS) including auto-index names. ADD COLUMN reuses the new `parse_one_column` helper from the parser refactor in the DEFAULT-clause commit. Allows NOT NULL only when a DEFAULT is supplied (matches SQLite — without DEFAULT there's no backfill source for existing rows). Rejects PRIMARY KEY / UNIQUE on the added column; both would need backfill+uniqueness against existing rows. With a DEFAULT, every existing rowid gets backfilled in place so the new column reads consistently from the start. DROP COLUMN refuses the PK column and refuses to leave the table columnless; cascades through every dependent index family. Docs: rewrote the schema-modification section of supported-sql.md to enumerate the new surface (ALTER TABLE, DROP TABLE, DROP INDEX), the DEFAULT clause expansion to CREATE TABLE, and the residual not-yet-supported gaps. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two findings from review of feat/alter-drop-tables: - JSON DEFAULT validation gap: ALTER TABLE ADD COLUMN ... JSON DEFAULT '<garbage>' would silently backfill every existing row with invalid JSON because insert_row's per-row validation is bypassed during the add_column backfill path. Tighten eval_literal_default to parse JSON literals at CREATE TABLE / ALTER TABLE time so the check fires before any rows are written. - Add a transaction-rollback test for DROP TABLE to lock down the Database::deep_clone snapshot path. The other ALTER ops are covered via the snapshot semantics implicitly, but DROP TABLE is the most destructive new statement and warrants explicit coverage. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joaoh82
added a commit
that referenced
this pull request
May 4, 2026
Bumps every product manifest from 0.2.0 → 0.3.0 (engine, sqlrite-ask, sqlrite-ffi, sqlrite-mcp, four SDK crates, desktop, Tauri config) and the three inter-workspace dependency pins that `bump-version.sh` currently misses (engine→sqlrite-ask, sqlrite-mcp→engine, wasm SDK→sqlrite-ask). Refreshes Cargo.lock. Headline change: PR #86 (SQLR-2) added DEFAULT clause on CREATE TABLE columns, DROP TABLE / DROP INDEX with IF EXISTS, and ALTER TABLE with the four SQLite-style sub-operations (RENAME TO, RENAME COLUMN, ADD COLUMN, DROP COLUMN). Note: the release-pr.yml workflow's bump step failed with `failed to select a version for the requirement \`sqlrite-ask = "^0.2"\`` because bump-version.sh doesn't update inter-workspace path-dep version specs. Filing a follow-up to fix the script; for this release the three pins were patched manually. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings DDL surface to SQLite parity for the schema-modification statements that were previously listed under "Not yet supported". Closes SQLR-2.
DEFAULT <literal>on CREATE TABLE columns — landed first as a prerequisite soALTER TABLE ADD COLUMN ... NOT NULLhas a value to backfill with. Literal expressions only (integer/real/text/bool/null + unary+/-); non-literal expressions likeCURRENT_TIMESTAMPare rejected at CREATE time.DROP TABLE [IF EXISTS] <name>andDROP INDEX [IF EXISTS] <name>— single target per statement. DROP INDEX refuses auto-indexes (sqlrite_autoindex_*), matching SQLite.ALTER TABLE [IF EXISTS] <t> <op>— one operation per statement, four sub-operations:RENAME TO,RENAME COLUMN,ADD COLUMN,DROP COLUMN. ADD COLUMN allowsNOT NULLonly withDEFAULT(matches SQLite). DROP COLUMN refuses the PK column and the only-column case.Persistence is full-rebuild-on-save: dropped objects are simply absent from the next
sqlrite_masterwrite. Pages previously occupied by them become orphans on disk (no free-list yet — file size doesn't shrink until a future VACUUM).Test plan
cargo build --workspace --exclude sqlrite-desktop --exclude sqlrite-python --exclude sqlrite-nodejs --all-targetscargo test --workspace --exclude sqlrite-desktop --exclude sqlrite-python --exclude sqlrite-nodejs— 421 passing (380 baseline + 41 new), 1 ignoredcargo fmt --all -- --checkcargo clippy --workspace --exclude sqlrite-desktop --exclude sqlrite-python --exclude sqlrite-nodejs --all-targets— warning count unchanged from baseline (41)BEGINKnown limitations (documented in docs/supported-sql.md)
DEFAULTaccepts literals only — noCURRENT_TIMESTAMP/ function calls / column refsDROP TABLE/DROP INDEXleave orphan pages on disk (no free-list)ADD COLUMNrejectsPRIMARY KEY/UNIQUE(would need backfill + uniqueness against existing rows)ALTER TABLE; one target perDROP🤖 Generated with Claude Code