You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/guides/engine-plugins.md
+40-25Lines changed: 40 additions & 25 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ Data returned by the engine plugin (SQL text, parameters, columns) is passed thr
16
16
17
17
An engine plugin is an external process that implements one RPC:
18
18
19
-
-**Parse** — accepts the query text and either schema SQL or connection parameters, and returns processed SQL, parameter list, and result columns.
19
+
-**Parse** — accepts the **entire contents** of one query file (e.g. `query.sql`) and either schema SQL or connection parameters; returns **one Statement per query block** in that file (each with sql, parameters, columns, and name/cmd).
20
20
21
21
Process plugins (e.g. written in Go) talk to sqlc over **stdin/stdout** using **Protocol Buffers**. The protocol is defined in `protos/engine/engine.proto`.
22
22
@@ -102,40 +102,54 @@ The engine API exposes only **Parse**. There are no separate methods for catalog
102
102
103
103
### 2. Parse
104
104
105
+
sqlc calls Parse **once per query file** (e.g. once for `query.sql`). The plugin receives the full file contents and returns one **Statement** per query block in that file. sqlc then passes each statement to the codegen plugin as a separate query.
106
+
105
107
**Request**
106
108
107
-
- `sql`— The query text to parse.
109
+
- `sql` — The **entire contents** of one query file (all query blocks, with `-- name: X :one`-style comments).
108
110
- `schema_source` — One of:
109
-
- `schema_sql`: schema as in a schema.sql file (used for schema-based parsing).
111
+
- `schema_sql`: full schema as in schema.sql (for schema-based parsing).
110
112
- `connection_params`: DSN and options for database-only mode.
111
113
112
114
**Response**
113
115
114
-
- `sql`— Processed query text. Often the same as input; with a schema you may expand `*` into explicit columns.
115
-
- `parameters`— List of parameters (position/name, type, nullable, array, etc.).
116
-
- `columns`— List of result columns (name, type, nullable, table/schema if known).
116
+
Return `statements`: one `Statement` per query block. Each `Statement` has:
117
+
118
+
- `name` — Query name (from `-- name: GetUser` etc.).
119
+
- `cmd` — Command/type: use the `Cmd` enum (`engine.Cmd_CMD_ONE`, `engine.Cmd_CMD_MANY`, `engine.Cmd_CMD_EXEC`, etc.). See `protos/engine/engine.proto` for the full list.
120
+
- `sql`— Processed SQL for that block (as-is or with `*` expanded using schema).
121
+
- `parameters`— Parameters for this statement.
122
+
- `columns`— Result columns (names, types, nullability, etc.) for this statement.
123
+
124
+
The engine package provides helpers (optional) to split `query.sql` and parse `"-- name: X :cmd"` lines in the same way as the built-in engines:
117
125
118
-
Example handler:
126
+
- `engine.CommentSyntax`— Which comment styles to accept (`Dash`, `SlashStar`, `Hash`).
127
+
- `engine.ParseNameAndCmd(line, syntax)` — Parses a single line like `"-- name: ListAuthors :many"` → `(name, cmd, ok)`. `cmd` is `engine.Cmd`.
128
+
- `engine.QueryBlocks(content, syntax)`— Splits file content into `[]engine.QueryBlock` (each has `Name`, `Cmd`, `SQL`).
129
+
- `engine.StatementMeta(name, cmd, sql)`— Builds a `*engine.Statement` with name/cmd/sql set; you add parameters and columns.
The definition lives in `engine/engine.proto` (and generated Go in `pkg/engine`).
181
+
The definition lives in `protos/engine/engine.proto` (generated Go in `pkg/engine`). After editing the proto, run `make proto-engine-plugin` to regenerate the Go code.
168
182
169
183
## Example
170
184
171
185
The protocol and Go SDK are in this repository: `protos/engine/engine.proto`and `pkg/engine/` (including `sdk.go` with `engine.Run` and `engine.Handler`). Use them to build a binary that implements the Parse RPC; register it under `engines` in sqlc.yaml as shown above.
172
186
173
187
## Architecture
174
188
175
-
For each `sql[]` block, `sqlc generate` branches on the configured engine: built-in (postgresql, mysql, sqlite) use the compiler and catalog; any engine listed under `engines:` in sqlc.yaml uses the plugin path (no compiler, schema + queries go to the plugin's Parse RPC, then output goes to codegen).
189
+
For each `sql[]` block, `sqlc generate` branches on the configured engine: built-in (postgresql, mysql, sqlite) use the compiler and catalog; any engine listed under `engines:` in sqlc.yaml uses the plugin path (no compiler). For the plugin path, sqlc calls Parse **once per query file**, sending the full file contents and schema (or connection params). The plugin returns **N statements** (one per query block); sqlc passes each statement to codegen as a separate query.
{Name: "GetUser", Cmd: pb.Cmd_CMD_ONE, Sql: "SELECT id, name FROM users WHERE id = $1", Parameters: engineRecord.ReturnedParams, Columns: engineRecord.ReturnedCols},
302
+
{Name: "ListUsers", Cmd: pb.Cmd_CMD_MANY, Sql: "SELECT id, name FROM users ORDER BY id", Parameters: nil, Columns: engineRecord.ReturnedCols},
0 commit comments