8000 feat(engine): type a .sql file of any one statement by colinhacks · Pull Request #26 · colinhacks/reylo · GitHub
[go: up one dir, main page]

Skip to content

feat(engine): type a .sql file of any one statement - #26

Merged
colinhacks merged 6 commits into
mainfrom
any-statement
Oct 23, 2026
Merged

colinhacks merged 6 commits into
mainfrom
any-statement

Conversation

@colinhacks
Copy link
Copy Markdown
Owner

A .sql file may now hold one statement of any kind. A select, insert, update, delete, merge, replace, values or table is analyzed as before. Any other statement (DDL, a session setting, explain, show, pragma, call on Postgres) is a command, typed from the database's own describe:

  • it resolves to nothing (cardinality: "none", so .run() is Promise<void>) where the database describes no columns;
  • it resolves to Row[] where it returns rows, every column nullable, since nothing says where a column comes from (SQLite's are unknown, as its prepare declares no type);
  • its parameters are those the database binds: on Postgres only explain, call and create table … as take any, and a placeholder in another command is an error at the placeholder.

Until now each of these was error reylo10. A file of several statements still is, and its message still says how to leave a migration out of the type check.

What stays refused, each with its reason:

  • Postgres: copy … from stdin and copy … to stdout, which move data through the connection outside a statement's rows.
  • MySQL: call, and a command that may return rows (explain, analyze, check, …) whose prepare describes no columns: MySQL's prepare of explain describes none and the run returns twelve. Statements MySQL cannot prepare (start transaction, lock tables, use) keep the server's own error.

A database error on a command carries the advice to exclude migrations, since a migration's create table fails against a schema that already has the table on SQLite, and reylo generate skips such files as it skipped migrations before.

Verification

  • cargo test for the four engine crates, with unit tests for the command path in core and on Postgres.
  • The oracle, on Postgres 18 and MySQL 8.4: new cases commands (Postgres) and sqlite_commands, and mysql_statements re-blessed, its DDL, set, do, show tables and describe now typed and checked against what the server returns.
  • tests/analyze.test.ts: a SQLite create index is typed none and runs through .run(), a pragma returns its rows, and a create table of an existing table is SQLite's error with the advice.
  • lab/pg-forms: a do block and an explain are typed forms now, their types pinned like the others'; untyped/ holds what is still refused (a copy from stdin, a placeholder in DDL, a parameter written twice), its errors listed in expected.txt.
  • By hand through pg, postgres.js and mysql2: DDL resolves to undefined; explain, show and show tables return their rows.
  • The loader's typecheck and tests, every lab, the driver matrix and every example project pass.
  • The three engine artifacts are rebuilt.

Copilot AI balanced review requested due to automatic review settings October 22, 2026 20:42
@vercel
vercel Bot commented Oct 22, 2026 •
Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
reylo Ready Ready Preview Oct 22, 2026 11:56pm UTC

Request Review

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No critical issues. Two small things inline.

Reviewed changes

I reviewed the whole of the single commit, which makes any single non-query statement a typed "command" on all three databases.

  • Core statement classification: lex::one_statement now returns Statement::Query or Statement::Command(first_word) instead of refusing. refused_command adds the exclude-from-type-check advice to any database error on a command.
  • Postgres commands: a statement that analyze.rs can't read goes to the new Engine::command. It types from the describe alone with every column nullable, and puts reylo1 on a placeholder the server doesn't bind. COPY … FROM STDIN and COPY … TO STDOUT are refused before 8000 any round trip.
  • MySQL commands: these are typed from the prepare. CALL is still refused, and so is a command in MAY_RETURN_ROWS (such as EXPLAIN) whose prepare describes no columns.
  • SQLite commands: these are typed from the embedded SQLite's prepare against the replayed schema, with every column unknown and nullable.
  • reylo generate: NOT_A_QUERY now skips any file whose diagnostic carries the exclude-from-type-check advice.
  • Oracle, lab, docs and tests: new commands and sqlite_commands cases, a re-blessed mysql_statements, pg-forms typed and untyped forms, updated per-dialect "One statement per file" docs, and a SQLite loader test.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using claude-opus-5-5 | 𝕏

Comment thread src/cli.ts Resolved
Comment thread engine/postgres/src/postgres.rs Resolved
@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found. Both earlier points are addressed.

Reviewed changes

I reviewed the two commits pushed since the last pullfrog review.

  • Narrowed reylo generate skipping: NOT_A_QUERY in src/cli.ts now matches only the shared lex::several_statements() message and Postgres's cannot insert multiple commands into a prepared statement. So if the database refuses a single command, generate prints the error and fails instead of skipping it as a migration. tests/cli.test.ts covers a command that types, a command SQLite refuses (the message includes the exclude advice) and two migrations of several statements that are still skipped.
  • Removed the orphaned doc line: deleted the leftover KINDS doc comment in engine/postgres/src/postgres.rs and rebuilt the three engine artifacts.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

@colinhacks
colinhacks force-pushed the any-statement branch 3 times, most recently from bf672f8 to 43b8690 Compare October 22, 2026 22:27
@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No critical issues. One small docs gap is inline.

Reviewed changes

Since the last pullfrog review, the branch was rebased onto main (28aeadf). According to the range-diff, the only changes since then are in the docs, plus a new commit that rebuilds the artifacts.

  • Rewrote the per-dialect docs bullet: main removed the old "One statement per file" bullet. The PR now adds a "Statements other than queries" bullet to postgres.mdx, mysql.mdx and sqlite.mdx, written in main's new plain style.
  • Rebuilt the engine artifacts on main: all three engine.wasm files pass tests/fingerprint.test.ts against the rebased sources.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using claude-opus-5-5 | 𝕏

Comment thread site/content/docs/postgres.mdx Resolved
@colinhacks
colinhacks force-pushed the any-statement branch 4 times, most recently from a887c83 to 3f71406 Compare October 22, 2026 23:39
@colinhacks
colinhacks merged commit bd05e3d into main Oct 23, 2026
6 checks passed
@colinhacks
colinhacks deleted the any-statement branch October 23, 2026 00:18
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

0