Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Added support for the database engine plugin system for extending sqlc with new databases (in addition to PostgreSQL, Dolphin (MySQL), sqlite) #4247

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
asmyasnikov wants to merge 13 commits into sqlc-dev:main
base: main
Choose a base branch
Loading
from ydb-platform:engine-plugin

Conversation

@asmyasnikov
Copy link

@asmyasnikov asmyasnikov commented Dec 28, 2025
edited
Loading

This PR resolve issue #4158

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 YDB, Clickhouse, 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:

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

version: "2"
# Define engine plugins
engines:
 - name: somedb
 process:
 cmd: sqlc-engine-somedb
 env:
 - SOMEDB_CONNECTION_STRING
sql:
 - engine: somedb # Use the SomeDB 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

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

2. Implement the Handler

package main
import (
 "github.com/sqlc-dev/sqlc/pkg/engine"
)
func main() {
 engine.Run(engine.Handler{
 PluginName: "somedb",
 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.

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.

func handleGetCatalog(req *engine.GetCatalogRequest) (*engine.GetCatalogResponse, error) {
 return &engine.GetCatalogResponse{
 Catalog: &engine.Catalog{
 DefaultSchema: "public",
 Name: "somedb",
 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.

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.

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.

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

go build -o sqlc-engine-somedb .
mv sqlc-engine-somedb /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:

sqlc-engine-somedb parse # stdin: ParseRequest, stdout: ParseResponse
sqlc-engine-somedb 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: somedb → look up in engines[] │
│ 3. Run: sqlc-engine-somedb parse < schema.sql │
│ 4. Get AST via protobuf on stdout │
│ 5. Generate Go code │
└─────────────────────────────────────────────────────────────────┘
Process Plugin Communication (Protobuf):
 sqlc sqlc-engine-somedb
 ──── ────────────────
 │ │
 │──── spawn process ─────────────► │
 │ args: ["parse"] │
 │ │
 │──── protobuf on stdin ─────────► │
 │ ParseRequest{sql: "..."} │
 │ │
 │◄─── protobuf on stdout ───────── │
 │ ParseResponse{statements} │
 │ │

@asmyasnikov asmyasnikov changed the title (削除) Added support for the database engine plugin system for extending sqlc with new databases (in addition to PostgreSQL, Dolphin, sqlite) (削除ここまで) (追記) Added support for the database engine plugin system for extending sqlc with new databases (in addition to PostgreSQL, Dolphin (MySQL), sqlite) (追記ここまで) Jan 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

1 participant

AltStyle によって変換されたページ (->オリジナル) /