Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
b6aa62d
Added support for the database engine plugin system for extending sql…
asmyasnikov Dec 28, 2025
5336821
Fix of endtoend tests
asmyasnikov Dec 28, 2025
2b88994
added install plugin-based-codegen's
asmyasnikov Dec 28, 2025
b1d156d
remove tmp file
asmyasnikov Dec 28, 2025
9f65d4f
removed go.{mod,sum}
asmyasnikov Dec 28, 2025
74b621f
SQLCDEBUG=processplugins=1
asmyasnikov Dec 28, 2025
cede5d3
Fix
asmyasnikov Dec 28, 2025
15b240d
Fix
asmyasnikov Dec 28, 2025
0b3b165
Apply suggestions from code review
asmyasnikov Dec 28, 2025
6c5b9a6
revert Combine
asmyasnikov Dec 28, 2025
7609ebc
.gitignore + README
asmyasnikov Jan 10, 2026
2c74313
simplified engine API
asmyasnikov Jan 27, 2026
88e6082
Apply suggestions from code review
asmyasnikov Jan 27, 2026
f39ae4a
Delete protos/engine/engine_grpc.pb.go
asmyasnikov Jan 27, 2026
18f5368
Delete protos/engine/engine.pb.go
asmyasnikov Jan 27, 2026
8eaef3c
Delete pkg/plugin/sdk.go
asmyasnikov Jan 27, 2026
fbaf6ba
Delete pkg/engine/engine.pb.go
asmyasnikov Jan 27, 2026
ce385ae
Delete pkg/plugin/codegen.pb.go
asmyasnikov Jan 27, 2026
a024d3e
Delete examples/plugin-based-codegen/README.md
asmyasnikov Jan 27, 2026
fbd5b43
Delete examples/plugin-based-codegen/gen/rust/queries.rs
asmyasnikov Jan 27, 2026
e6a730a
docs
asmyasnikov Jan 27, 2026
c8831c7
removed example
asmyasnikov Jan 27, 2026
6d5770f
fix
asmyasnikov Jan 27, 2026
d2417e8
Update .gitignore
asmyasnikov Jan 27, 2026
c50e9c7
pb.go
asmyasnikov Jan 27, 2026
e9cc264
fix comments
asmyasnikov Jan 27, 2026
ad7bf6c
simplified plugin engine code
asmyasnikov Jan 27, 2026
5d4c8dd
sourceFiles
asmyasnikov Jan 27, 2026
131d7bb
fix
asmyasnikov Jan 27, 2026
048a64d
Apply suggestions from code review
asmyasnikov Jan 27, 2026
79621b0
removed temp file
asmyasnikov Jan 27, 2026
d9df83b
Apply suggestions from code review
asmyasnikov Jan 27, 2026
55760fc
Apply suggestions from code review
asmyasnikov Jan 27, 2026
96dfabd
Apply suggestions from code review
asmyasnikov Jan 27, 2026
85475e2
removed engine interface
asmyasnikov Jan 27, 2026
0f81f5d
merge files
asmyasnikov Jan 27, 2026
7800a42
move md doc
asmyasnikov Jan 27, 2026
f6b34f0
Apply suggestions from code review
asmyasnikov Jan 27, 2026
830767e
revert changes
asmyasnikov Jan 27, 2026
e4667d2
revert
asmyasnikov Jan 27, 2026
9b9b3ed
docs
asmyasnikov Jan 27, 2026
a8fec25
fix
asmyasnikov Jan 27, 2026
778b45c
fixes and tests
asmyasnikov Jan 28, 2026
fb7e9a6
change ParseResponse - returns multiple statements from single call
asmyasnikov Jan 28, 2026
13fc9f3
Merge branch 'sqlc-dev:main' into engine-plugin
asmyasnikov Jan 30, 2026
12ffdbb
fix
asmyasnikov Feb 1, 2026
2e280c8
Merge branch 'sqlc-dev:main' into engine-plugin
asmyasnikov Feb 5, 2026
a6a4bdb
fix doc
asmyasnikov Feb 8, 2026
2f48010
fix doc
asmyasnikov Feb 8, 2026
bd1f56e
throw error on wrong external plugin options
asmyasnikov Feb 8, 2026
d4ccb4d
Catalog from engine plugin
asmyasnikov Feb 9, 2026
b9d8139
clickhouse + YDB
asmyasnikov Feb 13, 2026
ec0503c
README
asmyasnikov Feb 13, 2026
7f8f44e
Merge branch 'sqlc-dev:main' into engine-plugin
asmyasnikov Feb 21, 2026
eedd52c
Merge branch 'sqlc-dev:main' into engine-plugin
asmyasnikov Feb 25, 2026
7b46024
Merge branch 'sqlc-dev:main' into engine-plugin
asmyasnikov Mar 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ __pycache__
.devenv*
devenv.local.nix

/bin/sqlc
251 changes: 251 additions & 0 deletions docs/howto/engine-plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
# Database Engine Plugins

sqlc supports adding custom database backends through engine plugins. This allows you to use sqlc with databases that aren't natively supported (like MyDB, CockroachDB, or other SQL-compatible databases).

## Overview

Engine plugins are external programs that implement the sqlc engine interface:
- **Process plugins** (Go): Communicate via **Protocol Buffers** over stdin/stdout
- **WASM plugins** (any language): Communicate via **JSON** over stdin/stdout

## Compatibility Guarantee

For Go process plugins, compatibility is guaranteed at **compile time**:

```go
import "github.com/sqlc-dev/sqlc/pkg/engine"
```

When you import this package:
- If your plugin compiles successfully → it's compatible with this version of sqlc
- If types change incompatibly → your plugin won't compile until you update it

The Protocol Buffer schema ensures binary compatibility. No version negotiation needed.

## Configuration

### sqlc.yaml

```yaml
version: "2"

# Define engine plugins
engines:
- name: mydb
process:
cmd: sqlc-engine-mydb
env:
- MYDB_CONNECTION_STRING

sql:
- engine: mydb # Use the MyDB engine
schema: "schema.sql"
queries: "queries.sql"
gen:
go:
package: db
out: db
```

### Configuration Options

| Field | Description |
|-------|-------------|
| `name` | Unique name for the engine (used in `sql[].engine`) |
| `process.cmd` | Command to run (must be in PATH or absolute path) |
| `wasm.url` | URL to download WASM module (`file://` or `https://`) |
| `wasm.sha256` | SHA256 checksum of the WASM module |
| `env` | Environment variables to pass to the plugin |

## Creating a Go Engine Plugin

### 1. Import the SDK

```go
import "github.com/sqlc-dev/sqlc/pkg/engine"
```

### 2. Implement the Handler

```go
package main

import (
"github.com/sqlc-dev/sqlc/pkg/engine"
)

func main() {
engine.Run(engine.Handler{
PluginName: "mydb",
PluginVersion: "1.0.0",
Parse: handleParse,
GetCatalog: handleGetCatalog,
IsReservedKeyword: handleIsReservedKeyword,
GetCommentSyntax: handleGetCommentSyntax,
GetDialect: handleGetDialect,
})
}
```

### 3. Implement Methods

#### Parse

Parses SQL text into statements with AST.

```go
func handleParse(req *engine.ParseRequest) (*engine.ParseResponse, error) {
sql := req.GetSql()
// Parse SQL using your database's parser

return &engine.ParseResponse{
Statements: []*engine.Statement{
{
RawSql: sql,
StmtLocation: 0,
StmtLen: int32(len(sql)),
AstJson: astJSON, // AST encoded as JSON bytes
},
},
}, nil
}
```

#### GetCatalog

Returns the initial catalog with built-in types and functions.

```go
func handleGetCatalog(req *engine.GetCatalogRequest) (*engine.GetCatalogResponse, error) {
return &engine.GetCatalogResponse{
Catalog: &engine.Catalog{
DefaultSchema: "public",
Name: "mydb",
Schemas: []*engine.Schema{
{
Name: "public",
Functions: []*engine.Function{
{Name: "now", ReturnType: &engine.DataType{Name: "timestamp"}},
},
},
},
},
}, nil
}
```

#### IsReservedKeyword

Checks if a string is a reserved keyword.

```go
func handleIsReservedKeyword(req *engine.IsReservedKeywordRequest) (*engine.IsReservedKeywordResponse, error) {
reserved := map[string]bool{
"select": true, "from": true, "where": true,
}
return &engine.IsReservedKeywordResponse{
IsReserved: reserved[strings.ToLower(req.GetKeyword())],
}, nil
}
```

#### GetCommentSyntax

Returns supported SQL comment syntax.

```go
func handleGetCommentSyntax(req *engine.GetCommentSyntaxRequest) (*engine.GetCommentSyntaxResponse, error) {
return &engine.GetCommentSyntaxResponse{
Dash: true, // -- comment
SlashStar: true, // /* comment */
Hash: false, // # comment
}, nil
}
```

#### GetDialect

Returns SQL dialect information for formatting.

```go
func handleGetDialect(req *engine.GetDialectRequest) (*engine.GetDialectResponse, error) {
return &engine.GetDialectResponse{
QuoteChar: "`", // Identifier quoting character
ParamStyle: "dollar", // $1, $2, ...
ParamPrefix: "$", // Parameter prefix
CastSyntax: "cast_function", // CAST(x AS type) or "double_colon" for ::
}, nil
}
```

### 4. Build and Install

```bash
go build -o sqlc-engine-mydb .
mv sqlc-engine-mydb /usr/local/bin/
```

## Protocol

### Process Plugins (Go)

Process plugins use **Protocol Buffers** for serialization:

```
sqlc → stdin (protobuf) → plugin → stdout (protobuf) → sqlc
```

The proto schema is published at `buf.build/sqlc/sqlc` in `engine/engine.proto`.

Methods are invoked as command-line arguments:
```bash
sqlc-engine-mydb parse # stdin: ParseRequest, stdout: ParseResponse
sqlc-engine-mydb get_catalog # stdin: GetCatalogRequest, stdout: GetCatalogResponse
```

### WASM Plugins

WASM plugins use **JSON** for broader language compatibility:

```
sqlc → stdin (JSON) → wasm module → stdout (JSON) → sqlc
```

## Full Example

See `examples/plugin-based-codegen/` for a complete engine plugin implementation.

## Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│ sqlc generate │
│ │
│ 1. Read sqlc.yaml │
│ 2. Find engine: mydb → look up in engines[] │
│ 3. Run: sqlc-engine-mydb parse < schema.sql │
│ 4. Get AST via protobuf on stdout │
│ 5. Generate Go code │
└─────────────────────────────────────────────────────────────────┘

Process Plugin Communication (Protobuf):

sqlc sqlc-engine-mydb
──── ────────────────
│ │
│──── spawn process ─────────────► │
│ args: ["parse"] │
│ │
│──── protobuf on stdin ─────────► │
│ ParseRequest{sql: "..."} │
│ │
│◄─── protobuf on stdout ───────── │
│ ParseResponse{statements} │
│ │
```

## See Also

- [Codegen Plugins](plugins.md) - For custom code generators
- [Configuration Reference](../reference/config.md)
- Proto schema: `protos/engine/engine.proto`
Loading
Loading