snapshot of https://github.com/sqlc-dev/sqlc.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
kotlin / test (push) Has been skipped
python / test (push) Has been skipped
typescript / test (push) Has been skipped
go / build darwin/amd64 (push) Has been cancelled
go / build linux/amd64 (push) Has been cancelled
go / build windows/amd64 (push) Has been cancelled
go / build darwin/arm64 (push) Has been cancelled
go / build linux/arm64 (push) Has been cancelled
go / build windows/arm64 (push) Has been cancelled
go / test (push) Has been cancelled
go / vuln_check (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-16 02:17:34 +05:00
commit 0f4df23290
7340 changed files with 238743 additions and 0 deletions

2
docs/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
_venv
_build

View File

@@ -0,0 +1,61 @@
# Developing sqlc
## Building
For local development, install `sqlc` under an alias. We suggest `sqlc-dev`.
```
go build -o ~/go/bin/sqlc-dev ./cmd/sqlc
```
Install `sqlc-gen-json` to avoid test failure.
```
go build -o ~/go/bin/sqlc-gen-json ./cmd/sqlc-gen-json
```
## Running Tests
```
go test ./...
```
To run the tests in the examples folder, use the `examples` tag.
```
go test --tags=examples ./...
```
These tests require locally-running database instances. Run these databases
using [Docker Compose](https://docs.docker.com/compose/).
```
docker compose up -d
```
The tests use the following environment variables to connect to the
database
### For PostgreSQL
```
Variable Default Value
-------------------------
PG_HOST 127.0.0.1
PG_PORT 5432
PG_USER postgres
PG_PASSWORD mysecretpassword
PG_DATABASE dinotest
```
### For MySQL
```
Variable Default Value
-------------------------
MYSQL_HOST 127.0.0.1
MYSQL_PORT 3306
MYSQL_USER root
MYSQL_ROOT_PASSWORD mysecretpassword
MYSQL_DATABASE dinotest
```

View File

@@ -0,0 +1,71 @@
# Migrating off hosted managed databases
Starting in sqlc 1.27.0, [managed databases](../howto/managed-databases.md) will require a database server URI in the configuration file.
This guide walks you through migrating to a locally running database server.
## Run a database server locally
There are many options for running a database server locally, but this guide
will use [Docker Compose](https://docs.docker.com/compose/), as it can support
both MySQL and PostgreSQL.
If you're using macOS and PostgreSQL, [Postgres.app](https://postgresapp.com/) is also a good option.
For MySQL, create a `docker-compose.yml` file with the following contents:
```yaml
version: "3.8"
services:
mysql:
image: "mysql/mysql-server:8.0"
ports:
- "3306:3306"
restart: always
environment:
MYSQL_DATABASE: dinotest
MYSQL_ROOT_PASSWORD: mysecretpassword
MYSQL_ROOT_HOST: '%'
```
For PostgreSQL, create a `docker-compose.yml` file with the following contents:
```yaml
version: "3.8"
services:
postgresql:
image: "postgres:16"
ports:
- "5432:5432"
restart: always
environment:
POSTGRES_DB: postgres
POSTGRES_PASSWORD: mysecretpassword
POSTGRES_USER: postgres
```
```sh
docker compose up -d
```
## Upgrade sqlc
You must be running sqlc v1.31.1 or greater to have access to the `servers`
configuration.
## Add servers to configuration
```diff
version: '2'
cloud:
project: '<PROJECT_ID>'
+ servers:
+ - name: mysql
+ uri: mysql://localhost:3306
+ - name: postgres
+ uri: postgres://localhost:5432/postgres?sslmode=disable
```
## Re-generate the code
Run `sqlc generate`. A database with the `sqlc_managed_` prefix will be automatically created and used for query analysis.

View File

@@ -0,0 +1,119 @@
# Migrating to sqlc-gen-kotlin
Starting in sqlc 1.16.0, built-in Kotlin support has been deprecated. It will
be fully removed in 1.17.0 in favor of sqlc-gen-kotlin.
This guide will walk you through migrating to the [sqlc-gen-kotlin](https://github.com/sqlc-dev/sqlc-gen-kotlin) plugin,
which involves three steps.
1. Add the sqlc-gen-kotlin plugin
2. Migrate each package
3. Re-generate the code
## Add the sqlc-gen-kotlin plugin
In your configuration file, add a `plugins` array if you don't have one
already. Add the following configuration for the plugin:
```json
{
"version": "2",
"plugins": [
{
"name": "kt",
"wasm": {
"url": "https://downloads.sqlc.dev/plugin/sqlc-gen-kotlin_1.0.0.wasm",
"sha256": "7620dc5d462de41fdc90e2011232c842117b416c98fd5c163d27c5738431a45c"
}
}
]
}
```
```yaml
version: "2"
plugins:
- name: "kt"
wasm:
url: "https://downloads.sqlc.dev/plugin/sqlc-gen-kotlin_1.0.0.wasm"
sha256: "7620dc5d462de41fdc90e2011232c842117b416c98fd5c163d27c5738431a45c"
```
## Migrate each package
Your package configuration should currently looks something like this for JSON.
```json
"sql": [
{
"schema": "schema.sql",
"queries": "query.sql",
"engine": "postgresql",
"gen": {
"kotlin": {
"out": "src/main/kotlin/com/example/foo",
"package": "com.example.foo"
}
}
}
]
```
Or this if you're using YAML.
```yaml
sql:
- schema: "schema.sql"
queries: "query.sql"
engine: "postgresql"
gen:
kotlin:
out: "src/main/kotlin/com/example/foo"
package: "com.example.foo"
```
To use the plugin, you'll need to replace the `gen` mapping with the `codegen`
collection. Add the `plugin` field, setting it to `kt`. All fields other than
`out` need to be moved into the `options` mapping.
After you're done, it should look like this for JSON.
```json
"sql": [
{
"schema": "schema.sql",
"queries": "query.sql",
"engine": "postgresql",
"codegen": [
{
"out": "src/main/kotlin/com/example/foo",
"plugin": "kt",
"options": {
"package": "com.example.foo"
}
}
]
}
]
```
Or this for YAML.
```yaml
sql:
- schema: "schema.sql"
queries: "query.sql"
engine: "postgresql"
codegen:
- plugin: "kt"
out: "src/main/kotlin/com/example/foo"
options:
package: "com.example.foo"
```
## Re-generate the code
Run `sqlc generate`. The plugin will produce the same output, so you shouldn't
see any changes. The first time `sqlc generate` is run, the plugin must be
downloaded and compiled, resulting in a slightly longer runtime. Subsequent
`generate` calls will be fast.

View File

@@ -0,0 +1,131 @@
# Migrating to sqlc-gen-python
Starting in sqlc 1.16.0, built-in Python support has been deprecated. It will
be fully removed in 1.17.0 in favor of sqlc-gen-python.
This guide will walk you through migrating to the [sqlc-gen-python](https://github.com/sqlc-dev/sqlc-gen-python) plugin,
which involves three steps.
1. Add the sqlc-gen-python plugin
2. Migrate each package
3. Re-generate the code
## Add the sqlc-gen-python plugin
In your configuration file, add a `plugins` array if you don't have one
already. Add the following configuration for the plugin:
```json
{
"version": "2",
"plugins": [
{
"name": "py",
"wasm": {
"url": "https://downloads.sqlc.dev/plugin/sqlc-gen-python_1.0.0.wasm",
"sha256": "aca83e1f59f8ffdc604774c2f6f9eb321a2b23e07dc83fc12289d25305fa065b"
}
}
]
}
```
```yaml
version: "2"
plugins:
- name: "py"
wasm:
url: "https://downloads.sqlc.dev/plugin/sqlc-gen-python_1.0.0.wasm"
sha256: "aca83e1f59f8ffdc604774c2f6f9eb321a2b23e07dc83fc12289d25305fa065b"
```
## Migrate each package
Your package configuration should currently looks something like this for JSON.
```json
"sql": [
{
"schema": "schema.sql",
"queries": "query.sql",
"engine": "postgresql",
"gen": {
"python": {
"out": "src",
"package": "foo",
"emit_sync_querier": true,
"emit_async_querier": true,
"query_parameter_limit": 5
}
}
}
]
```
Or this if you're using YAML.
```yaml
sql:
- schema: "schema.sql"
queries: "query.sql"
engine: "postgresql"
gen:
python:
out: "src"
package: "foo"
emit_sync_querier: true
emit_async_querier: true
query_parameter_limit: 5
```
To use the plugin, you'll need to replace the `gen` mapping with the `codegen`
collection. Add the `plugin` field, setting it to `py`. All fields other than
`out` need to be moved into the `options` mapping.
After you're done, it should look like this for JSON.
```json
"sql": [
{
"schema": "schema.sql",
"queries": "query.sql",
"engine": "postgresql",
"codegen": [
{
"out": "src",
"plugin": "py",
"options": {
"package": "authors",
"emit_sync_querier": true,
"emit_async_querier": true,
"query_parameter_limit": 5
}
}
]
}
]
```
Or this for YAML.
```yaml
sql:
- schema: "schema.sql"
queries: "query.sql"
engine: "postgresql"
codegen:
- plugin: "py"
out: "src"
options:
package: "foo"
emit_sync_querier: true
emit_async_querier: true
query_parameter_limit: 5
```
## Re-generate the code
Run `sqlc generate`. The plugin will produce the same output, so you shouldn't
see any changes. The first time `sqlc generate` is run, the plugin must be
downloaded and compiled, resulting in a slightly longer runtime. Subsequent
`generate` calls will be fast.

104
docs/guides/plugins.md Normal file
View File

@@ -0,0 +1,104 @@
# Using plugins
To use plugins, you must be using [Version 2](../reference/config.md#version-2) of
the configuration file. The top-level `plugins` array defines the available
plugins.
## WASM plugins
> WASM plugins are fully sandboxed; they do not have access to the network,
> filesystem, or environment variables.
In the `codegen` section, the `out` field dictates what directory will contain
the new files. The `plugin` key must reference a plugin defined in the
top-level `plugins` map. Any `options` are serialized to a string as JSON and
passed on to the plugin itself.
```yaml
version: '2'
plugins:
- name: greeter
wasm:
url: https://github.com/sqlc-dev/sqlc-gen-greeter/releases/download/v0.1.0/sqlc-gen-greeter.wasm
sha256: afc486dac2068d741d7a4110146559d12a013fd0286f42a2fc7dcd802424ad07
sql:
- schema: schema.sql
queries: query.sql
engine: postgresql
codegen:
- out: gen
plugin: greeter
options:
lang: en-US
```
For a complete working example see the following files:
- [sqlc-gen-greeter](https://github.com/sqlc-dev/sqlc-gen-greeter)
- A WASM plugin (written in Rust) that outputs a friendly message
- [wasm_plugin_sqlc_gen_greeter](https://github.com/sqlc-dev/sqlc/tree/main/internal/endtoend/testdata/wasm_plugin_sqlc_gen_greeter)
- An example project showing how to use a WASM plugin
## Process plugins
> Process-based plugins offer minimal security. Only use plugins that you
> trust. Better yet, only use plugins that you've written yourself.
In the `codegen` section, the `out` field dictates what directory will contain
the new files. The `plugin` key must reference a plugin defined in the
top-level `plugins` map. Any `options` are serialized to a string as JSON and
passed on to the plugin itself.
```yaml
version: '2'
plugins:
- name: jsonb
process:
cmd: sqlc-gen-json
sql:
- schema: schema.sql
queries: query.sql
engine: postgresql
codegen:
- out: gen
plugin: jsonb
options:
indent: " "
filename: codegen.json
```
For a complete working example see the following files:
- [sqlc-gen-json](https://github.com/sqlc-dev/sqlc/tree/main/cmd/sqlc-gen-json)
- A process-based plugin that serializes the CodeGenRequest to JSON
- [process_plugin_sqlc_gen_json](https://github.com/sqlc-dev/sqlc/tree/main/internal/endtoend/testdata/process_plugin_sqlc_gen_json)
- An example project showing how to use a process-based plugin
- [process_plugin_sqlc_gen_json](https://github.com/sqlc-dev/sqlc/tree/main/internal/endtoend/testdata/process_plugin_format_json/)
- An example project showing how to use a process-based plugin using json
## Environment variables
By default, plugins do not inherit access to environment variables. Instead,
you can configure access on a per-variable basis. For example, if your plugin
needs the `PATH` environment variable, add `PATH` to the `env` list in the
`plugins` collection.
```yaml
version: '2'
sql:
- schema: schema.sql
queries: query.sql
engine: postgresql
codegen:
- out: gen
plugin: test
plugins:
- name: test
env:
- PATH
wasm:
url: https://github.com/sqlc-dev/sqlc-gen-test/releases/download/v0.1.0/sqlc-gen-test.wasm
sha256: 138220eae508d4b65a5a8cea555edd155eb2290daf576b7a8b96949acfeb3790
```
A variable named `SQLC_VERSION` is always included in the plugin's
environment, set to the version of the `sqlc` executable invoking it.

55
docs/guides/privacy.md Normal file
View File

@@ -0,0 +1,55 @@
# Privacy and data collection
These days, it feels like every piece of software is tracking you. From your
browser, to your phone, to your terminal, programs collect as much data about
you as possible and send it off to the cloud for analysis.
We believe the best way to keep data safe is to never collect it in the first
place.
## Our Privacy Pledge
The `sqlc` command line tool does not collect any information. It
does not send crash reports to a third-party. It does not gather anonymous
aggregate user behaviour analytics.
No analytics.
No finger-printing.
No tracking.
Not now and not in the future.
### Distribution Channels
We distribute sqlc using popular package managers such as
[Homebrew](https://brew.sh/) and [Snapcraft](https://snapcraft.io/). These
package managers and their associated command-line tools do collect usage
metrics.
We use these services to make it easy to for users to install sqlc. There will
always be an option to download sqlc from a stable URL.
## Hosted Services
We provide a few hosted services in addition to the sqlc command line tool.
### sqlc.dev
* Hosted on [GitHub Pages](https://pages.github.com/)
* Analytics with [Plausible](https://plausible.io/privacy-focused-web-analytics)
### docs.sqlc.dev
* Hosted on [Read the Docs](https://readthedocs.org/)
* Analytics with [Plausible](https://plausible.io/privacy-focused-web-analytics)
### play.sqlc.dev
* Hosted on [Heroku](https://heroku.com)
* Playground data stored in [Google Cloud Storage](https://cloud.google.com/storage)
* Automatically deleted after 30 days
### app.sqlc.dev / api.sqlc.dev
* Hosted on [Heroku](https://heroku.com)
* Error tracking and tracing with [Sentry](https://sentry.io)

View File

@@ -0,0 +1,125 @@
# Using Go and pgx
> [!NOTE]
> `pgx/v5` is supported starting from v1.18.0.
pgx is a pure Go driver and toolkit for PostgreSQL. It's become the default
PostgreSQL package for many Gophers since lib/pq was put into maintenance mode.
## Getting started
To start generating code that uses pgx, set the `sql_package` field in
your `sqlc.yaml` configuration file. Valid options are `pgx/v4` or
`pgx/v5`
```yaml
version: "2"
sql:
- engine: "postgresql"
queries: "query.sql"
schema: "query.sql"
gen:
go:
package: "db"
sql_package: "pgx/v5"
out: "db"
```
If you don't have an existing sqlc project on hand, create a directory with the
configuration file above and the following `query.sql` file.
```sql
CREATE TABLE authors (
id BIGSERIAL PRIMARY KEY,
name text NOT NULL,
bio text
);
-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = $1 LIMIT 1;
-- name: ListAuthors :many
SELECT * FROM authors
ORDER BY name;
-- name: CreateAuthor :one
INSERT INTO authors (
name, bio
) VALUES (
$1, $2
)
RETURNING *;
-- name: DeleteAuthor :exec
DELETE FROM authors
WHERE id = $1;
```
Generating the code will now give you pgx-compatible database access methods.
```bash
sqlc generate
```
## Generated code walkthrough
The generated code is very similar to the code generated when using
`lib/pq`. However, instead of using `database/sql`, the code uses
pgx types directly.
```go
package main
import (
"context"
"fmt"
"os"
"github.com/jackc/pgx/v5"
"example.com/sqlc-tutorial/db"
)
func main() {
// urlExample := "postgres://username:password@localhost:5432/database_name"
conn, err := pgx.Connect(context.Background(), os.Getenv("DATABASE_URL"))
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
os.Exit(1)
}
defer conn.Close(context.Background())
q := db.New(conn)
author, err := q.GetAuthor(context.Background(), 1)
if err != nil {
fmt.Fprintf(os.Stderr, "GetAuthor failed: %v\n", err)
os.Exit(1)
}
fmt.Println(author.Name)
}
```
> [!NOTE]
> For production applications, consider using pgxpool for connection pooling:
>
> ```go
> import (
> "github.com/jackc/pgx/v5/pgxpool"
> "example.com/sqlc-tutorial/db"
> )
>
> func main() {
> pool, err := pgxpool.New(context.Background(), os.Getenv("DATABASE_URL"))
> if err != nil {
> fmt.Fprintf(os.Stderr, "Unable to create connection pool: %v\n", err)
> os.Exit(1)
> }
> defer pool.Close()
>
> q := db.New(pool)
> // Use q the same way as with single connections
> }
> ```

129
docs/howto/analyze.md Normal file
View File

@@ -0,0 +1,129 @@
# `analyze` - Analyzing query result types
> [!NOTE]
> `analyze` is in beta. Its flags and JSON output may change in a
> future release, and the types it reports can differ from the ones
> `generate` produces.
`sqlc analyze` analyzes a query against a schema and prints the inferred result
columns and parameters as a single JSON document.
Unlike [`generate`](generate.md), this command does not require a configuration
file and does not connect to a database. It uses sqlc's native static analysis
to infer types directly from the provided schema.
Every dialect is analyzed by the same engine-neutral analysis core: the schema
is loaded into a catalog seeded with the dialect's types, operators and
functions, and each query is resolved against it. `generate` still uses each
engine's own analysis path, so the two can report a type differently — most
visibly, `analyze` reports type names as the catalog stores them, in lower
case.
## Usage
```sh
sqlc analyze --dialect <dialect> --schema <schema-file> [query-file]
```
The query is read from the given file, or from standard input when no file is
provided. The schema is always read from the `--schema` file.
## Flags
- `--dialect`, `-d` - The SQL dialect to use. One of `postgresql`, `mysql`,
`sqlite`, `clickhouse`, `googlesql`, `mssql`, or `duckdb`. Required.
- `--schema`, `-s` - Path to the schema (DDL) file. Required.
- `--ast` - Include each statement's AST in the output. Defaults to `false`.
## Examples
Given a schema in `schema.sql`:
```sql
CREATE TABLE authors (
id BIGSERIAL PRIMARY KEY,
name text NOT NULL,
bio text
);
```
and a query in `query.sql`:
```sql
-- name: GetAuthor :one
SELECT * FROM authors WHERE id = $1;
```
Running:
```sh
sqlc analyze --dialect postgresql --schema schema.sql query.sql
```
reports the result columns and parameters:
```json
[
{
"name": "GetAuthor",
"cmd": ":one",
"columns": [
{
"name": "id",
"type": {
"name": "bigint"
},
"table": "authors"
},
{
"name": "name",
"type": {
"name": "text"
},
"table": "authors"
},
{
"name": "bio",
"type": {
"name": "text",
"nullable": true
},
"table": "authors"
}
],
"params": [
{
"number": 1,
"column": {
"name": "id",
"type": {
"name": "bigint"
},
"table": "authors"
}
}
]
}
]
```
A column's `type` is written as a call expression: a `name` applied to
`args`, each of which carries an optional `label` and exactly one of `type`,
`int`, `bool`, `string` or `ident`, with `nullable` set at whatever depth it
applies. A `numeric(10,2)` column is `numeric` applied to `10` and `2`; an
array of text is `array` applied to `text`, and an array of arrays nests
one `array` per dimension; a `Map(String, Nullable(UInt8))` in ClickHouse is
`map` applied to `string` and a nullable `uint8`; a `STRUCT<a INT64>` in
GoogleSQL is `struct` applied to an `int64` labelled `a`; the `MAX` of SQL
Server's `nvarchar(max)` is the identifier `max`.
Types are reported the way the engine itself stores and reports them rather
than the way the schema spelled them: PostgreSQL's `int` and `bigserial` are
`integer` and `bigint`, as `format_type` prints them; MySQL's `BOOLEAN` is
`tinyint(1)`; ClickHouse's `Decimal32(4)` is `decimal(9, 4)`; DuckDB's
`TEXT` is `varchar`; SQL Server's `FLOAT(24)` is `real`. SQLite, which
keeps a declared type as written, is reported as written.
Pass `--ast` to also include each statement's parsed AST under an `ast` key. It
has the same shape as the output of [`parse`](parse.md), with every node tagged
by type.

159
docs/howto/ci-cd.md Normal file
View File

@@ -0,0 +1,159 @@
# Using sqlc in CI/CD
If your project has more than a single developer, we suggest running `sqlc` as
part of your CI/CD pipeline. The four subcommands you'll want to run are `diff`,
`vet`, `verify` and `push`
`sqlc diff` ensures that your generated code is up to date. New developers to a
project may forget to run `sqlc generate` after adding a query or updating a
schema. They also might edit generated code. `sqlc diff` will catch both errors
by comparing the expected output from `sqlc generate` to what's on disk.
```diff
% sqlc diff
--- a/postgresql/query.sql.go
+++ b/postgresql/query.sql.go
@@ -55,7 +55,7 @@
const listAuthors = `-- name: ListAuthors :many
SELECT id, name, bio FROM authors
-ORDER BY name
+ORDER BY bio
`
```
`sqlc vet` runs a set of lint rules against your SQL queries. These rules are
helpful in catching anti-patterns before they make it into production. Please
see the [vet](vet.md) documentation for a complete guide to adding lint rules
for your project.
`sqlc verify` ensures that schema changes do not break production. Existing
queries are checked against new schema changes for correctness. Please see the
[verify](verify.md) documentation for a complete guide.
`sqlc push` pushes your database schema, queries and configuration to sqlc
Cloud. These archives are used by `verify` to catch breaking changes to your
database schema. Learn more about uploading projects [here](push.md)
## General setup
Install `sqlc` using the [suggested instructions](../overview/install.md).
Create three steps in your pipeline for `sqlc diff`, `sqlc vet`, and `sqlc
verify`. Run `sqlc push` after merge on your `main` branch.
## GitHub Actions
We provide the [setup-sqlc](https://github.com/marketplace/actions/setup-sqlc)
GitHub Action to install `sqlc`. The action uses the built-in
[tool-cache](https://github.com/actions/toolkit/blob/main/packages/tool-cache/README.md)
to speed up the installation process.
### diff
The following GitHub Workflow configuration runs `sqlc diff` on every push.
```yaml
name: sqlc
on: [push]
jobs:
diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: sqlc-dev/setup-sqlc@v3
with:
sqlc-version: '1.31.1'
- run: sqlc diff
```
### vet
The following GitHub Workflow configuration runs [sqlc vet](vet.md) on every push.
You can use `sqlc vet` without a database connection, but you'll need one if your
`sqlc` configuration references the built-in `sqlc/db-prepare` lint rule.
```yaml
name: sqlc
on: [push]
jobs:
vet:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: sqlc-dev/setup-sqlc@v3
with:
sqlc-version: '1.31.1'
# Start a PostgreSQL server
- uses: sqlc-dev/action-setup-postgres@master
with:
postgres-version: "16"
id: postgres
- run: sqlc vet
env:
POSTGRESQL_SERVER_URI: ${{ steps.postgres.outputs.connection-uri }}?sslmode=disable
```
### push
> [!NOTE]
> Pushing a project is powered by [sqlc Cloud](https://dashboard.sqlc.dev). Sign up for [free](https://dashboard.sqlc.dev) today.
The following GitHub Workflow configuration runs [sqlc push](push.md) on
every push to `main`. Create an auth token via the
[dashboard](https://dashboard.sqlc.dev).
```yaml
name: sqlc
on: [push]
jobs:
push:
runs-on: ubuntu-latest
if: ${{ github.ref == 'refs/heads/main' }}
steps:
- uses: actions/checkout@v3
- uses: sqlc-dev/setup-sqlc@v3
with:
sqlc-version: '1.31.1'
- run: sqlc push
env:
SQLC_AUTH_TOKEN: ${{ secrets.SQLC_AUTH_TOKEN }}
```
### verify
> [!NOTE]
> Verify database migrations is powered by [sqlc Cloud](https://dashboard.sqlc.dev). Sign up for [free](https://dashboard.sqlc.dev) today.
```yaml
name: sqlc
on: [push]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: sqlc-dev/setup-sqlc@v3
with:
sqlc-version: '1.31.1'
- uses: sqlc-dev/action-setup-postgres@master
with:
postgres-version: "16"
id: postgres
- run: sqlc verify
env:
POSTGRESQL_SERVER_URI: ${{ steps.postgres.outputs.connection-uri }}?sslmode=disable
SQLC_AUTH_TOKEN: ${{ secrets.SQLC_AUTH_TOKEN }}
push:
runs-on: ubuntu-latest
if: ${{ github.ref == 'refs/heads/main' }}
steps:
- uses: sqlc-dev/setup-sqlc@v3
with:
sqlc-version: '1.31.1'
- run: sqlc push
env:
SQLC_AUTH_TOKEN: ${{ secrets.SQLC_AUTH_TOKEN }}
``````

232
docs/howto/ddl.md Normal file
View File

@@ -0,0 +1,232 @@
# Modifying the database schema
sqlc parses `CREATE TABLE` and `ALTER TABLE` statements in order to generate
the necessary code.
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
birth_year int NOT NULL
);
ALTER TABLE authors ADD COLUMN bio text NOT NULL;
ALTER TABLE authors DROP COLUMN birth_year;
ALTER TABLE authors RENAME TO writers;
```
```go
package db
type Writer struct {
ID int
Bio string
}
```
## Handling SQL migrations
sqlc does not perform database migrations for you. However, sqlc is able to
differentiate between up and down migrations. sqlc ignores down migrations when
parsing SQL files.
sqlc supports parsing migrations from the following tools:
- [atlas](https://github.com/ariga/atlas)
- [dbmate](https://github.com/amacneil/dbmate)
- [golang-migrate](https://github.com/golang-migrate/migrate)
- [goose](https://github.com/pressly/goose)
- [sql-migrate](https://github.com/rubenv/sql-migrate)
- [tern](https://github.com/jackc/tern)
To enable migration parsing, specify the migration directory instead of a schema file:
```yaml
version: "2"
sql:
- engine: "postgresql"
queries: "query.sql"
schema: "db/migrations"
gen:
go:
package: "tutorial"
out: "tutorial"
```
### atlas
```sql
-- Create "post" table
CREATE TABLE "public"."post" ("id" integer NOT NULL, "title" text NULL, "body" text NULL, PRIMARY KEY ("id"));
```
```go
package db
type Post struct {
ID int
Title sql.NullString
Body sql.NullString
}
```
### dbmate
```sql
-- migrate:up
CREATE TABLE foo (bar INT NOT NULL);
-- migrate:down
DROP TABLE foo;
```
```go
package db
type Foo struct {
Bar int32
}
```
### golang-migrate
**Warning:**
[golang-migrate interprets](https://github.com/golang-migrate/migrate/blob/master/MIGRATIONS.md#migration-filename-format)
migration filenames numerically. However, sqlc parses migration files in
lexicographic order. If you choose to have sqlc enumerate your migration files,
make sure their numeric ordering matches their lexicographic ordering to avoid
unexpected behavior. This can be done by prepending enough zeroes to the
migration filenames.
This doesn't work as intended.
```
1_initial.up.sql
...
9_foo.up.sql
# this migration file will be parsed BEFORE 9_foo
10_bar.up.sql
```
This worked as intended.
```
001_initial.up.sql
...
009_foo.up.sql
010_bar.up.sql
```
In `20060102.up.sql`:
```sql
CREATE TABLE post (
id int NOT NULL,
title text,
body text,
PRIMARY KEY(id)
);
```
In `20060102.down.sql`:
```sql
DROP TABLE post;
```
```go
package db
type Post struct {
ID int
Title sql.NullString
Body sql.NullString
}
```
### goose
**Warning:**
sqlc parses migration files in lexicographic order. **If you are using numeric filenames for migrations in Goose and you choose to have sqlc enumerate your migration files**,
make sure their numeric ordering matches their lexicographic ordering to avoid
unexpected behavior. This can be done by prepending enough zeroes to the
migration filenames.
This doesn't work as intended.
```
1_initial.sql
...
9_foo.sql
# this migration file will be parsed BEFORE 9_foo
10_bar.sql
```
This worked as intended.
```
001_initial.sql
...
009_foo.sql
010_bar.sql
```
```sql
-- +goose Up
CREATE TABLE post (
id int NOT NULL,
title text,
body text,
PRIMARY KEY(id)
);
-- +goose Down
DROP TABLE post;
```
```go
package db
type Post struct {
ID int
Title sql.NullString
Body sql.NullString
}
```
### sql-migrate
```sql
-- +migrate Up
-- SQL in section 'Up' is executed when this migration is applied
CREATE TABLE people (id int);
-- +migrate Down
-- SQL section 'Down' is executed when this migration is rolled back
DROP TABLE people;
```
```go
package db
type People struct {
ID int32
}
```
### tern
```sql
CREATE TABLE comment (id int NOT NULL, text text NOT NULL);
---- create above / drop below ----
DROP TABLE comment;
```
```go
package db
type Comment struct {
ID int32
Text string
}
```

52
docs/howto/delete.md Normal file
View File

@@ -0,0 +1,52 @@
# Deleting rows
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
bio text NOT NULL
);
```
The parameter syntax varies by database engine:
**PostgreSQL:**
```sql
-- name: DeleteAuthor :exec
DELETE FROM authors WHERE id = $1;
```
**MySQL and SQLite:**
```sql
-- name: DeleteAuthor :exec
DELETE FROM authors WHERE id = ?;
```
```go
package db
import (
"context"
"database/sql"
)
type DBTX interface {
ExecContext(context.Context, string, ...any) (sql.Result, error)
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
const deleteAuthor = `-- name: DeleteAuthor :exec
DELETE FROM authors WHERE id = $1
`
func (q *Queries) DeleteAuthor(ctx context.Context, id int) error {
_, err := q.db.ExecContext(ctx, deleteAuthor, id)
return err
}
```

61
docs/howto/embedding.md Normal file
View File

@@ -0,0 +1,61 @@
# Embedding structs
Embedding allows you to reuse existing model structs in more queries, resulting
in less manual serialization work. First, imagine we have the following schema
with students and test scores.
```sql
CREATE TABLE students (
id bigserial PRIMARY KEY,
name text NOT NULL,
age integer NOT NULL
);
CREATE TABLE test_scores (
student_id bigint NOT NULL,
score integer NOT NULL,
grade text NOT NULL
);
```
We want to select the student record and the scores they got on a test.
Here's how we'd usually do that:
```sql
-- name: ScoreAndTests :many
SELECT students.*, test_scores.*
FROM students
JOIN test_scores ON test_scores.student_id = students.id
WHERE students.id = $1;
```
When using Go, sqlc will produce a struct like this:
```go
type ScoreAndTestsRow struct {
ID int64
Name string
Age int32
StudentID int64
Score int32
Grade string
}
```
With embedding, the struct will contain a model for both tables instead of a
flattened list of columns.
```sql
-- name: ScoreAndTests :many
SELECT sqlc.embed(students), sqlc.embed(test_scores)
FROM students
JOIN test_scores ON test_scores.student_id = students.id
WHERE students.id = $1;
```
```
type ScoreAndTestsRow struct {
Student Student
TestScore TestScore
}
```

74
docs/howto/fmt.md Normal file
View File

@@ -0,0 +1,74 @@
# `fmt` - Formatting queries
> [!NOTE]
> `fmt` is in beta. It rewrites your query files in place, so commit
> or back them up first. The formatting it produces may change in a
> future release.
`sqlc fmt` rewrites the query files referenced by your configuration file in a
canonical format. Each query is parsed with the engine's parser and printed
back from the syntax tree, so formatting never depends on how the query was
written — only on what it means. PostgreSQL, MySQL and SQLite are supported;
query files for other engines are left unchanged.
Like `gofmt`, the formatter does not impose a maximum line width. A statement
written on a single line stays on a single line, and a statement the author
broke across lines keeps its breaks: the printer notices which clause
boundaries (`FROM`, `WHERE`, `ORDER BY`, ...) and list boundaries the author
broke at and preserves them, normalizing indentation and spacing around them.
Comments inside a statement are formatted along with it: each comment is
anchored to the code around it by source position and printed back there —
a comment trailing a select-list item stays with that item, a comment above
a clause stays above its keyword — and a comment that runs to the end of its
line breaks the statement open around it. Any statement that cannot be
proven to survive formatting unchanged is left exactly as written.
## Usage
```sh
sqlc fmt [--diff]
```
Without flags, the query files are rewritten in place. With `--diff`, the
changes are printed to standard output instead and no files are modified.
## Examples
Given this query file:
```sql
-- name: GetAuthor :one
select id,name , bio
from authors
where id = ? limit 1;
-- name: SearchAuthors :many
SELECT id, -- the primary key
name, bio, created_at FROM authors WHERE name LIKE ? AND bio IS NOT NULL AND id > ? AND created_at > ? AND name <> ? ORDER BY name;
```
running `sqlc fmt` rewrites it to:
```sql
-- name: GetAuthor :one
SELECT id, name, bio
FROM authors
WHERE id = ?
LIMIT 1;
-- name: SearchAuthors :many
SELECT
id, -- the primary key
name,
bio,
created_at
FROM authors
WHERE name LIKE ? AND bio IS NOT NULL AND id > ? AND created_at > ? AND name <> ?
ORDER BY name;
```
`GetAuthor` keeps the line breaks its author wrote; had it been written on
one line, it would stay on one line. In `SearchAuthors`, the line comment
cannot share a line with the code after it, so the statement breaks open
around it, while the `WHERE` chain — written on one line — stays on one.

76
docs/howto/generate.md Normal file
View File

@@ -0,0 +1,76 @@
# `generate` - Generating code
`sqlc generate` parses SQL, analyzes the results, and outputs code. Your schema and queries are stored in separate SQL files. The paths to these files live in a `sqlc.yaml` configuration file.
```yaml
version: "2"
sql:
- engine: "postgresql"
queries: "query.sql"
schema: "schema.sql"
gen:
go:
package: "tutorial"
out: "tutorial"
sql_package: "pgx/v5"
```
We've written extensive docs on [retrieving](select.md), [inserting](insert.md),
[updating](update.md), and [deleting](delete.md) rows.
By default, sqlc runs its analysis using a built-in query analysis engine. While fast, this engine can't handle some complex queries and type-inference.
You can configure sqlc to use a database connection for enhanced analysis using metadata from that database.
The database-backed analyzer currently supports PostgreSQL, with [MySQL](https://github.com/sqlc-dev/sqlc/issues/2902) and [SQLite](https://github.com/sqlc-dev/sqlc/issues/2903)
support planned in the future.
## Enhanced analysis with managed databases
With [managed databases](managed-databases.md) configured, `generate` will automatically create a hosted ephemeral database with your
schema and use that database to improve its query analysis. And sqlc will cache its analysis locally
on a per-query basis to speed up future `generate` runs. This saves you the trouble of running and maintaining a database with
an up-to-date schema. Here's a minimal working configuration:
```yaml
version: "2"
servers:
- engine: postgresql
uri: "postgres://locahost:5432/postgres?sslmode=disable"
sql:
- engine: "postgresql"
queries: "query.sql"
schema: "schema.sql"
database:
managed: true
gen:
go:
out: "db"
sql_package: "pgx/v5"
```
## Enhanced analysis using your own database
You can opt-in to database-backed analysis using your own database, by providing a `uri` in your sqlc
[database](../reference/config.md#database) configuration.
The `uri` string can contain references to environment variables using the `${...}`
syntax. In the following example, the connection string will have the value of
the `PG_PASSWORD` environment variable set as its password.
```yaml
version: "2"
sql:
- engine: "postgresql"
queries: "query.sql"
schema: "schema.sql"
database:
uri: "postgres://postgres:${PG_PASSWORD}@localhost:5432/postgres"
gen:
go:
out: "db"
sql_package: "pgx/v5"
```
Databases configured with a `uri` must have an up-to-date schema for query analysis to work correctly, and `sqlc` does not apply schema migrations your database. Use your migration tool of choice to create the necessary
tables and objects before running `sqlc generate`.

238
docs/howto/insert.md Normal file
View File

@@ -0,0 +1,238 @@
# Inserting rows
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
bio text NOT NULL
);
```
The parameter syntax varies by database engine:
**PostgreSQL:**
```sql
-- name: CreateAuthor :exec
INSERT INTO authors (bio) VALUES ($1);
```
**MySQL and SQLite:**
```sql
-- name: CreateAuthor :exec
INSERT INTO authors (bio) VALUES (?);
```
```go
package db
import (
"context"
"database/sql"
)
type DBTX interface {
ExecContext(context.Context, string, ...any) (sql.Result, error)
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
const createAuthor = `-- name: CreateAuthor :exec
INSERT INTO authors (bio) VALUES ($1)
`
func (q *Queries) CreateAuthor(ctx context.Context, bio string) error {
_, err := q.db.ExecContext(ctx, createAuthor, bio)
return err
}
```
## Returning columns from inserted rows
sqlc has full support for the `RETURNING` statement.
```sql
-- Example queries for sqlc
CREATE TABLE authors (
id BIGSERIAL PRIMARY KEY,
name text NOT NULL,
bio text
);
```
**PostgreSQL:**
```sql
-- name: CreateAuthor :one
INSERT INTO authors (
name, bio
) VALUES (
$1, $2
)
RETURNING *;
-- name: CreateAuthorAndReturnId :one
INSERT INTO authors (
name, bio
) VALUES (
$1, $2
)
RETURNING id;
```
**SQLite (with RETURNING support):**
```sql
-- name: CreateAuthor :one
INSERT INTO authors (
name, bio
) VALUES (
?, ?
)
RETURNING *;
-- name: CreateAuthorAndReturnId :one
INSERT INTO authors (
name, bio
) VALUES (
?, ?
)
RETURNING id;
```
Note: MySQL does not support the `RETURNING` clause. Use `:execresult` instead to get the last insert ID.
```go
package db
import (
"context"
"database/sql"
)
const createAuthor = `-- name: CreateAuthor :one
INSERT INTO authors (
name, bio
) VALUES (
$1, $2
)
RETURNING id, name, bio
`
type CreateAuthorParams struct {
Name string
Bio sql.NullString
}
func (q *Queries) CreateAuthor(ctx context.Context, arg CreateAuthorParams) (Author, error) {
row := q.db.QueryRowContext(ctx, createAuthor, arg.Name, arg.Bio)
var i Author
err := row.Scan(&i.ID, &i.Name, &i.Bio)
return i, err
}
const createAuthorAndReturnId = `-- name: CreateAuthorAndReturnId :one
INSERT INTO authors (
name, bio
) VALUES (
$1, $2
)
RETURNING id
`
type CreateAuthorAndReturnIdParams struct {
Name string
Bio sql.NullString
}
func (q *Queries) CreateAuthorAndReturnId(ctx context.Context, arg CreateAuthorAndReturnIdParams) (int64, error) {
row := q.db.QueryRowContext(ctx, createAuthorAndReturnId, arg.Name, arg.Bio)
var id int64
err := row.Scan(&id)
return id, err
}
```
## Using CopyFrom
### PostgreSQL
PostgreSQL supports the [COPY protocol](https://www.postgresql.org/docs/current/sql-copy.html) that can insert rows a lot faster than sequential inserts. You can use this easily with sqlc:
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
name text NOT NULL,
bio text NOT NULL
);
-- name: CreateAuthors :copyfrom
INSERT INTO authors (name, bio) VALUES ($1, $2);
```
```go
type CreateAuthorsParams struct {
Name string
Bio string
}
func (q *Queries) CreateAuthors(ctx context.Context, arg []CreateAuthorsParams) (int64, error) {
...
}
```
The `:copyfrom` command requires either `pgx/v4` or `pgx/v5`.
```yaml
version: "2"
sql:
- engine: "postgresql"
queries: "query.sql"
schema: "query.sql"
gen:
go:
package: "db"
sql_package: "pgx/v5"
out: "db"
```
### MySQL
MySQL supports a similar feature using [LOAD DATA](https://dev.mysql.com/doc/refman/8.0/en/load-data.html).
Errors and duplicate keys are treated as warnings and insertion will
continue, even without an error for some cases. Use this in a transaction
and use SHOW WARNINGS to check for any problems and roll back if necessary.
Check the [error handling](https://dev.mysql.com/doc/refman/8.0/en/load-data.html#load-data-error-handling) documentation for more information.
```sql
CREATE TABLE foo (a text, b integer, c DATETIME, d DATE);
-- name: InsertValues :copyfrom
INSERT INTO foo (a, b, c, d) VALUES (?, ?, ?, ?);
```
```go
func (q *Queries) InsertValues(ctx context.Context, arg []InsertValuesParams) (int64, error) {
...
}
```
The `:copyfrom` command requires setting the `sql_package` and `sql_driver` options.
```yaml
version: "2"
sql:
- engine: "mysql"
queries: "query.sql"
schema: "query.sql"
gen:
go:
package: "db"
sql_package: "database/sql"
sql_driver: "github.com/go-sql-driver/mysql"
out: "db"
```

View File

@@ -0,0 +1,101 @@
# Managed databases
*Added in v1.22.0*
`sqlc` can automatically create read-only databases to power query analysis,
linting and verification. These databases are immediately useful for powering
sqlc's database-connected query analyzer, an opt-in feature that improves upon
sqlc's built-in query analysis engine. PostgreSQL support is available today,
with MySQL on the way.
Once configured, `sqlc` will also use managed databases when linting queries
with [`sqlc vet`](vet.md) in cases where your lint rules require a connection
to a running database.
Managed databases are under active development, and we're interested in
supporting other use-cases.
## Configuring managed databases
To configure `sqlc` to use managed databases, remove the `uri` key from your
`database` configuration and replace it with the `managed` key set to `true`.
Access to a running database server is required. Add a connection string to the `servers` mapping.
```yaml
version: '2'
servers:
- engine: postgresql
uri: "postgres://localhost:5432/postgres?sslmode=disable"
sql:
- schema: schema.sql
queries: query.sql
engine: postgresql
database:
managed: true
```
An environment variable can also be used via the `${}` syntax.
```yaml
version: '2'
servers:
- engine: postgresql
uri: ${DATABASE_URI}
sql:
- schema: schema.sql
queries: query.sql
engine: postgresql
database:
managed: true
```
## Improving codegen
Without a database connection, sqlc does its best to parse, analyze and compile your queries just using
the schema you pass it and what it knows about the various database engines it supports. In many cases
this works just fine, but for more advanced queries sqlc might not have enough information to produce good code.
With managed databases configured, `sqlc generate` will automatically create a hosted ephemeral database with your
schema and use that database to improve its query analysis. And sqlc will cache its analysis locally
on a per-query basis to speed up future codegen runs. Here's a minimal working configuration:
```yaml
version: '2'
servers:
- engine: postgresql
uri: "postgres://localhost:5432/postgres?sslmode=disable"
sql:
- schema: schema.sql
queries: query.sql
engine: postgresql
database:
managed: true
gen:
go:
out: "db"
```
## Linting queries
With managed databases configured, `sqlc vet` will automatically create a hosted ephemeral database with your
schema and use that database when running lint rules that require a
database connection, e.g. any [rule relying on `EXPLAIN ...` output](vet.md#rules-using-explain--output).
If you don't yet have any vet rules, the [built-in sqlc/db-prepare rule](vet.md#sqlcdb-prepare)
is a good place to start. It prepares each of your queries against the database
to ensure the query is valid. Here's a minimal working configuration:
```yaml
version: '2'
servers:
- engine: postgresql
uri: "postgres://localhost:5432/postgres?sslmode=disable"
sql:
- schema: schema.sql
queries: query.sql
engine: postgresql
database:
managed: true
rules:
- sqlc/db-prepare
```

View File

@@ -0,0 +1,93 @@
# Naming parameters
sqlc tries to generate good names for positional parameters, but sometimes it
lacks enough context. The following SQL generates parameters with less than
ideal names:
```sql
-- name: UpsertAuthorName :one
UPDATE author
SET
name = CASE WHEN $1::bool
THEN $2::text
ELSE name
END
RETURNING *;
```
```go
type UpdateAuthorNameParams struct {
Column1 bool `json:""`
Column2_2 string `json:"_2"`
}
```
In these cases, named parameters give you the control over field names on the
Params struct.
```sql
-- name: UpsertAuthorName :one
UPDATE author
SET
name = CASE WHEN sqlc.arg(set_name)::bool
THEN sqlc.arg(name)::text
ELSE name
END
RETURNING *;
```
```go
type UpdateAuthorNameParams struct {
SetName bool `json:"set_name"`
Name string `json:"name"`
}
```
If the `sqlc.arg()` syntax is too verbose for your taste, you can use the `@`
operator as a shortcut.
> [!NOTE]
> The `@` operator as a shortcut for `sqlc.arg()` is not supported in MySQL.
```sql
-- name: UpsertAuthorName :one
UPDATE author
SET
name = CASE WHEN @set_name::bool
THEN @name::text
ELSE name
END
RETURNING *;
```
## Nullable parameters
sqlc infers the nullability of any specified parameters, and often does exactly
what you want. If you want finer control over the nullability of your
parameters, you may use `sqlc.narg()` (**n**ullable arg) to override the default
behavior. Using `sqlc.narg` tells sqlc to ignore whatever nullability it has
inferred and generate a nullable parameter instead. There is no nullable
equivalent of the `@` syntax.
Here is an example that uses a single query to allow updating an author's
name, bio or both.
```sql
-- name: UpdateAuthor :one
UPDATE author
SET
name = coalesce(sqlc.narg('name'), name),
bio = coalesce(sqlc.narg('bio'), bio)
WHERE id = sqlc.arg('id')
RETURNING *;
```
The following code is generated:
```go
type UpdateAuthorParams struct {
Name sql.NullString
Bio sql.NullString
ID int64
}
```

184
docs/howto/overrides.md Normal file
View File

@@ -0,0 +1,184 @@
# Overriding types
> [!NOTE]
> Type overrides and field renaming are only fully-supported for Go.
In many cases it's useful to tell `sqlc` explicitly what Go type you want it to
use for a query input or output. For instance, by default when you use
`pgx/v5`, `sqlc` will map a PostgreSQL UUID type to `UUID` from `github.com/jackc/pgx/pgtype`.
But you may want `sqlc` to use `UUID` from `github.com/google/uuid` instead.
To tell `sqlc` to use a different Go type, add an entry to the `overrides` list in your
configuration.
`sqlc` offers two kinds of Go type overrides:
* `db_type` overrides, which override the Go type for a specific database type.
* `column` overrides, which override the Go type for a column or columns by name.
Here's an example including one of each kind:
```yaml
version: "2"
sql:
- schema: "postgresql/schema.sql"
queries: "postgresql/query.sql"
engine: "postgresql"
gen:
go:
package: "authors"
out: "db"
sql_package: "pgx/v5"
overrides:
- db_type: "uuid"
nullable: true
go_type:
import: "github.com/google/uuid"
type: "UUID"
- column: "users.birthday"
go_type: "time.Time"
```
> [!TIP]
> A single `db_type` override configuration applies to either nullable or non-nullable
> columns, but not both. If you want the same Go type to override regardless of
> nullability, you'll need to configure two overrides: one with `nullable: true` and one without.
## The `overrides` list
Each element in the `overrides` list has the following keys:
- `db_type`:
- A database type to override. Find the full list of supported types in [postgresql_type.go](https://github.com/sqlc-dev/sqlc/blob/main/internal/codegen/golang/postgresql_type.go#L12) or [mysql_type.go](https://github.com/sqlc-dev/sqlc/blob/main/internal/codegen/golang/mysql_type.go#L12). Note that for Postgres you must use pg_catalog-prefixed names where available. `db_type` and `column` are mutually exclusive.
- `column`:
- A column name to override. The value should be of the form `table.column` but you can also specify `schema.table.column` or `catalog.schema.table.column`. `column` and `db_type` are mutually exclusive.
- `go_type`:
- The fully-qualified name of a Go type to use in generated code. This is usually a string but can also be [a map](#the-go_type-map) for more complex configurations.
- `go_struct_tag`:
- A reflect-style struct tag to use in generated code, e.g. `a:"b" x:"y,z"`.
If you want `json` or `db` tags for all fields, configure `emit_json_tags` or `emit_db_tags` instead.
- `unsigned`:
- If `true`, sqlc will apply this override when a numeric column is unsigned.
Note that this only applies to `db_type` overrides and has no effect on `column` overrides.
Defaults to `false`.
- `nullable`:
- If `true`, sqlc will apply this override when a column is nullable.
Otherwise `sqlc` will apply this override when a column is non-nullable.
Note that this only applies to `db_type` overrides and has no effect on `column` overrides.
Defaults to `false`.
> [!TIP]
> A single `db_type` override configuration applies to either nullable or non-nullable
> columns, but not both. If you want the same Go type to override regardless of nullability, you'll
> need to configure two overrides: one with `nullable: true` and one without.
> [!NOTE]
> When generating code, `column` override configurations take precedence over `db_type` configurations.
### The `go_type` map
Some overrides may require more detailed configuration. If necessary, `go_type`
can be a map with the following keys:
- `import`:
- The import path for the package where the type is defined.
- `package`:
- The package name where the type is defined. This should only be necessary when your import path doesn't end with the desired package name.
- `type`:
- The type name itself, without any package prefix.
- `pointer`:
- If `true`, generated code will use a pointer to the type rather than the type itself.
- `slice`:
- If `true`, generated code will use a slice of the type rather than the type itself.
An example:
```yaml
version: "2"
sql:
- schema: "postgresql/schema.sql"
queries: "postgresql/query.sql"
engine: "postgresql"
gen:
go:
package: "authors"
out: "db"
sql_package: "pgx/v5"
overrides:
- db_type: "uuid"
go_type:
import: "a/b/v2"
package: "b"
type: "MyType"
pointer: true
```
## Global overrides
To override types in all packages that `sqlc` generates, add an override
configuration to the top-level `overrides` section of your `sqlc` config:
```yaml
version: "2"
overrides:
go:
overrides:
- db_type: "pg_catalog.timestamptz"
nullable: true
engine: "postgresql"
go_type:
import: "gopkg.in/guregu/null.v4"
package: "null"
type: "Time"
sql:
- schema: "service1/schema.sql"
queries: "service1/query.sql"
engine: "postgresql"
gen:
go:
package: "service1"
out: "service1"
- schema: "service2/schema.sql"
queries: "service2/query.sql"
engine: "postgresql"
gen:
go:
package: "service2"
out: "service2"
```
Using this configuration, whenever there is a nullable `timestamp with time zone`
column in a Postgres table, `sqlc` will generate Go code using `null.Time`.
Note that the mapping for global type overrides has a field called `engine` that
is absent in per-package type overrides. This field is only used when there are
multiple `sql` sections using different engines. If you're only generating code
for a single database engine you can omit it.
#### Version 1 configuration
If you are using the older version 1 of the `sqlc` configuration format, override
configurations themselves are unchanged but are nested differently.
Per-package configurations are nested under the `overrides` key within an item
in the `packages` list:
```yaml
version: "1"
packages:
- name: "db"
path: "internal/db"
queries: "./sql/query/"
schema: "./sql/schema/"
engine: "postgresql"
overrides: [...]
```
And global configurations are nested under the top-level `overrides` key:
```yaml
version: "1"
packages: [...]
overrides:
- db_type: "uuid"
go_type: "github.com/gofrs/uuid.UUID"
```

111
docs/howto/parse.md Normal file
View File

@@ -0,0 +1,111 @@
# `parse` - Parsing SQL into an AST
> [!NOTE]
> `parse` is in beta. Its flags and the shape of the JSON AST it
> prints may change in a future release.
`sqlc parse` parses SQL from a file or standard input and prints the abstract
syntax tree (AST) as a single JSON document. It does not require a configuration
file or a database connection.
Each statement is reported with its sqlc query name and command (when the
statement carries a [`-- name:`](../reference/query-annotations.md) annotation)
alongside its AST.
## Usage
```sh
sqlc parse --dialect <dialect> [file]
```
The SQL is read from the given file, or from standard input when no file is
provided.
## Flags
- `--dialect`, `-d` - The SQL dialect to use. One of `postgresql`, `mysql`,
`sqlite`, `clickhouse`, `googlesql`, `mssql`, or `duckdb`. Required.
## Examples
Parse a query file:
```sh
sqlc parse --dialect postgresql query.sql
```
Parse SQL piped via standard input:
```sh
echo "SELECT 1;" | sqlc parse --dialect mysql
```
The output is a JSON array with one object per statement:
```json
[
{
"name": "GetAuthor",
"cmd": ":one",
"ast": {
"tag": "RawStmt",
"stmt": {
"...": "..."
},
"stmt_location": 0,
"stmt_len": 42
}
}
]
```
Statements without a `-- name:` annotation (for example schema DDL) omit the
`name` and `cmd` fields. Field names are `snake_case` versions of the AST node
field names.
## Node types
Every node in the AST carries a `tag` naming its type. Some nodes have no
fields of their own, so without it a star, a null literal and an untranslated
clause would all print as `{}`.
```json
"val": {
"tag": "ColumnRef",
"name": "",
"fields": {
"tag": "List",
"items": [
{
"tag": "A_Star"
}
]
},
"location": 93
}
```
A `tag` of `TODO` marks a clause the dialect's converter does not translate
yet. It means the clause was parsed but is not represented in the AST, not that
the clause was absent from the query.
## Absent fields
A field the statement does not use is left out rather than printed as `null`.
An `A_Const` carrying an integer reports only what it has:
```json
"val": {
"tag": "A_Const",
"val": {
"tag": "Integer",
"ival": 1
},
"location": 30
}
```
Only absent fields — and empty lists, which engines construct differently for
the same SQL — are omitted. A zero keeps its place, because zero is a value the
parser can find: `stmt_location` is 0 for the first statement in a file, and
`LIMIT 0` parses to an `ival` of 0.

View File

@@ -0,0 +1,89 @@
# Preparing queries
If you're using `pgx/v5` you get its
[implicit support](https://github.com/jackc/pgx/wiki/Automatic-Prepared-Statement-Caching)
for prepared statements. No additional `sqlc` configuration is required.
For other drivers, `sqlc` can give you the option to explicitly use prepared
queries. These prepared queries also work with transactions.
You'll need to set `emit_prepared_queries` to `true` in your `sqlc` configuration
to generate code similar to the example below.
```sql
CREATE TABLE records (
id SERIAL PRIMARY KEY
);
-- name: GetRecord :one
SELECT * FROM records
WHERE id = $1;
```
```go
package db
import (
"context"
"database/sql"
"fmt"
)
type Record struct {
ID int32
}
type DBTX interface {
PrepareContext(context.Context, string) (*sql.Stmt, error)
QueryRowContext(context.Context, string, ...any) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
q := Queries{db: db}
var err error
if q.getRecordStmt, err = db.PrepareContext(ctx, getRecord); err != nil {
return nil, fmt.Errorf("error preparing query GetRecord: %w", err)
}
return &q, nil
}
func (q *Queries) queryRow(ctx context.Context, stmt *sql.Stmt, query string, args ...any) *sql.Row {
switch {
case stmt != nil && q.tx != nil:
return q.tx.StmtContext(ctx, stmt).QueryRowContext(ctx, args...)
case stmt != nil:
return stmt.QueryRowContext(ctx, args...)
default:
return q.db.QueryRowContext(ctx, query, args...)
}
}
type Queries struct {
db DBTX
tx *sql.Tx
getRecordStmt *sql.Stmt
}
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
return &Queries{
db: tx,
tx: tx,
getRecordStmt: q.getRecordStmt,
}
}
const getRecord = `-- name: GetRecord :one
SELECT id FROM records
WHERE id = $1
`
func (q *Queries) GetRecord(ctx context.Context, id int32) (int32, error) {
row := q.queryRow(ctx, q.getRecordStmt, getRecord, id)
err := row.Scan(&id)
return id, err
}
```

70
docs/howto/push.md Normal file
View File

@@ -0,0 +1,70 @@
# `push` - Uploading projects
> [!NOTE]
> `push` is powered by [sqlc Cloud](https://dashboard.sqlc.dev). Sign up for [free](https://dashboard.sqlc.dev) today.
*Added in v1.24.0*
We've renamed the `upload` sub-command to `push`. We've also changed the data sent along in a push request. Upload used to include the configuration file, migrations, queries, and all generated code. Push drops the generated code in favor of including the [plugin.GenerateRequest](https://buf.build/sqlc/sqlc/docs/main:plugin#plugin.GenerateRequest), which is the protocol buffer message we pass to codegen plugins.
## Add configuration
After creating a project, add the project ID to your sqlc configuration file.
```yaml
version: "2"
cloud:
project: "<PROJECT_ID>"
```
You'll also need to create an auth token and make it available via the
`SQLC_AUTH_TOKEN` environment variable.
```shell
export SQLC_AUTH_TOKEN=sqlc_xxxxxxxx
```
## Dry run
You can see what's included when uploading your project by using using the
`--dry-run` flag:
```shell
$ sqlc push --dry-run
2023/11/21 10:39:51 INFO config file=sqlc.yaml bytes=912
2023/11/21 10:39:51 INFO codegen_request queryset=app file=codegen_request.pb
2023/11/21 10:39:51 INFO schema queryset=app file=migrations/00001_initial.sql bytes=3033
2023/11/21 10:39:51 INFO query queryset=app file=queries/app.sql bytes=1150
```
The output is the files `sqlc` would have sent without the `--dry-run` flag.
## Push
Once you're ready to push, remove the `--dry-run` flag.
```shell
$ sqlc push
```
### Tags
You can provide tags to associate with a push, primarily as a convenient reference when using `sqlc verify` with the `against` argument.
Tags only refer to a single push, so if you pass an existing tag to `push` it will overwrite the previous reference.
```shell
$ sqlc push --tag main
```
### Annotations
Annotations are added to each push request. By default, we include these environment variables (if they are present).
```
GITHUB_REPOSITORY
GITHUB_REF
GITHUB_REF_NAME
GITHUB_REF_TYPE
GITHUB_SHA
```

83
docs/howto/query_count.md Normal file
View File

@@ -0,0 +1,83 @@
# Counting rows
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
hometown text NOT NULL
);
-- name: CountAuthors :one
SELECT count(*) FROM authors;
-- name: CountAuthorsByTown :many
SELECT hometown, count(*) FROM authors
GROUP BY 1
ORDER BY 1;
```
```go
package db
import (
"context"
"database/sql"
)
type DBTX interface {
QueryContext(context.Context, string, ...any) (*sql.Rows, error)
QueryRowContext(context.Context, string, ...any) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
const countAuthors = `-- name: CountAuthors :one
SELECT count(*) FROM authors
`
func (q *Queries) CountAuthors(ctx context.Context) (int, error) {
row := q.db.QueryRowContext(ctx, countAuthors)
var i int
err := row.Scan(&i)
return i, err
}
const countAuthorsByTown = `-- name: CountAuthorsByTown :many
SELECT hometown, count(*) FROM authors
GROUP BY 1
ORDER BY 1
`
type CountAuthorsByTownRow struct {
Hometown string
Count int
}
func (q *Queries) CountAuthorsByTown(ctx context.Context) ([]CountAuthorsByTownRow, error) {
rows, err := q.db.QueryContext(ctx, countAuthorsByTown)
if err != nil {
return nil, err
}
defer rows.Close()
items := []CountAuthorsByTownRow{}
for rows.Next() {
var i CountAuthorsByTownRow
if err := rows.Scan(&i.Hometown, &i.Count); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
```

122
docs/howto/rename.md Normal file
View File

@@ -0,0 +1,122 @@
# Renaming fields
Struct field names are generated from column names using a simple algorithm:
split the column name on underscores and capitalize the first letter of each
part.
```
account -> Account
spotify_url -> SpotifyUrl
app_id -> AppID
```
If you're not happy with a field's generated name, use the `rename` mapping
to pick a new name. The keys are column names and the values are the struct
field name to use.
```yaml
version: "2"
sql:
- schema: "postgresql/schema.sql"
queries: "postgresql/query.sql"
engine: "postgresql"
gen:
go:
package: "authors"
out: "postgresql"
rename:
spotify_url: "SpotifyURL"
```
## Tables
The output structs associated with tables can also be renamed. By default,
the struct name will be the singular version of the table name. For example,
the `authors` table will generate an `Author` struct and the `book_publishers`
table will generate a `BookPublisher` struct.
```sql
CREATE TABLE authors (
id BIGSERIAL PRIMARY KEY,
name text NOT NULL,
bio text
);
CREATE TABLE book_publishers (
id BIGSERIAL PRIMARY KEY,
name text NOT NULL
);
```
```go
package db
import (
"database/sql"
)
type Author struct {
ID int64
Name string
Bio sql.NullString
}
type Publisher struct {
ID int64
Name string
}
```
To rename these structs, you must use the generated struct name. In this
example, that would be `author` and `book_publisher`. Use the `rename` map to
change the name of these struct to `Writer` and `BookPublisher` (note the
camel-casing and the underscore for multi-worded tables).
```yaml
version: '1'
packages:
- path: db
engine: postgresql
schema: query.sql
queries: query.sql
rename:
author: Writer
book_publisher: Publisher
```
```yaml
version: "2"
sql:
- engine: postgresql
queries: query.sql
schema: query.sql
overrides:
go:
rename:
author: Writer
book_publisher: Publisher
```
```go
package db
import (
"database/sql"
)
type Writer struct {
ID int64
Name string
Bio sql.NullString
}
type Publisher struct {
ID int64
Name string
}
```
## Limitations
Rename mappings apply to an entire package. Therefore, a column named `foo` and
a table name `foo` can't map to different rename values.

393
docs/howto/select.md Normal file
View File

@@ -0,0 +1,393 @@
# Retrieving rows
To generate a database access method, annotate a query with a specific comment.
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
bio text NOT NULL,
birth_year int NOT NULL
);
```
The parameter syntax varies by database engine:
**PostgreSQL:**
```sql
-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = $1;
-- name: ListAuthors :many
SELECT * FROM authors
ORDER BY id;
```
**MySQL and SQLite:**
```sql
-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = ?;
-- name: ListAuthors :many
SELECT * FROM authors
ORDER BY id;
```
A few new pieces of code are generated beyond the `Author` struct. An interface
for the underlying database is generated. The `*sql.DB` and `*sql.Tx` types
satisfy this interface.
The database access methods are added to a `Queries` struct, which is created
using the `New` method.
Note that the `*` in our query has been replaced with explicit column names.
This change ensures that the query will never return unexpected data.
Our query was annotated with `:one`, meaning that it should only return a
single row. We scan the data from that one into a `Author` struct.
Since the get query has a single parameter, the `GetAuthor` method takes a single
`int` as an argument.
Since the list query has no parameters, the `ListAuthors` method accepts no
arguments.
```go
package db
import (
"context"
"database/sql"
)
type Author struct {
ID int
Bio string
BirthYear int
}
type DBTX interface {
QueryContext(context.Context, string, ...any) (*sql.Rows, error)
QueryRowContext(context.Context, string, ...any) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
const getAuthor = `-- name: GetAuthor :one
SELECT id, bio, birth_year FROM authors
WHERE id = $1
`
func (q *Queries) GetAuthor(ctx context.Context, id int) (Author, error) {
row := q.db.QueryRowContext(ctx, getAuthor, id)
var i Author
err := row.Scan(&i.ID, &i.Bio, &i.BirthYear)
return i, err
}
const listAuthors = `-- name: ListAuthors :many
SELECT id, bio, birth_year FROM authors
ORDER BY id
`
func (q *Queries) ListAuthors(ctx context.Context) ([]Author, error) {
rows, err := q.db.QueryContext(ctx, listAuthors)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Author
for rows.Next() {
var i Author
if err := rows.Scan(&i.ID, &i.Bio, &i.BirthYear); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
```
## Selecting columns
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
bio text NOT NULL,
birth_year int NOT NULL
);
-- name: GetBioForAuthor :one
SELECT bio FROM authors
WHERE id = $1;
-- name: GetInfoForAuthor :one
SELECT bio, birth_year FROM authors
WHERE id = $1;
```
When selecting a single column, only that value is returned. The `GetBioForAuthor`
method takes a single `int` as an argument and returns a `string` and an
`error`.
When selecting multiple columns, a row record (method-specific struct) is
returned. In this case, `GetInfoForAuthor` returns a struct with two fields:
`Bio` and `BirthYear`.
If a query result has no row records, a zero value and an `ErrNoRows` error are
returned instead of a zero value and `nil`. For instance, when the `GetBioForAuthor`
result has no rows, it will return `""` and `ErrNoRows`.
```go
package db
import (
"context"
"database/sql"
)
type DBTX interface {
QueryRowContext(context.Context, string, ...any) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
const getBioForAuthor = `-- name: GetBioForAuthor :one
SELECT bio FROM authors
WHERE id = $1
`
func (q *Queries) GetBioForAuthor(ctx context.Context, id int) (string, error) {
row := q.db.QueryRowContext(ctx, getBioForAuthor, id)
var i string
err := row.Scan(&i)
return i, err
}
const getInfoForAuthor = `-- name: GetInfoForAuthor :one
SELECT bio, birth_year FROM authors
WHERE id = $1
`
type GetInfoForAuthorRow struct {
Bio string
BirthYear int
}
func (q *Queries) GetInfoForAuthor(ctx context.Context, id int) (GetInfoForAuthorRow, error) {
row := q.db.QueryRowContext(ctx, getInfoForAuthor, id)
var i GetInfoForAuthorRow
err := row.Scan(&i.Bio, &i.BirthYear)
return i, err
}
```
## Passing a slice as a parameter to a query
### PostgreSQL
In PostgreSQL,
[ANY](https://www.postgresql.org/docs/current/functions-comparisons.html#id-1.5.8.28.16)
allows you to check if a value exists in an array expression. Queries using ANY
with a single parameter will generate method signatures with slices as
arguments. Use the postgres data types, eg: int, varchar, etc.
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
bio text NOT NULL,
birth_year int NOT NULL
);
-- name: ListAuthorsByIDs :many
SELECT * FROM authors
WHERE id = ANY($1::int[]);
```
The above SQL will generate the following code:
```go
package db
import (
"context"
"database/sql"
"github.com/lib/pq"
)
type Author struct {
ID int
Bio string
BirthYear int
}
type DBTX interface {
QueryContext(context.Context, string, ...any) (*sql.Rows, error)
QueryRowContext(context.Context, string, ...any) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
const listAuthors = `-- name: ListAuthorsByIDs :many
SELECT id, bio, birth_year FROM authors
WHERE id = ANY($1::int[])
`
func (q *Queries) ListAuthorsByIDs(ctx context.Context, ids []int) ([]Author, error) {
rows, err := q.db.QueryContext(ctx, listAuthors, pq.Array(ids))
if err != nil {
return nil, err
}
defer rows.Close()
var items []Author
for rows.Next() {
var i Author
if err := rows.Scan(&i.ID, &i.Bio, &i.BirthYear); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
```
### MySQL and SQLite
MySQL and SQLite differ from PostgreSQL in that placeholders must be generated based on
the number of elements in the slice you pass in. Though trivial it is still
something of a nuisance. The passed in slice must not be nil or empty or an
error will be returned (ie not a panic). The placeholder insertion location is
marked by the meta-function `sqlc.slice()` (which is similar to `sqlc.arg()`
that you see documented under [Naming parameters](named_parameters.md)).
To rephrase, the `sqlc.slice('param')` behaves identically to `sqlc.arg()` it
terms of how it maps the explicit argument to the function signature, eg:
* `sqlc.slice('ids')` maps to `ids []GoType` in the function signature
* `sqlc.slice(cust_ids)` maps to `custIds []GoType` in the function signature
(like `sqlc.arg()`, the parameter does not have to be quoted)
This feature is not compatible with `emit_prepared_queries` statement found in the
[Configuration file](../reference/config.md).
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
bio text NOT NULL,
birth_year int NOT NULL
);
-- name: ListAuthorsByIDs :many
SELECT * FROM authors
WHERE id IN (sqlc.slice('ids'));
```
The above SQL will generate the following code:
```go
package db
import (
"context"
"database/sql"
"fmt"
"strings"
)
type Author struct {
ID int
Bio string
BirthYear int
}
type DBTX interface {
ExecContext(context.Context, string, ...any) (sql.Result, error)
PrepareContext(context.Context, string) (*sql.Stmt, error)
QueryContext(context.Context, string, ...any) (*sql.Rows, error)
QueryRowContext(context.Context, string, ...any) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
return &Queries{
db: tx,
}
}
const listAuthorsByIDs = `-- name: ListAuthorsByIDs :many
SELECT id, bio, birth_year FROM authors
WHERE id IN (/*SLICE:ids*/?)
`
func (q *Queries) ListAuthorsByIDs(ctx context.Context, ids []int64) ([]Author, error) {
sql := listAuthorsByIDs
var queryParams []any
if len(ids) == 0 {
return nil, fmt.Errorf("slice ids must have at least one element")
}
for _, v := range ids {
queryParams = append(queryParams, v)
}
sql = strings.Replace(sql, "/*SLICE:ids*/?", strings.Repeat(",?", len(ids))[1:], 1)
rows, err := q.db.QueryContext(ctx, sql, queryParams...)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Author
for rows.Next() {
var i Author
if err := rows.Scan(&i.ID, &i.Bio, &i.BirthYear); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
```

53
docs/howto/structs.md Normal file
View File

@@ -0,0 +1,53 @@
# Configuring generated structs
## Naming scheme
Structs generated from tables will attempt to use the singular form of a table
name if the table name is pluralized.
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
name text NOT NULL
);
```
```go
package db
// Struct names use the singular form of table names
type Author struct {
ID int
Name string
}
```
## JSON tags
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
created_at timestamp NOT NULL
);
```
sqlc can generate structs with JSON tags by adding the `emit_json_tags` key to the configuration file as it shows on [configuration reference](../reference/config.md).
The JSON name for a field matches
the column name in the database.
```go
package db
import (
"time"
)
type Author struct {
ID int `json:"id"`
CreatedAt time.Time `json:"created_at"`
}
```
## More control
See the guide to [Overriding types](./overrides.md) for fine-grained control over struct field types and tags.

101
docs/howto/transactions.md Normal file
View File

@@ -0,0 +1,101 @@
# Using transactions
In the code generated by sqlc, the `WithTx` method allows a `Queries` instance to be associated with a transaction.
For example, with the following SQL structure:
`schema.sql`:
```sql
CREATE TABLE records (
id SERIAL PRIMARY KEY,
counter INT NOT NULL
);
```
`query.sql`
```sql
-- name: GetRecord :one
SELECT * FROM records
WHERE id = $1;
-- name: UpdateRecord :exec
UPDATE records SET counter = $2
WHERE id = $1;
```
And the generated code from sqlc in `db.go`:
```go
package tutorial
import (
"context"
"database/sql"
)
type DBTX interface {
ExecContext(context.Context, string, ...any) (sql.Result, error)
PrepareContext(context.Context, string) (*sql.Stmt, error)
QueryContext(context.Context, string, ...any) (*sql.Rows, error)
QueryRowContext(context.Context, string, ...any) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
return &Queries{
db: tx,
}
}
```
You'd use it like this:
```go
// Using `github/lib/pq` as the driver.
func bumpCounter(ctx context.Context, db *sql.DB, queries *tutorial.Queries, id int32) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
qtx := queries.WithTx(tx)
r, err := qtx.GetRecord(ctx, id)
if err != nil {
return err
}
if err := qtx.UpdateRecord(ctx, tutorial.UpdateRecordParams{
ID: r.ID,
Counter: r.Counter + 1,
}); err != nil {
return err
}
return tx.Commit()
}
// Using `github.com/jackc/pgx/v5` as the driver.
func bumpCounter(ctx context.Context, db *pgx.Conn, queries *tutorial.Queries, id int32) error {
tx, err := db.Begin(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx)
qtx := queries.WithTx(tx)
r, err := qtx.GetRecord(ctx, id)
if err != nil {
return err
}
if err := qtx.UpdateRecord(ctx, tutorial.UpdateRecordParams{
ID: r.ID,
Counter: r.Counter + 1,
}); err != nil {
return err
}
return tx.Commit(ctx)
}
```

115
docs/howto/update.md Normal file
View File

@@ -0,0 +1,115 @@
# Updating rows
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
bio text NOT NULL
);
```
## Single parameter
If your query has a single parameter, your Go method will also have a single
parameter.
The parameter syntax varies by database engine:
**PostgreSQL:**
```sql
-- name: UpdateAuthorBios :exec
UPDATE authors SET bio = $1;
```
**MySQL and SQLite:**
```sql
-- name: UpdateAuthorBios :exec
UPDATE authors SET bio = ?;
```
```go
package db
import (
"context"
"database/sql"
)
type DBTX interface {
ExecContext(context.Context, string, ...any) (sql.Result, error)
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
const updateAuthorBios = `-- name: UpdateAuthorBios :exec
UPDATE authors SET bio = $1
`
func (q *Queries) UpdateAuthorBios(ctx context.Context, bio string) error {
_, err := q.db.ExecContext(ctx, updateAuthorBios, bio)
return err
}
```
## Multiple parameters
If your query has more than one parameter, your Go method will accept a
`Params` struct.
**PostgreSQL:**
```sql
-- name: UpdateAuthor :exec
UPDATE authors SET bio = $2
WHERE id = $1;
```
**MySQL and SQLite:**
```sql
-- name: UpdateAuthor :exec
UPDATE authors SET bio = ?
WHERE id = ?;
```
Note: For MySQL and SQLite, parameters are bound in the order they appear in the query, regardless of the order in the function signature.
```go
package db
import (
"context"
"database/sql"
)
type DBTX interface {
ExecContext(context.Context, string, ...any) (sql.Result, error)
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
const updateAuthor = `-- name: UpdateAuthor :exec
UPDATE authors SET bio = $2
WHERE id = $1
`
type UpdateAuthorParams struct {
ID int32
Bio string
}
func (q *Queries) UpdateAuthor(ctx context.Context, arg UpdateAuthorParams) error {
_, err := q.db.ExecContext(ctx, updateAuthor, arg.ID, arg.Bio)
return err
}
```

105
docs/howto/verify.md Normal file
View File

@@ -0,0 +1,105 @@
# `verify` - Verifying schema changes
*Added in v1.24.0*
Schema updates and poorly-written queries often bring down production databases. That’s bad.
Out of the box, `sqlc generate` catches some of these issues. Running `sqlc vet` with the `sqlc/db-prepare` rule catches more subtle problems. But there is a large class of issues that sqlc can’t prevent by looking at current schema and queries alone.
For instance, when a schema change is proposed, existing queries and code running in production might fail when the schema change is applied. Enter `sqlc verify`, which analyzes existing queries against new schema changes and errors if there are any issues.
Let's look at an example. Assume you have these two tables in production.
```sql
CREATE TABLE users (
id UUID PRIMARY KEY
);
CREATE TABLE user_actions (
id UUID PRIMARY KEY,
user_id UUID NOT NULL,
action TEXT,
created_at TIMESTAMP
);
```
Your application contains the following query to join user actions against the users table.
```sql
-- name: GetUserActions :many
SELECT * FROM users u
JOIN user_actions ua ON u.id = ua.user_id
ORDER BY created_at;
```
So far, so good. Then assume you propose this schema change:
```sql
ALTER TABLE users ADD COLUMN created_at TIMESTAMP;
```
Running `sqlc generate` fails with this change, returning a `column reference "created_at" is ambiguous` error. You update your query to fix the issue.
```sql
-- name: GetUserActions :many
SELECT * FROM users u
JOIN user_actions ua ON u.id = ua.user_id
ORDER BY u.created_at;
```
While that change fixes the issue, there's a production outage waiting to happen. When the schema change is applied, the existing `GetUserActions` query will begin to fail. The correct way to fix this is to deploy the updated query before applying the schema migration.
It ensures migrations are safe to deploy by sending your current schema and queries to sqlc cloud. There, we run the queries for your latest push against your new schema changes. This check catches backwards incompatible schema changes for existing queries.
Here `sqlc verify` alerts you to the fact that ORDER BY "created_at" is ambiguous.
```sh
$ sqlc verify
FAIL: app query.sql
=== Failed
=== FAIL: app query.sql GetUserActions
ERROR: column reference "created_at" is ambiguous (SQLSTATE 42702)
```
By the way, this scenario isn't made up! It happened to us a few weeks ago. We've been happily testing early versions of `verify` for the last two weeks and haven't had any issues since.
This type of verification is only the start. If your application is deployed on-prem by your customers, `verify` could tell you if it's safe for your customers to rollback to an older version of your app, even after schema migrations have been run.
Using `verify` requires that you push your queries and schema when you tag a release of your application. We run it on every push to main, as we continuously deploy those commits.
## Authentication
`sqlc` expects to find a valid auth token in the value of the `SQLC_AUTH_TOKEN`
environment variable. You can create an auth token via the [dashboard](https://dashboard.sqlc.dev).
```shell
export SQLC_AUTH_TOKEN=sqlc_xxxxxxxx
```
## Expected workflow
Using `sqlc verify` requires pushing your queries and schema to sqlc Cloud. When
you release a new version of your application, you should push your schema and
queries as well. For example, we run `sqlc push` after any change has been
merged into our `main` branch on Github, as we deploy every commit to
production.
```shell
$ sqlc push --tag main
```
Locally or in pull requests, run `sqlc verify` to check that existing queries
continue to work with your current database schema.
```shell
$ sqlc verify --against main
```
## Picking a tag
Without an `against` argument, `verify` will run its analysis of the provided schema using your most-recently pushed queries. We suggest using the `against` argument to explicitly select a set of queries for comparison.
```shell
$ sqlc verify --against [tag]
```

286
docs/howto/vet.md Normal file
View File

@@ -0,0 +1,286 @@
# `vet` - Linting queries
*Added in v1.19.0*
`sqlc vet` runs queries through a set of lint rules.
Rules are defined in the `sqlc` [configuration](../reference/config.md) file. They
consist of a name, message, and a [Common Expression Language
(CEL)](https://github.com/google/cel-spec) expression. Expressions are evaluated
using [cel-go](https://github.com/cel-expr/cel-go). If an expression evaluates to
`true`, `sqlc vet` will report an error using the given message.
## Defining lint rules
Each lint rule's CEL expression has access to information from your sqlc
configuration and queries via variables defined in the following proto messages.
```proto
message Config
{
string version = 1;
string engine = 2 ;
repeated string schema = 3;
repeated string queries = 4;
}
message Query
{
// SQL body
string sql = 1;
// Name of the query
string name = 2;
// One of "many", "one", "exec", etc.
string cmd = 3;
// Query parameters, if any
repeated Parameter params = 4;
}
message Parameter
{
int32 number = 1;
}
```
In addition to this basic information, when you have a PostgreSQL or MySQL
[database connection configured](../reference/config.md#database)
each CEL expression has access to the output from running `EXPLAIN ...` on your query
via the `postgresql.explain` and `mysql.explain` variables.
This output is quite complex and depends on the structure of your query but sqlc attempts
to parse and provide as much information as it can. See
[Rules using `EXPLAIN ...` output](#rules-using-explain--output) for more information.
Here are a few example rules just using the basic configuration and query information available
to the CEL expression environment. While these examples are simplistic, they give you a flavor
of the types of rules you can write.
```yaml
version: 2
sql:
- schema: "query.sql"
queries: "query.sql"
engine: "postgresql"
gen:
go:
package: "authors"
out: "db"
rules:
- no-pg
- no-delete
- only-one-param
- no-exec
rules:
- name: no-pg
message: "invalid engine: postgresql"
rule: |
config.engine == "postgresql"
- name: no-delete
message: "don't use delete statements"
rule: |
query.sql.contains("DELETE")
- name: only-one-param
message: "too many parameters"
rule: |
query.params.size() > 1
- name: no-exec
message: "don't use exec"
rule: |
query.cmd == "exec"
```
### Rules using `EXPLAIN ...` output
*Added in v1.20.0*
The CEL expression environment has two variables containing `EXPLAIN ...` output,
`postgresql.explain` and `mysql.explain`. `sqlc` only populates the variable associated with
your configured database engine, and only when you have a
[database connection configured](../reference/config.md#database).
For the `postgresql` engine, `sqlc` runs
```sql
EXPLAIN (ANALYZE false, VERBOSE, COSTS, SETTINGS, BUFFERS, FORMAT JSON) ...
```
where `"..."` is your query string, and parses the output into a [`PostgreSQLExplain`](https://buf.build/sqlc/sqlc/docs/v1.20.0:vet#vet.PostgreSQLExplain) proto message.
For the `mysql` engine, `sqlc` runs
```sql
EXPLAIN FORMAT=JSON ...
```
where `"..."` is your query string, and parses the output into a [`MySQLExplain`](https://buf.build/sqlc/sqlc/docs/v1.20.0:vet#vet.MySQLExplain) proto message.
These proto message definitions are too long to include here, but you can find them in the `protos`
directory within the `sqlc` source tree.
The output from `EXPLAIN ...` depends on the structure of your query so it's a bit difficult
to offer generic examples. Refer to the
[PostgreSQL documentation](https://www.postgresql.org/docs/current/using-explain.html) and
[MySQL documentation](https://dev.mysql.com/doc/refman/en/explain-output.html) for more
information.
```yaml
...
rules:
- name: postgresql-query-too-costly
message: "Query cost estimate is too high"
rule: "postgresql.explain.plan.total_cost > 1.0"
- name: postgresql-no-seq-scan
message: "Query plan results in a sequential scan"
rule: "postgresql.explain.plan.node_type == 'Seq Scan'"
- name: mysql-query-too-costly
message: "Query cost estimate is too high"
rule: "has(mysql.explain.query_block.cost_info) && double(mysql.explain.query_block.cost_info.query_cost) > 2.0"
- name: mysql-must-use-primary-key
message: "Query plan doesn't use primary key"
rule: "has(mysql.explain.query_block.table.key) && mysql.explain.query_block.table.key != 'PRIMARY'"
```
When building rules that depend on `EXPLAIN ...` output, it may be helpful to see the actual JSON
returned from the database. `sqlc` will print it When you set the environment variable
`SQLCDEBUG=dumpexplain=1`. Use this environment variable together with a dummy rule to see
`EXPLAIN ...` output for all of your queries.
```yaml
version: 2
sql:
- schema: "query.sql"
queries: "query.sql"
engine: "postgresql"
database:
uri: "postgresql://postgres:postgres@localhost:5432/postgres"
gen:
go:
package: "db"
out: "db"
rules:
- debug
rules:
- name: debug
rule: "!has(postgresql.explain)" # A dummy rule to trigger explain
```
Please note that databases configured with a `uri` must have an up-to-date
schema for `vet` to work correctly, and `sqlc` does not apply schema migrations
to your database. Use your migration tool of choice to create the necessary
tables and objects before running `sqlc vet` with rules that depend on
`EXPLAIN ...` output.
Alternatively, configure [managed databases](managed-databases.md) to have
`sqlc` create hosted ephemeral databases with the correct schema automatically.
## Built-in rules
### sqlc/db-prepare
When a [database](../reference/config.md#database) connection is configured, you can
run the built-in `sqlc/db-prepare` rule. This rule will attempt to prepare
each of your queries against the connected database and report any failures.
```yaml
version: 2
sql:
- schema: "schema.sql"
queries: "query.sql"
engine: "postgresql"
gen:
go:
package: "authors"
out: "db"
database:
uri: "postgresql://postgres:password@localhost:5432/postgres"
rules:
- sqlc/db-prepare
```
Please note that databases configured with a `uri` must have an up-to-date
schema for `vet` to work correctly, and `sqlc` does not apply schema migrations
to your database. Use your migration tool of choice to create the necessary
tables and objects before running `sqlc vet` with the `sqlc/db-prepare` rule.
Alternatively, configure [managed databases](managed-databases.md) to have
`sqlc` create hosted ephemeral databases with the correct schema automatically.
```yaml
version: 2
cloud:
project: "<PROJECT_ID>"
sql:
- schema: "schema.sql"
queries: "query.sql"
engine: "postgresql"
gen:
go:
package: "authors"
out: "db"
database:
managed: true
rules:
- sqlc/db-prepare
```
To see this in action, check out the [authors
example](https://github.com/sqlc-dev/sqlc/blob/main/examples/authors/sqlc.yaml).
## Running lint rules
When you add the name of a defined rule to the rules list
for a [sql package](../reference/config.md#sql),
`sqlc vet` will evaluate that rule against every query in the package.
In the example below, two rules are defined but only one is enabled.
```yaml
version: 2
sql:
- schema: "query.sql"
queries: "query.sql"
engine: "postgresql"
gen:
go:
package: "authors"
out: "db"
rules:
- no-delete
rules:
- name: no-pg
message: "invalid engine: postgresql"
rule: |
config.engine == "postgresql"
- name: no-delete
message: "don't use delete statements"
rule: |
query.sql.contains("DELETE")
```
### Opting-out of lint rules
For any query, you can tell `sqlc vet` not to evaluate lint rules using the
`@sqlc-vet-disable` query annotation. The annotation accepts a list of rules to ignore.
```sql
/* name: GetAuthor :one */
/* @sqlc-vet-disable sqlc/db-prepare no-pg */
SELECT * FROM authors
WHERE id = ? LIMIT 1;
```
The rules can also be split across lines.
```sql
/* name: GetAuthor :one */
/* @sqlc-vet-disable sqlc/db-prepare */
/* @sqlc-vet-disable no-pg */
SELECT * FROM authors
WHERE id = ? LIMIT 1;
```
To skip all rules for a query, you can provide the `@sqlc-vet-disable` annotation without any parameters.
```sql
/* name: GetAuthor :one */
/* @sqlc-vet-disable */
SELECT * FROM authors
WHERE id = ? LIMIT 1;
```

22
docs/index.md Normal file
View File

@@ -0,0 +1,22 @@
# sqlc Documentation
> And lo, the Great One looked down upon the people and proclaimed:
> "SQL is actually pretty great"
sqlc generates **fully type-safe idiomatic Go code** from SQL. Here's how it
works:
1. You write SQL queries
2. You run sqlc to generate Go code that presents type-safe interfaces to those
queries
3. You write application code that calls the methods sqlc generated
Seriously, it's that easy. You don't have to write any boilerplate SQL querying
code ever again.
## Getting started
- [Installing sqlc](overview/install.md)
- [Getting started with MySQL](tutorials/getting-started-mysql.md)
- [Getting started with PostgreSQL](tutorials/getting-started-postgresql.md)
- [Getting started with SQLite](tutorials/getting-started-sqlite.md)

51
docs/overview/install.md Normal file
View File

@@ -0,0 +1,51 @@
# Installing sqlc
sqlc is distributed as a single binary with zero dependencies.
## macOS
```
brew install sqlc
```
## Ubuntu
```
sudo snap install sqlc
```
## go install
Installing recent versions of sqlc requires Go 1.21+.
```
go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
```
## Docker
```
docker pull sqlc/sqlc
```
Run `sqlc` using `docker run`:
```
docker run --rm -v $(pwd):/src -w /src sqlc/sqlc generate
```
Run `sqlc` using `docker run` in the Command Prompt on Windows (`cmd`):
```
docker run --rm -v "%cd%:/src" -w /src sqlc/sqlc generate
```
## Downloads
Get pre-built binaries for *v1.31.1*:
- [Linux](https://downloads.sqlc.dev/sqlc_1.31.1_linux_amd64.tar.gz)
- [macOS](https://downloads.sqlc.dev/sqlc_1.31.1_darwin_amd64.zip)
- [Windows](https://downloads.sqlc.dev/sqlc_1.31.1_windows_amd64.zip)
See [downloads.sqlc.dev](https://downloads.sqlc.dev/) for older versions.

2936
docs/reference/changelog.md Normal file

File diff suppressed because it is too large Load Diff

29
docs/reference/cli.md Normal file
View File

@@ -0,0 +1,29 @@
# CLI
```sh
Usage:
sqlc [command]
Available Commands:
analyze Analyze a query against a schema and output the result columns and parameters
compile Statically check SQL for syntax and type errors
completion Generate the autocompletion script for the specified shell
createdb Create an ephemeral database
diff Compare the generated files to the existing files
fmt Format SQL queries
generate Generate source code from SQL
help Help about any command
init Create an empty sqlc.yaml settings file
parse Parse SQL and output the AST as JSON
push Push the schema, queries, and configuration for this project
verify Verify schema, queries, and configuration for this project
version Print the sqlc version number
vet Vet examines queries
Flags:
-f, --file string specify an alternate config file (default: sqlc.yaml)
-h, --help help for sqlc
--no-database disable database connections (default: false)
Use "sqlc [command] --help" for more information about a command.
```

501
docs/reference/config.md Normal file
View File

@@ -0,0 +1,501 @@
# Configuration
The `sqlc` tool is configured via a `sqlc.(yaml|yml)` or `sqlc.json` file. This
file must be in the directory where the `sqlc` command is run.
## Version 2
```yaml
version: "2"
cloud:
project: "<PROJECT_ID>"
sql:
- schema: "postgresql/schema.sql"
queries: "postgresql/query.sql"
engine: "postgresql"
gen:
go:
package: "authors"
out: "postgresql"
database:
managed: true
rules:
- sqlc/db-prepare
- schema: "mysql/schema.sql"
queries: "mysql/query.sql"
engine: "mysql"
gen:
go:
package: "authors"
out: "mysql"
```
### sql
Each mapping in the `sql` collection has the following keys:
- `name`:
- An human-friendly identifier for this query set. Optional.
- `engine`:
- One of `postgresql`, `mysql` or `sqlite`.
- `schema`:
- Directory of SQL migrations or path to single SQL file; or a list of paths.
- `queries`:
- Directory of SQL queries or path to single SQL file; or a list of paths.
- `codegen`:
- A collection of mappings to configure code generators. See [codegen](#codegen) for the supported keys.
- `gen`:
- A mapping to configure built-in code generators. See [gen](#gen) for the supported keys.
- `database`:
- A mapping to configure database connections. See [database](#database) for the supported keys.
- `rules`:
- A collection of rule names to run via `sqlc vet`. See [rules](#rules) for configuration options.
- `analyzer`:
- A mapping to configure query analysis. See [analyzer](#analyzer) for the supported keys.
- `strict_function_checks`
- If true, return an error if a called SQL function does not exist. Defaults to `false`.
- `strict_order_by`
- If true, return an error if a order by column is ambiguous. Defaults to `true`.
### codegen
The `codegen` mapping supports the following keys:
- `out`:
- Output directory for generated code.
- `plugin`:
- The name of the plugin. Must be defined in the `plugins` collection.
- `options`:
- A mapping of plugin-specific options.
```yaml
version: '2'
plugins:
- name: py
wasm:
url: https://github.com/sqlc-dev/sqlc-gen-python/releases/download/v0.16.0-alpha/sqlc-gen-python.wasm
sha256: 428476c7408fd4c032da4ec74e8a7344f4fa75e0f98a5a3302f238283b9b95f2
sql:
- schema: "schema.sql"
queries: "query.sql"
engine: postgresql
codegen:
- out: src/authors
plugin: py
options:
package: authors
emit_sync_querier: true
emit_async_querier: true
query_parameter_limit: 5
```
### database
The `database` mapping supports the following keys:
- `managed`:
- If true, connect to a [managed database](../howto/managed-databases.md). Defaults to `false`.
- `uri`:
- Database connection URI
The `uri` string can contain references to environment variables using the `${...}`
syntax. In the following example, the connection string will have the value of
the `PG_PASSWORD` environment variable set as its password.
```yaml
version: '2'
sql:
- schema: schema.sql
queries: query.sql
engine: postgresql
database:
uri: postgresql://postgres:${PG_PASSWORD}@localhost:5432/authors
gen:
go:
package: authors
out: postgresql
```
### analyzer
The `analyzer` mapping supports the following keys:
- `database`:
- If false, do not use the configured database for query analysis. Defaults to `true`.
### gen
The `gen` mapping supports the following keys:
#### go
- `package`:
- The package name to use for the generated code. Defaults to `out` basename.
- `out`:
- Output directory for generated code.
- `sql_package`:
- Either `pgx/v4`, `pgx/v5` or `database/sql`. Defaults to `database/sql`.
- `sql_driver`:
- Either `github.com/jackc/pgx/v4`, `github.com/jackc/pgx/v5`, `github.com/lib/pq` or `github.com/go-sql-driver/mysql`. No defaults. Required if query annotation `:copyfrom` is used.
- `emit_db_tags`:
- If true, add DB tags to generated structs. Defaults to `false`.
- `emit_prepared_queries`:
- If true, include support for prepared queries. Defaults to `false`.
- `emit_interface`:
- If true, output a `Querier` interface in the generated package. Defaults to `false`.
- `emit_exact_table_names`:
- If true, struct names will mirror table names. Otherwise, sqlc attempts to singularize plural table names. Defaults to `false`.
- `emit_empty_slices`:
- If true, slices returned by `:many` queries will be empty instead of `nil`. Defaults to `false`.
- `emit_exported_queries`:
- If true, autogenerated SQL statement can be exported to be accessed by another package.
- `emit_json_tags`:
- If true, add JSON tags to generated structs. Defaults to `false`.
- `emit_result_struct_pointers`:
- If true, query results are returned as pointers to structs. Queries returning multiple results are returned as slices of pointers. Defaults to `false`.
- `emit_params_struct_pointers`:
- If true, parameters are passed as pointers to structs. Defaults to `false`.
- `emit_methods_with_db_argument`:
- If true, generated methods will accept a DBTX argument instead of storing a DBTX on the `*Queries` struct. Defaults to `false`.
- `emit_pointers_for_null_types`:
- If true, generated types for nullable columns are emitted as pointers (ie. `*string`) instead of `database/sql` null types (ie. `NullString`). Currently only supported for PostgreSQL if `sql_package` is `pgx/v4` or `pgx/v5`, and for SQLite. Defaults to `false`. Nullable enum columns also follow this setting unless `emit_pointers_for_null_enum_types` is set.
- `emit_pointers_for_null_enum_types`:
- Overrides `emit_pointers_for_null_types` for nullable enum columns only. When `true`, nullable enum columns are emitted as pointers (ie. `*UserRole`). When `false`, nullable enum columns use the generated `NullUserRole` wrapper struct even if `emit_pointers_for_null_types` is true. Set this to `false` to keep the pre-v1.31 behavior when upgrading. Only applies to PostgreSQL with `sql_package` `pgx/v4` or `pgx/v5`.
- `emit_enum_valid_method`:
- If true, generate a Valid method on enum types,
indicating whether a string is a valid enum value.
- `emit_all_enum_values`:
- If true, emit a function per enum type
that returns all valid enum values.
- `emit_sql_as_comment`:
- If true, emits the SQL statement as a code-block comment above the generated function, appending to any existing comments. Defaults to `false`.
- `build_tags`:
- If set, add a `//go:build <build_tags>` directive at the beginning of each generated Go file.
- `initialisms`:
- An array of [initialisms](https://google.github.io/styleguide/go/decisions.html#initialisms) to upper-case. For example, `app_id` becomes `AppID`. Defaults to `["id"]`.
- `json_tags_id_uppercase`:
- If true, "Id" in json tags will be uppercase. If false, will be camelcase. Defaults to `false`
- `json_tags_case_style`:
- `camel` for camelCase, `pascal` for PascalCase, `snake` for snake_case or `none` to use the column name in the DB. Defaults to `none`.
- `omit_unused_structs`:
- If `true`, sqlc won't generate table and enum structs that aren't used in queries for a given package. Defaults to `false`.
- `output_batch_file_name`:
- Customize the name of the batch file. Defaults to `batch.go`.
- `output_db_file_name`:
- Customize the name of the db file. Defaults to `db.go`.
- `output_models_file_name`:
- Customize the name of the models file. Defaults to `models.go`.
- `output_querier_file_name`:
- Customize the name of the querier file. Defaults to `querier.go`.
- `output_copyfrom_file_name`:
- Customize the name of the copyfrom file. Defaults to `copyfrom.go`.
- `output_files_suffix`:
- If specified the suffix will be added to the name of the generated files.
- `query_parameter_limit`:
- The number of positional arguments that will be generated for Go functions. To always emit a parameter struct, set this to `0`. Defaults to `1`.
- `rename`:
- Customize the name of generated struct fields. See [Renaming fields](../howto/rename.md) for usage information.
- `overrides`:
- A collection of configurations to override sqlc's default Go type choices. See [Overriding types](../howto/overrides.md) for usage information.
##### overrides
See [Overriding types](../howto/overrides.md) for an in-depth guide to using type overrides.
#### kotlin
> Removed in v1.17.0 and replaced by the [sqlc-gen-kotlin](https://github.com/sqlc-dev/sqlc-gen-kotlin) plugin. Follow the [migration guide](../guides/migrating-to-sqlc-gen-kotlin.md) to switch.
- `package`:
- The package name to use for the generated code.
- `out`:
- Output directory for generated code.
- `emit_exact_table_names`:
- If true, use the exact table name for generated models. Otherwise, guess a singular form. Defaults to `false`.
#### python
> Removed in v1.17.0 and replaced by the [sqlc-gen-python](https://github.com/sqlc-dev/sqlc-gen-python) plugin. Follow the [migration guide](../guides/migrating-to-sqlc-gen-python.md) to switch.
- `package`:
- The package name to use for the generated code.
- `out`:
- Output directory for generated code.
- `emit_exact_table_names`:
- If true, use the exact table name for generated models. Otherwise, guess a singular form. Defaults to `false`.
- `emit_sync_querier`:
- If true, generate a class with synchronous methods. Defaults to `false`.
- `emit_async_querier`:
- If true, generate a class with asynchronous methods. Defaults to `false`.
- `emit_pydantic_models`:
- If true, generate classes that inherit from `pydantic.BaseModel`. Otherwise, define classes using the `dataclass` decorator. Defaults to `false`.
#### json
- `out`:
- Output directory for the generated JSON.
- `filename`:
- Filename for the generated JSON document. Defaults to `codegen_request.json`.
- `indent`:
- Indent string to use in the JSON document. Defaults to ` `.
### plugins
Each mapping in the `plugins` collection has the following keys:
- `name`:
- The name of this plugin. Required
- `env`
- A list of environment variables to pass to the plugin. By default, no environment variables are passed.
- `process`: A mapping with a single `cmd` key
- `cmd`:
- The executable to call when using this plugin
- `format`:
- The format expected. Supports `json` and `protobuf` formats. Defaults to `protobuf`.
- `wasm`: A mapping with a two keys `url` and `sha256`
- `url`:
- The URL to fetch the WASM file. Supports the `https://` or `file://` schemes.
- `sha256`
- The SHA256 checksum for the downloaded file.
```yaml
version: "2"
plugins:
- name: "py"
wasm:
url: "https://github.com/sqlc-dev/sqlc-gen-python/releases/download/v0.16.0-alpha/sqlc-gen-python.wasm"
sha256: "428476c7408fd4c032da4ec74e8a7344f4fa75e0f98a5a3302f238283b9b95f2"
- name: "js"
env:
- PATH
process:
cmd: "sqlc-gen-json"
```
### rules
Each mapping in the `rules` collection has the following keys:
- `name`:
- The name of this rule. Required
- `rule`:
- A [Common Expression Language (CEL)](https://github.com/google/cel-spec) expression. Required.
- `message`:
- An optional message shown when this rule evaluates to `true`.
See the [vet](../howto/vet.md) documentation for a list of built-in rules and
help writing custom rules.
```yaml
version: "2"
sql:
- schema: "query.sql"
queries: "query.sql"
engine: "postgresql"
gen:
go:
package: "authors"
out: "db"
rules:
- no-pg
- no-delete
- only-one-param
- no-exec
rules:
- name: no-pg
message: "invalid engine: postgresql"
rule: |
config.engine == "postgresql"
- name: no-delete
message: "don't use delete statements"
rule: |
query.sql.contains("DELETE")
- name: only-one-param
message: "too many parameters"
rule: |
query.params.size() > 1
- name: no-exec
message: "don't use exec"
rule: |
query.cmd == "exec"
```
### Global overrides
Sometimes, the same configuration must be done across various specifications of
code generation. Then a global definition for type overriding and field
renaming can be done using the `overrides` mapping the following manner:
```yaml
version: "2"
overrides:
go:
rename:
id: "Identifier"
overrides:
- db_type: "pg_catalog.timestamptz"
nullable: true
engine: "postgresql"
go_type:
import: "gopkg.in/guregu/null.v4"
package: "null"
type: "Time"
sql:
- schema: "postgresql/schema.sql"
queries: "postgresql/query.sql"
engine: "postgresql"
gen:
go:
package: "authors"
out: "postgresql"
- schema: "mysql/schema.sql"
queries: "mysql/query.sql"
engine: "mysql"
gen:
go:
package: "authors"
out: "mysql"
```
With the previous configuration, whenever a struct field is generated from a
table column that is called `id`, it will generated as `Identifier`.
Also, whenever there is a nullable `timestamp with time zone` column in a
Postgres table, it will be generated as `null.Time`. Note that the mapping for
global type overrides has a field called `engine` that is absent in the regular
type overrides. This field is only used when there are multiple definitions
using multiple engines. Otherwise, the value of the `engine` key
defaults to the engine that is currently being used.
Currently, type overrides and field renaming, both global and regular, are only
fully supported in Go.
## Version 1
```yaml
version: "1"
packages:
- name: "db"
path: "internal/db"
queries: "./sql/query/"
schema: "./sql/schema/"
engine: "postgresql"
emit_db_tags: false
emit_prepared_queries: true
emit_interface: false
emit_exact_table_names: false
emit_empty_slices: false
emit_exported_queries: false
emit_json_tags: true
emit_result_struct_pointers: false
emit_params_struct_pointers: false
emit_methods_with_db_argument: false
emit_pointers_for_null_types: false
emit_enum_valid_method: false
emit_all_enum_values: false
build_tags: "some_tag"
json_tags_case_style: "camel"
omit_unused_structs: false
output_batch_file_name: "batch.go"
output_db_file_name: "db.go"
output_models_file_name: "models.go"
output_querier_file_name: "querier.go"
output_copyfrom_file_name: "copyfrom.go"
query_parameter_limit: 1
```
### packages
Each mapping in the `packages` collection has the following keys:
- `name`:
- The package name to use for the generated code. Defaults to `path` basename.
- `path`:
- Output directory for generated code.
- `queries`:
- Directory of SQL queries or path to single SQL file; or a list of paths.
- `schema`:
- Directory of SQL migrations or path to single SQL file; or a list of paths.
- `engine`:
- Either `postgresql` or `mysql`. Defaults to `postgresql`.
- `sql_package`:
- Either `pgx/v4`, `pgx/v5` or `database/sql`. Defaults to `database/sql`.
- `overrides`:
- A list of type override configurations. See the [Overriding types](../howto/overrides.md) guide for details.
- `emit_db_tags`:
- If true, add DB tags to generated structs. Defaults to `false`.
- `emit_prepared_queries`:
- If true, include support for prepared queries. Defaults to `false`.
- `emit_interface`:
- If true, output a `Querier` interface in the generated package. Defaults to `false`.
- `emit_exact_table_names`:
- If true, struct names will mirror table names. Otherwise, sqlc attempts to singularize plural table names. Defaults to `false`.
- `emit_empty_slices`:
- If true, slices returned by `:many` queries will be empty instead of `nil`. Defaults to `false`.
- `emit_exported_queries`:
- If true, autogenerated SQL statement can be exported to be accessed by another package.
- `emit_json_tags`:
- If true, add JSON tags to generated structs. Defaults to `false`.
- `emit_result_struct_pointers`:
- If true, query results are returned as pointers to structs. Queries returning multiple results are returned as slices of pointers. Defaults to `false`.
- `emit_params_struct_pointers`:
- If true, parameters are passed as pointers to structs. Defaults to `false`.
- `emit_methods_with_db_argument`:
- If true, generated methods will accept a DBTX argument instead of storing a DBTX on the `*Queries` struct. Defaults to `false`.
- `emit_pointers_for_null_types`:
- If true and `sql_package` is set to `pgx/v4` or `pgx/v5`, generated types for nullable columns are emitted as pointers (ie. `*string`) instead of `database/sql` null types (ie. `NullString`). Defaults to `false`. Nullable enum columns also follow this setting unless `emit_pointers_for_null_enum_types` is set.
- `emit_pointers_for_null_enum_types`:
- Overrides `emit_pointers_for_null_types` for nullable enum columns only. When `true`, nullable enum columns are emitted as pointers (ie. `*UserRole`). When `false`, nullable enum columns use the generated `NullUserRole` wrapper struct even if `emit_pointers_for_null_types` is true. Set this to `false` to keep the pre-v1.31 behavior when upgrading. Only applies to PostgreSQL with `sql_package` `pgx/v4` or `pgx/v5`.
- `emit_enum_valid_method`:
- If true, generate a Valid method on enum types,
indicating whether a string is a valid enum value.
- `emit_all_enum_values`:
- If true, emit a function per enum type
that returns all valid enum values.
- `build_tags`:
- If set, add a `//go:build <build_tags>` directive at the beginning of each generated Go file.
- `json_tags_case_style`:
- `camel` for camelCase, `pascal` for PascalCase, `snake` for snake_case or `none` to use the column name in the DB. Defaults to `none`.
- `omit_unused_structs`:
- If `true`, sqlc won't generate table and enum structs that aren't used in queries for a given package. Defaults to `false`.
- `output_batch_file_name`:
- Customize the name of the batch file. Defaults to `batch.go`.
- `output_db_file_name`:
- Customize the name of the db file. Defaults to `db.go`.
- `output_models_file_name`:
- Customize the name of the models file. Defaults to `models.go`.
- `output_querier_file_name`:
- Customize the name of the querier file. Defaults to `querier.go`.
- `output_copyfrom_file_name`:
- Customize the name of the copyfrom file. Defaults to `copyfrom.go`.
- `output_files_suffix`:
- If specified the suffix will be added to the name of the generated files.
- `query_parameter_limit`:
- Positional arguments that will be generated in Go functions (`>= 0`). To always emit a parameter struct, you would need to set it to `0`. Defaults to `1`.
### overrides
See the version 1 configuration section of the [Overriding types](../howto/overrides.md#version-1-configuration) guide for details.
### rename
Struct field names are generated from column names using a simple algorithm:
split the column name on underscores and capitalize the first letter of each
part.
```
account -> Account
spotify_url -> SpotifyUrl
app_id -> AppID
```
If you're not happy with a field's generated name, use the `rename` mapping
to pick a new name. The keys are column names and the values are the struct
field name to use.
```yaml
version: "1"
packages: [...]
rename:
spotify_url: "SpotifyURL"
```

388
docs/reference/datatypes.md Normal file
View File

@@ -0,0 +1,388 @@
# Datatypes
`sqlc` attempts to make reasonable default choices when mapping internal
database types to Go types. Choices for more complex types are described below.
If you're unsatisfied with the default, you can override any type using the
[overrides list](config.md#overrides) in your `sqlc` config file.
## Arrays
PostgreSQL [arrays](https://www.postgresql.org/docs/current/arrays.html) are
materialized as Go slices.
```sql
CREATE TABLE places (
name text not null,
tags text[]
);
```
```go
package db
type Place struct {
Name string
Tags []string
}
```
## Dates and times
All date and time types are returned as `time.Time` structs. For
null time or date values, the `NullTime` type from `database/sql` is used.
The `pgx/v5` sql package uses the appropriate pgx types.
For MySQL users relying on `github.com/go-sql-driver/mysql`, ensure that
`parseTime=true` is added to your database connection string.
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
created_at timestamp NOT NULL DEFAULT NOW(),
updated_at timestamp
);
```
```go
package db
import (
"database/sql"
"time"
)
type Author struct {
ID int
CreatedAt time.Time
UpdatedAt sql.NullTime
}
```
## Enums
PostgreSQL [enums](https://www.postgresql.org/docs/current/datatype-enum.html) are
mapped to an aliased string type.
```sql
CREATE TYPE status AS ENUM (
'open',
'closed'
);
CREATE TABLE stores (
name text PRIMARY KEY,
status status NOT NULL
);
```
```go
package db
type Status string
const (
StatusOpen Status = "open"
StatusClosed Status = "closed"
)
type Store struct {
Name string
Status Status
}
```
## Null
For structs, null values are represented using the appropriate type from the
`database/sql` or `pgx` package.
```sql
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
name text NOT NULL,
bio text
);
```
```go
package db
import (
"database/sql"
)
type Author struct {
ID int
Name string
Bio sql.NullString
}
```
## UUIDs
For UUID support, sqlc uses the `github.com/google/uuid` package by default.
The pgx/v5 sql package uses `pgtype.UUID`.
```sql
CREATE TABLE records (
id uuid PRIMARY KEY
);
```
```go
package db
import (
"github.com/google/uuid"
)
type Author struct {
ID uuid.UUID
}
```
### Using the standard library uuid package
Go 1.27 added a [`uuid`](https://pkg.go.dev/uuid) package to the standard
library. sqlc will use this package by default in a future release. Until
then, use it today with type overrides
(see [Overriding types](../howto/overrides.md) for details).
Two overrides are required: one for non-nullable columns and one for nullable
columns. The standard library does not include a `NullUUID` type, so nullable
columns map to `*uuid.UUID` instead.
```yaml
version: "2"
sql:
- engine: "postgresql"
schema: "schema.sql"
queries: "query.sql"
gen:
go:
package: "db"
out: "db"
sql_package: "pgx/v5"
overrides:
- db_type: "uuid"
go_type: "uuid.UUID"
- db_type: "uuid"
nullable: true
go_type:
import: "uuid"
type: "UUID"
pointer: true
```
With this configuration, a table with both nullable and non-nullable `uuid`
columns:
```sql
CREATE TABLE records (
id uuid PRIMARY KEY,
external_id uuid
);
```
generates:
```go
package db
import (
"uuid"
)
type Record struct {
ID uuid.UUID
ExternalID *uuid.UUID
}
```
These overrides work with both the `pgx/v5` and `database/sql` sql packages.
pgx supports any type whose underlying type is `[16]byte`, and as of Go 1.27
`database/sql` converts `uuid.UUID` values in both directions: parameters are
bound via `driver.DefaultParameterConverter` and results are scanned into
`uuid.UUID` and `*uuid.UUID` destinations, with `nil` representing `NULL`.
For MySQL, there is no native `uuid` data type. When using `UUID_TO_BIN` to store a `UUID()`, the underlying field type is `BINARY(16)` which by default sqlc would map to `sql.NullString`. To have sqlc automatically convert these fields to a `uuid.UUID` type, use an overide on the column storing the `uuid`
(see [Overriding types](../howto/overrides.md) for details).
```json
{
"overrides": [
{
"column": "*.uuid",
"go_type": "github.com/google/uuid.UUID"
}
]
}
```
## JSON
By default, sqlc will generate the `[]byte`, `pgtype.JSON` or `json.RawMessage` for JSON column type.
But if you use the `pgx/v5` sql package then you can specify a struct instead of the default type
(see [Overriding types](../howto/overrides.md) for details).
The `pgx` implementation will marshal/unmarshal the struct automatically.
```go
package dto
type BookData struct {
Genres []string `json:"genres"`
Title string `json:"title"`
Published bool `json:"published"`
}
```
```sql
CREATE TABLE books (
data jsonb
);
```
```json
{
"overrides": [
{
"column": "books.data",
"go_type": {
"import":"example.com/db",
"package": "dto",
"type":"BookData",
"pointer": true
}
}
]
}
```
```go
package db
import (
"example.com/db/dto"
)
type Book struct {
Data *dto.BookData
}
```
## TEXT
In PostgreSQL, when you have a column with the TEXT type, sqlc will map it to a Go string by default. This default mapping applies to `TEXT` columns that are not nullable. However, for nullable `TEXT` columns, sqlc maps them to `pgtype.Text` when using the pgx/v5 driver. This distinction is crucial for developers looking to handle null values appropriately in their Go applications.
To accommodate nullable strings and map them to `*string` in Go, you can use the `emit_pointers_for_null_types` option in your sqlc configuration. This option ensures that nullable SQL columns are represented as pointer types in Go, allowing for a clear distinction between null and non-null values. Another way to do this is by passing the option `pointer: true` when you are overriding the `TEXT` datatype in your sqlc config file (see [Overriding types](../howto/overrides.md) for details).
## Geometry
### PostGIS
#### Using `github.com/twpayne/go-geos` (pgx/v5 only)
sqlc can be configured to use the [geos](https://github.com/twpayne/go-geos)
package for working with PostGIS geometry types in [GEOS](https://libgeos.org/).
There are three steps:
1. Configure sqlc to use `*github.com/twpayne/go-geos.Geom` for geometry types (see [Overriding types](../howto/overrides.md) for details).
2. Call `github.com/twpayne/pgx-geos.Register` on each
`*github.com/jackc/pgx/v5.Conn`.
3. Annotate your SQL with `::geometry` typecasts, if needed.
```sql
-- Multipolygons in British National Grid (epsg:27700)
create table shapes(
id serial,
name varchar,
geom geometry(Multipolygon, 27700)
);
-- name: GetCentroids :many
SELECT id, name, ST_Centroid(geom)::geometry FROM shapes;
```
```json
{
"version": 2,
"gen": {
"go": {
"overrides": [
{
"db_type": "geometry",
"go_type": {
"import": "github.com/twpayne/go-geos",
"package": "geos",
"pointer": true,
"type": "Geom"
},
"nullable": true
}
]
}
}
}
```
```go
import (
"github.com/twpayne/go-geos"
pgxgeos "github.com/twpayne/pgx-geos"
)
// ...
config.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error {
if err := pgxgeos.Register(ctx, conn, geos.NewContext()); err != nil {
return err
}
return nil
}
```
#### Using `github.com/twpayne/go-geom`
sqlc can be configured to use the [geom](https://github.com/twpayne/go-geom)
package for working with PostGIS geometry types. See [Overriding types](../howto/overrides.md) for more information.
```sql
-- Multipolygons in British National Grid (epsg:27700)
create table shapes(
id serial,
name varchar,
geom geometry(Multipolygon, 27700)
);
-- name: GetShapes :many
SELECT * FROM shapes;
```
```json
{
"version": "1",
"packages": [
{
"path": "db",
"engine": "postgresql",
"schema": "query.sql",
"queries": "query.sql"
}
],
"overrides": [
{
"db_type": "geometry",
"go_type": "github.com/twpayne/go-geom.MultiPolygon"
},
{
"db_type": "geometry",
"go_type": "github.com/twpayne/go-geom.MultiPolygon",
"nullable": true
}
]
}
```

View File

@@ -0,0 +1,190 @@
# Environment variables
## SQLCEXPERIMENT
The `SQLCEXPERIMENT` variable controls experimental features within sqlc. It is
a comma-separated list of experiment names. This is modeled after Go's
[GOEXPERIMENT](https://pkg.go.dev/internal/goexperiment) environment variable.
Experiment names can be prefixed with `no` to explicitly disable them.
```
SQLCEXPERIMENT=foo,bar # enable foo and bar experiments
SQLCEXPERIMENT=nofoo # explicitly disable foo experiment
SQLCEXPERIMENT=foo,nobar # enable foo, disable bar
```
The following experiments are defined:
### coreanalyzer
Routes `sqlc generate` through the core catalog and analyzer instead of each
engine's own analysis path. This is the same analysis used by `sqlc analyze`,
and the only analysis path for the ClickHouse and GoogleSQL engines.
```
SQLCEXPERIMENT=coreanalyzer
```
## SQLCCACHE
The `SQLCCACHE` environment variable dictates where `sqlc` will store cached
data. By default `sqlc` follows the [XDG Base Directory
Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html).
The cache is designed after Bazel's local disk cache and has three parts:
- `cas/` — a content-addressable store holding blobs (query analysis
results, WASM plugin binaries, compiled WASM machine code) keyed by the
SHA-256 hash of their contents. A remotely fetched plugin's address is
exactly the checksum declared in the configuration file, so it is loaded
directly by that address.
- `ac/` — an action cache mapping the digest of a unit of cacheable work and
its inputs (analyzing a query against a schema, compiling a WASM module to
machine code) to the CAS digests of its outputs.
- `exec/` — per-action directories where cached output trees are
materialized for tools that read them from disk, such as the
[wazero](https://wazero.io) runtime's compilation cache.
The entire directory is safe to delete at any time; sqlc will rebuild it as
needed.
## SQLCDEBUG
The `SQLCDEBUG` variable controls debugging variables within the runtime. It is
a comma-separated list of name=val pairs settings.
### dumpast
The `dumpast` command shows the SQL AST that was generated by the parser. Note
that this is the generic SQL AST, not the engine-specific SQL AST.
```
SQLCDEBUG=dumpast=1
```
```
([]interface {}) (len=1 cap=1) {
(*catalog.Catalog)(0xc0004f48c0)({
Comment: (string) "",
DefaultSchema: (string) (len=6) "public",
Name: (string) "",
Schemas: ([]*catalog.Schema) (len=3 cap=4) {
(*catalog.Schema)(0xc0004f4930)({
Name: (string) (len=6) "public",
Tables: ([]*catalog.Table) (len=1 cap=1) {
(*catalog.Table)(0xc00052ff20)({
Rel: (*ast.TableName)(0xc00052fda0)({
Catalog: (string) "",
Schema: (string) "",
Name: (string) (len=7) "authors"
}),
```
### dumpcatalog
The `dumpcatalog` command outputs the entire catalog. If you're using MySQL or
PostgreSQL, this can be a bit overwhelming. Expect this output to change in
future versions.
```
SQLCDEBUG=dumpcatalog=1
```
```
([]interface {}) (len=1 cap=1) {
(*catalog.Catalog)(0xc00050d1f0)({
Comment: (string) "",
DefaultSchema: (string) (len=6) "public",
Name: (string) "",
Schemas: ([]*catalog.Schema) (len=3 cap=4) {
(*catalog.Schema)(0xc00050d260)({
Name: (string) (len=6) "public",
Tables: ([]*catalog.Table) (len=1 cap=1) {
(*catalog.Table)(0xc0000c0840)({
Rel: (*ast.TableName)(0xc0000c06c0)({
Catalog: (string) "",
Schema: (string) "",
Name: (string) (len=7) "authors"
}),
```
### trace
The `trace` command is helpful for tracking down performance issues.
`SQLCDEBUG=trace=1`
By default, the trace output is written to `trace.out` in the current working
directory. You can configure a different path if needed.
`SQLCDEBUG=trace=name.out`
View the execution trace using the Go `trace` tool.
```
go tool trace trace.out
```
There's a ton of different views for the trace output, but here's an example
log showing the execution time for each package.
```
0.000043897 . 1 task sqlc (id 1, parent 0) created
0.000144923 . 101026 1 region generate started (duration: 47.619781ms)
0.001048975 . 904052 1 region package started (duration: 14.588456ms)
0.001054616 . 5641 1 name=authors dir=/Users/kyle/projects/sqlc/examples/python language=python
0.001071257 . 16641 1 region parse started (duration: 7.966549ms)
0.009043960 . 7972703 1 region codegen started (duration: 6.587086ms)
0.009171704 . 127744 1 new goroutine 35: text/template/parse.lex·dwrap·1
0.010361654 . 1189950 1 new goroutine 36: text/template/parse.lex·dwrap·1
0.015641815 . 5280161 1 region package started (duration: 10.904938ms)
0.015644943 . 3128 1 name=booktest dir=/Users/kyle/projects/sqlc/examples/python language=python
0.015647431 . 2488 1 region parse started (duration: 4.207749ms)
0.019860308 . 4212877 1 region codegen started (duration: 6.681624ms)
0.020028488 . 168180 1 new goroutine 37: text/template/parse.lex·dwrap·1
0.021020310 . 991822 1 new goroutine 8: text/template/parse.lex·dwrap·1
0.026551163 . 5530853 1 region package started (duration: 9.217294ms)
0.026554368 . 3205 1 name=jets dir=/Users/kyle/projects/sqlc/examples/python language=python
0.026556804 . 2436 1 region parse started (duration: 3.491005ms)
0.030051911 . 3495107 1 region codegen started (duration: 5.711931ms)
0.030213937 . 162026 1 new goroutine 20: text/template/parse.lex·dwrap·1
0.031099938 . 886001 1 new goroutine 38: text/template/parse.lex·dwrap·1
0.035772637 . 4672699 1 region package started (duration: 10.267039ms)
0.035775688 . 3051 1 name=ondeck dir=/Users/kyle/projects/sqlc/examples/python language=python
0.035778150 . 2462 1 region parse started (duration: 4.094518ms)
0.039877181 . 4099031 1 region codegen started (duration: 6.156341ms)
0.040010771 . 133590 1 new goroutine 39: text/template/parse.lex·dwrap·1
0.040894567 . 883796 1 new goroutine 40: text/template/parse.lex·dwrap·1
0.046042779 . 5148212 1 region writefiles started (duration: 1.718259ms)
0.047767781 . 1725002 1 task end
```
### processplugins
Setting this value to `0` disables process-based plugins. If a process-based
plugin is declared in the configuration file, running any `sqlc` command will
return an error.
`SQLCDEBUG=processplugins=0`
### dumpvetenv
The `dumpvetenv` command prints the variables available to a `sqlc vet` rule
during evaluation.
`SQLCDEBUG=dumpvetenv=1`
### dumpexplain
The `dumpexplain` command prints the JSON-formatted result from running
`EXPLAIN ...` on a query when a `sqlc vet` rule evaluation requires its output.
`SQLCDEBUG=dumpexplain=1`
## SQLCTMPDIR
If specified, use the given directory as the base for temporary folders. Only
applies when using WASM-based codegen plugins. When not specified, this
defaults to passing an empty string to
[`os.MkdirTemp`](https://pkg.go.dev/os#MkdirTemp).

View File

@@ -0,0 +1,34 @@
# Database and language support
| Language | Plugin | MySQL | PostgreSQL | SQLite |
| ---------- | ---------------------------------------------------------------------- | ------ | ---------- | --------------- |
| Go | (built-in) | Stable | Stable | Beta |
| Go | [sqlc-gen-go](https://github.com/sqlc-dev/sqlc-gen-go) | Stable | Stable | Beta |
| Kotlin | [sqlc-gen-kotlin](https://github.com/sqlc-dev/sqlc-gen-kotlin) | Beta | Beta | Not implemented |
| Python | [sqlc-gen-python](https://github.com/sqlc-dev/sqlc-gen-python) | Beta | Beta | Not implemented |
| TypeScript | [sqlc-gen-typescript](https://github.com/sqlc-dev/sqlc-gen-typescript) | Beta | Beta | Not implemented |
## Community language support
New languages can be added via [plugins](../guides/plugins.md).
| Language | Plugin | MySQL | PostgreSQL | SQLite |
| -------- | ------------------------------------------------------------------------------------- | ------ | ---------- | ------ |
| C# | [DaredevilOSS/sqlc-gen-csharp](https://github.com/DaredevilOSS/sqlc-gen-csharp) | Stable | Stable | Stable |
| F# | [kaashyapan/sqlc-gen-fsharp](https://github.com/kaashyapan/sqlc-gen-fsharp) | N/A | Beta | Beta |
| Java | [tandemdude/sqlc-gen-java](https://github.com/tandemdude/sqlc-gen-java) | Beta | Beta | N/A |
| PHP | [lcarilla/sqlc-plugin-php-dbal](https://github.com/lcarilla/sqlc-plugin-php-dbal) | Beta | N/A | N/A |
| Ruby | [DaredevilOSS/sqlc-gen-ruby](https://github.com/DaredevilOSS/sqlc-gen-ruby) | Beta | Beta | Beta |
| Zig | [tinyzimmer/sqlc-gen-zig](https://github.com/tinyzimmer/sqlc-gen-zig) | N/A | Beta | Beta |
| Python | [rayakame/sqlc-gen-better-python](https://github.com/rayakame/sqlc-gen-better-python) | Beta | Stable | Stable |
| Rust | [mathematic-inc/sqlc-gen-sqlx](https://github.com/mathematic-inc/sqlc-gen-sqlx) | N/A | Beta | N/A |
| \[Any\] | [fdietze/sqlc-gen-from-template](https://github.com/fdietze/sqlc-gen-from-template) | Stable | Stable | Stable |
Plugins developed by our Community can also be found using our
[github topic](https://github.com/topics/sqlc-plugin).
## Community projects
| Language | Project | MySQL | PostgreSQL | SQLite |
| -------- | ----------------------------------------------------------------- | ------ | ---------- | ------ |
| Gleam | [daniellionel01/parrot](https://github.com/daniellionel01/parrot) | Stable | Stable | Stable |

119
docs/reference/macros.md Normal file
View File

@@ -0,0 +1,119 @@
# Macros
## `sqlc.arg`
Attach a name to a parameter in a SQL query. This macro expands to an
engine-specific parameter placeholder. The name of the parameter is noted and
used during code generation.
```sql
-- name: GetAuthorByName :one
SELECT *
FROM authors
WHERE lower(name) = sqlc.arg(name);
-- >>> EXPANDS TO >>>
-- name: GetAuthorByName :one
SELECT *
FROM authors
WHERE lower(name) = ?;
```
See more examples in [Naming parameters](../howto/named_parameters.md).
## `sqlc.embed`
Embedding allows you to reuse existing model structs in more queries, resulting
in less manual serialization work. First, imagine we have the following schema
with students and test scores.
```sql
CREATE TABLE students (
id bigserial PRIMARY KEY,
name text,
age integer
);
CREATE TABLE test_scores (
student_id bigint,
score integer,
grade text
);
```
```sql
-- name: GetStudentAndScore :one
SELECT sqlc.embed(students), sqlc.embed(test_scores)
FROM students
JOIN test_scores ON test_scores.student_id = students.id
WHERE students.id = $1;
-- >>> EXPANDS TO >>>
-- name: GetStudentAndScore :one
SELECT students.*, test_scores.*
FROM students
JOIN test_scores ON test_scores.student_id = students.id
WHERE students.id = $1;
```
The Go method will return a struct with a field for the `Student` and field for
the test `TestScore` instead of each column existing on the struct.
```go
type GetStudentAndScoreRow struct {
Student Student
TestScore TestScore
}
func (q *Queries) GetStudentAndScore(ctx context.Context, id int64) (GetStudentAndScoreRow, error) {
// ...
}
```
See a full example in [Embedding structs](../howto/embedding.md).
## `sqlc.narg`
The same as `sqlc.arg`, but always marks the parameter as nullable.
```sql
-- name: GetAuthorByName :one
SELECT *
FROM authors
WHERE lower(name) = sqlc.narg(name);
-- >>> EXPANDS TO >>>
-- name: GetAuthorByName :one
SELECT *
FROM authors
WHERE LOWER(name) = ?;
```
See more examples in [Naming parameters](../howto/named_parameters.md).
## `sqlc.slice`
For drivers that do not support passing slices to the IN operator, the
`sqlc.slice` macro generates a dynamic query at runtime with the correct
number of parameters.
```sql
/* name: SelectStudents :many */
SELECT * FROM students
WHERE age IN (sqlc.slice("ages"))
-- >>> EXPANDS TO >>>
/* name: SelectStudents :many */
SELECT id, name, age FROM authors
WHERE age IN (/*SLICE:ages*/?)
```
Since the `/*SLICE:ages*/` placeholder is dynamically replaced on a per-query
basis, this macro can't be used with prepared statements.
See a full example in [Passing a slice as a parameter to a
query](../howto/select.md#mysql-and-sqlite).

View File

@@ -0,0 +1,230 @@
# Query annotations
sqlc requires each query to have a small comment indicating the name and
command. The format of this comment is as follows:
```sql
-- name: <name> <command>
```
## `:exec`
The generated method will return the error from
[ExecContext](https://golang.org/pkg/database/sql/#DB.ExecContext).
```sql
-- name: DeleteAuthor :exec
DELETE FROM authors
WHERE id = $1;
```
```go
func (q *Queries) DeleteAuthor(ctx context.Context, id int64) error {
_, err := q.db.ExecContext(ctx, deleteAuthor, id)
return err
}
```
## `:execresult`
The generated method will return the [sql.Result](https://golang.org/pkg/database/sql/#Result) returned by
[ExecContext](https://golang.org/pkg/database/sql/#DB.ExecContext).
```sql
-- name: DeleteAllAuthors :execresult
DELETE FROM authors;
```
```go
func (q *Queries) DeleteAllAuthors(ctx context.Context) (sql.Result, error) {
return q.db.ExecContext(ctx, deleteAllAuthors)
}
```
## `:execrows`
The generated method will return the number of affected rows from the
[result](https://golang.org/pkg/database/sql/#Result) returned by
[ExecContext](https://golang.org/pkg/database/sql/#DB.ExecContext).
```sql
-- name: DeleteAllAuthors :execrows
DELETE FROM authors;
```
```go
func (q *Queries) DeleteAllAuthors(ctx context.Context) (int64, error) {
_, err := q.db.ExecContext(ctx, deleteAllAuthors)
// ...
}
```
## `:execlastid`
The generated method will return the number generated by the database from the
[result](https://golang.org/pkg/database/sql/#Result) returned by
[ExecContext](https://golang.org/pkg/database/sql/#DB.ExecContext).
```sql
-- name: InsertAuthor :execlastid
INSERT INTO authors (name) VALUES (?);
```
```go
func (q *Queries) InsertAuthor(ctx context.Context, name string) (int64, error) {
_, err := q.db.ExecContext(ctx, insertAuthor, name)
// ...
}
```
## `:many`
The generated method will return a slice of records via
[QueryContext](https://golang.org/pkg/database/sql/#DB.QueryContext).
```sql
-- name: ListAuthors :many
SELECT * FROM authors
ORDER BY name;
```
```go
func (q *Queries) ListAuthors(ctx context.Context) ([]Author, error) {
rows, err := q.db.QueryContext(ctx, listAuthors)
// ...
}
```
## `:one`
The generated method will return a single record via
[QueryRowContext](https://golang.org/pkg/database/sql/#DB.QueryRowContext).
```sql
-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = $1 LIMIT 1;
```
```go
func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) {
row := q.db.QueryRowContext(ctx, getAuthor, id)
// ...
}
```
## `:batchexec`
__NOTE: This command only works with PostgreSQL using the `pgx/v4` and `pgx/v5` drivers and outputting Go code.__
The generated method will return a batch object. The batch object will have
the following methods:
- `Exec`, that takes a `func(int, error)` parameter,
- `Close`, to close the batch operation early.
```sql
-- name: DeleteBook :batchexec
DELETE FROM books
WHERE book_id = $1;
```
```go
type DeleteBookBatchResults struct {
br pgx.BatchResults
ind int
}
func (q *Queries) DeleteBook(ctx context.Context, bookID []int32) *DeleteBookBatchResults {
//...
}
func (b *DeleteBookBatchResults) Exec(f func(int, error)) {
//...
}
func (b *DeleteBookBatchResults) Close() error {
//...
}
```
## `:batchmany`
__NOTE: This command only works with PostgreSQL using the `pgx/v4` and `pgx/v5` drivers and outputting Go code.__
The generated method will return a batch object. The batch object will have
the following methods:
- `Query`, that takes a `func(int, []T, error)` parameter, where `T` is your query's return type
- `Close`, to close the batch operation early.
```sql
-- name: BooksByTitleYear :batchmany
SELECT * FROM books
WHERE title = $1 AND year = $2;
```
```go
type BooksByTitleYearBatchResults struct {
br pgx.BatchResults
ind int
}
type BooksByTitleYearParams struct {
Title string `json:"title"`
Year int32 `json:"year"`
}
func (q *Queries) BooksByTitleYear(ctx context.Context, arg []BooksByTitleYearParams) *BooksByTitleYearBatchResults {
//...
}
func (b *BooksByTitleYearBatchResults) Query(f func(int, []Book, error)) {
//...
}
func (b *BooksByTitleYearBatchResults) Close() error {
//...
}
```
## `:batchone`
__NOTE: This command only works with PostgreSQL using the `pgx/v4` and `pgx/v5` drivers and outputting Go code.__
The generated method will return a batch object. The batch object will have
the following methods:
- `QueryRow`, that takes a `func(int, T, error)` parameter, where `T` is your query's return type
- `Close`, to close the batch operation early.
```sql
-- name: CreateBook :batchone
INSERT INTO books (
author_id,
isbn
) VALUES (
$1,
$2
)
RETURNING book_id, author_id, isbn
```
```go
type CreateBookBatchResults struct {
br pgx.BatchResults
ind int
}
type CreateBookParams struct {
AuthorID int32 `json:"author_id"`
Isbn string `json:"isbn"`
}
func (q *Queries) CreateBook(ctx context.Context, arg []CreateBookParams) *CreateBookBatchResults {
//...
}
func (b *CreateBookBatchResults) QueryRow(f func(int, Book, error)) {
//...
}
func (b *CreateBookBatchResults) Close() error {
//...
}
```
## `:copyfrom`
__NOTE: This command is driver and package specific, see [how to insert](../howto/insert.md#using-copyfrom)
This command is used to insert rows a lot faster than sequential inserts.

72
docs/toc.yaml Normal file
View File

@@ -0,0 +1,72 @@
# Navigation for the sqlc documentation site.
#
# Every page in docs/ must appear exactly once, either in a section or in
# the unlisted set. Unlisted pages are published but do not appear in the
# sidebar.
index: index.md
sections:
- title: Overview
pages:
- overview/install.md
- title: Tutorials
pages:
- tutorials/getting-started-mysql.md
- tutorials/getting-started-postgresql.md
- tutorials/getting-started-sqlite.md
- title: Commands
pages:
- howto/analyze.md
- howto/fmt.md
- howto/generate.md
- howto/parse.md
- howto/push.md
- howto/verify.md
- howto/vet.md
- title: How-to Guides
pages:
- howto/select.md
- howto/query_count.md
- howto/insert.md
- howto/update.md
- howto/delete.md
- howto/prepared_query.md
- howto/transactions.md
- howto/named_parameters.md
- howto/ddl.md
- howto/structs.md
- howto/embedding.md
- howto/overrides.md
- howto/rename.md
- title: sqlc Cloud
pages:
- howto/managed-databases.md
- title: Reference
pages:
- reference/changelog.md
- reference/cli.md
- reference/config.md
- reference/datatypes.md
- reference/environment-variables.md
- reference/language-support.md
- reference/macros.md
- reference/query-annotations.md
- title: Conceptual Guides
pages:
- howto/ci-cd.md
- guides/using-go-and-pgx.md
- guides/plugins.md
- guides/development.md
- guides/privacy.md
unlisted:
- guides/migrating-off-hosted-managed-databases.md
- guides/migrating-to-sqlc-gen-kotlin.md
- guides/migrating-to-sqlc-gen-python.md

View File

@@ -0,0 +1,221 @@
# Getting started with MySQL
This tutorial assumes that the latest version of sqlc is
[installed](../overview/install.md) and ready to use.
We'll generate Go code here, but other
[language plugins](../reference/language-support.md) are available. You'll
naturally need the Go toolchain if you want to build and run a program with the
code sqlc generates, but sqlc itself has no dependencies.
At the end, you'll push your SQL queries to [sqlc Cloud](https://dashboard.sqlc.dev/) for further insights and analysis.
## Setting up
Create a new directory called `sqlc-tutorial` and open it up.
Initialize a new Go module named `tutorial.sqlc.dev/app`
```shell
go mod init tutorial.sqlc.dev/app
```
sqlc looks for either a `sqlc.(yaml|yml)` or `sqlc.json` file in the current
directory. In our new directory, create a file named `sqlc.yaml` with the
following contents:
```yaml
version: "2"
sql:
- engine: "mysql"
queries: "query.sql"
schema: "schema.sql"
gen:
go:
package: "tutorial"
out: "tutorial"
```
## Schema and queries
sqlc needs to know your database schema and queries in order to generate code.
In the same directory, create a file named `schema.sql` with the following
content:
```sql
CREATE TABLE authors (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name text NOT NULL,
bio text
);
```
Next, create a `query.sql` file with the following four queries:
```sql
-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = ? LIMIT 1;
-- name: ListAuthors :many
SELECT * FROM authors
ORDER BY name;
-- name: CreateAuthor :execresult
INSERT INTO authors (
name, bio
) VALUES (
?, ?
);
-- name: DeleteAuthor :exec
DELETE FROM authors
WHERE id = ?;
```
## Generating code
You are now ready to generate code. You shouldn't see any output when you run
the `generate` subcommand, unless something goes wrong:
```shell
sqlc generate
```
You should now have a `tutorial` subdirectory with three files containing Go
source code. These files comprise a Go package named `tutorial`:
```
├── go.mod
├── query.sql
├── schema.sql
├── sqlc.yaml
└── tutorial
├── db.go
├── models.go
└── query.sql.go
```
## Using generated code
You can use your newly-generated `tutorial` package from any Go program.
Create a file named `tutorial.go` and add the following contents:
```go
package main
import (
"context"
"database/sql"
"log"
"reflect"
_ "github.com/go-sql-driver/mysql"
"tutorial.sqlc.dev/app/tutorial"
)
func run() error {
ctx := context.Background()
db, err := sql.Open("mysql", "user:password@/dbname?parseTime=true")
if err != nil {
return err
}
queries := tutorial.New(db)
// list all authors
authors, err := queries.ListAuthors(ctx)
if err != nil {
return err
}
log.Println(authors)
// create an author
result, err := queries.CreateAuthor(ctx, tutorial.CreateAuthorParams{
Name: "Brian Kernighan",
Bio: sql.NullString{String: "Co-author of The C Programming Language and The Go Programming Language", Valid: true},
})
if err != nil {
return err
}
insertedAuthorID, err := result.LastInsertId()
if err != nil {
return err
}
log.Println(insertedAuthorID)
// get the author we just inserted
fetchedAuthor, err := queries.GetAuthor(ctx, insertedAuthorID)
if err != nil {
return err
}
// prints true
log.Println(reflect.DeepEqual(insertedAuthorID, fetchedAuthor.ID))
return nil
}
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}
```
Before this code will compile you'll need to fetch the relevant MySQL driver:
```shell
go get github.com/go-sql-driver/mysql
go build .
```
The program should compile without errors. To make that possible, sqlc generates
readable, **idiomatic** Go code that you otherwise would've had to write
yourself. Take a look in `tutorial/query.sql.go`.
Of course for this program to run successfully you'll need
to compile after replacing the database connection parameters in the call to
`sql.Open()` with the correct parameters for your database. And your
database must have the `authors` table as defined in `schema.sql`.
You should now have a working program using sqlc's generated Go source code,
and hopefully can see how you'd use sqlc in your own real-world applications.
## Query verification
[sqlc Cloud](https://dashboard.sqlc.dev) provides additional verification, catching subtle bugs. To get started, create a
[dashboard account](https://dashboard.sqlc.dev). Once you've signed in, create a
project and generate an auth token. Add your project's ID to the `cloud` block
to your sqlc.yaml.
```yaml
version: "2"
cloud:
# Replace <PROJECT_ID> with your project ID from the sqlc Cloud dashboard
project: "<PROJECT_ID>"
sql:
- engine: "mysql"
queries: "query.sql"
schema: "schema.sql"
gen:
go:
package: "tutorial"
out: "tutorial"
```
Replace `<PROJECT_ID>` with your project ID from the sqlc Cloud dashboard. It
will look something like `01HA8SZH31HKYE9RR3N3N3TSJM`.
And finally, set the `SQLC_AUTH_TOKEN` environment variable:
```shell
export SQLC_AUTH_TOKEN="<your sqlc auth token>"
```
```shell
$ sqlc push --tag tutorial
```

View File

@@ -0,0 +1,248 @@
# Getting started with PostgreSQL
This tutorial assumes that the latest version of sqlc is
[installed](../overview/install.md) and ready to use.
We'll generate Go code here, but other
[language plugins](../reference/language-support.md) are available. You'll
naturally need the Go toolchain if you want to build and run a program with the
code sqlc generates, but sqlc itself has no dependencies.
At the end, you'll push your SQL queries to [sqlc
Cloud](https://dashboard.sqlc.dev/) for further insights and analysis.
## Setting up
Create a new directory called `sqlc-tutorial` and open it up.
Initialize a new Go module named `tutorial.sqlc.dev/app`:
```shell
go mod init tutorial.sqlc.dev/app
```
sqlc looks for either a `sqlc.(yaml|yml)` or `sqlc.json` file in the current
directory. In our new directory, create a file named `sqlc.yaml` with the
following contents:
```yaml
version: "2"
sql:
- engine: "postgresql"
queries: "query.sql"
schema: "schema.sql"
gen:
go:
package: "tutorial"
out: "tutorial"
sql_package: "pgx/v5"
```
## Schema and queries
sqlc needs to know your database schema and queries in order to generate code.
In the same directory, create a file named `schema.sql` with the following
content:
```sql
CREATE TABLE authors (
id BIGSERIAL PRIMARY KEY,
name text NOT NULL,
bio text
);
```
Next, create a `query.sql` file with the following five queries:
```sql
-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = $1 LIMIT 1;
-- name: ListAuthors :many
SELECT * FROM authors
ORDER BY name;
-- name: CreateAuthor :one
INSERT INTO authors (
name, bio
) VALUES (
$1, $2
)
RETURNING *;
-- name: UpdateAuthor :exec
UPDATE authors
set name = $2,
bio = $3
WHERE id = $1;
-- name: DeleteAuthor :exec
DELETE FROM authors
WHERE id = $1;
```
If you prefer, you can alter the `UpdateAuthor` query to return the updated
record:
```sql
-- name: UpdateAuthor :one
UPDATE authors
set name = $2,
bio = $3
WHERE id = $1
RETURNING *;
```
## Generating code
You are now ready to generate code. You shouldn't see any output when you run
the `generate` subcommand, unless something goes wrong:
```shell
sqlc generate
```
You should now have a `tutorial` subdirectory with three files containing Go
source code. These files comprise a Go package named `tutorial`:
```
├── go.mod
├── query.sql
├── schema.sql
├── sqlc.yaml
└── tutorial
├── db.go
├── models.go
└── query.sql.go
```
## Using generated code
You can use your newly-generated `tutorial` package from any Go program.
Create a file named `tutorial.go` and add the following contents:
```go
package main
import (
"context"
"log"
"reflect"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
"tutorial.sqlc.dev/app/tutorial"
)
func run() error {
ctx := context.Background()
conn, err := pgx.Connect(ctx, "user=pqgotest dbname=pqgotest sslmode=verify-full")
if err != nil {
return err
}
defer conn.Close(ctx)
queries := tutorial.New(conn)
// list all authors
authors, err := queries.ListAuthors(ctx)
if err != nil {
return err
}
log.Println(authors)
// create an author
insertedAuthor, err := queries.CreateAuthor(ctx, tutorial.CreateAuthorParams{
Name: "Brian Kernighan",
Bio: pgtype.Text{String: "Co-author of The C Programming Language and The Go Programming Language", Valid: true},
})
if err != nil {
return err
}
log.Println(insertedAuthor)
// get the author we just inserted
fetchedAuthor, err := queries.GetAuthor(ctx, insertedAuthor.ID)
if err != nil {
return err
}
// prints true
log.Println(reflect.DeepEqual(insertedAuthor, fetchedAuthor))
return nil
}
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}
```
Before this code will compile you'll need to fetch the relevant PostgreSQL
driver. You can use `lib/pq` with the standard library's `database/sql`
package, but in this tutorial we've used `pgx/v5`:
```shell
go get github.com/jackc/pgx/v5
go build .
```
The program should compile without errors. To make that possible, sqlc generates
readable, **idiomatic** Go code that you otherwise would've had to write
yourself. Take a look in `tutorial/query.sql.go`.
Of course for this program to run successfully you'll need
to compile after replacing the database connection parameters in the call to
`pgx.Connect()` with the correct parameters for your database. And your
database must have the `authors` table as defined in `schema.sql`.
You should now have a working program using sqlc's generated Go source code,
and hopefully can see how you'd use sqlc in your own real-world applications.
## Query verification
[sqlc Cloud](https://dashboard.sqlc.dev) provides additional verification, catching subtle bugs. To get started, create a
[dashboard account](https://dashboard.sqlc.dev). Once you've signed in, create a
project and generate an auth token. Add your project's ID to the `cloud` block
to your sqlc.yaml.
```yaml
version: "2"
cloud:
# Replace <PROJECT_ID> with your project ID from the sqlc Cloud dashboard
project: "<PROJECT_ID>"
sql:
- engine: "postgresql"
queries: "query.sql"
schema: "schema.sql"
gen:
go:
package: "tutorial"
out: "tutorial"
sql_package: "pgx/v5"
```
Replace `<PROJECT_ID>` with your project ID from the sqlc Cloud dashboard. It
will look something like `01HA8SZH31HKYE9RR3N3N3TSJM`.
And finally, set the `SQLC_AUTH_TOKEN` environment variable:
```shell
export SQLC_AUTH_TOKEN="<your sqlc auth token>"
```
```shell
$ sqlc push --tag tutorial
```
In the sidebar, go to the "Queries" section to see your published queries. Run
`verify` to ensure that previously published queries continue to work against
updated database schema.
```shell
$ sqlc verify --against tutorial
```

View File

@@ -0,0 +1,201 @@
# Getting started with SQLite
This tutorial assumes that the latest version of sqlc is
[installed](../overview/install.md) and ready to use.
We'll generate Go code here, but other
[language plugins](../reference/language-support.md) are available. You'll
naturally need the Go toolchain if you want to build and run a program with the
code sqlc generates, but sqlc itself has no dependencies.
## Setting up
Create a new directory called `sqlc-tutorial` and open it up.
Initialize a new Go module named `tutorial.sqlc.dev/app`
```shell
go mod init tutorial.sqlc.dev/app
```
sqlc looks for either a `sqlc.(yaml|yml)` or `sqlc.json` file in the current
directory. In our new directory, create a file named `sqlc.yaml` with the
following contents:
```yaml
version: "2"
sql:
- engine: "sqlite"
queries: "query.sql"
schema: "schema.sql"
gen:
go:
package: "tutorial"
out: "tutorial"
```
## Schema and queries
sqlc needs to know your database schema and queries in order to generate code.
In the same directory, create a file named `schema.sql` with the following
content:
```sql
CREATE TABLE authors (
id INTEGER PRIMARY KEY,
name text NOT NULL,
bio text
);
```
Next, create a `query.sql` file with the following five queries:
```sql
-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = ? LIMIT 1;
-- name: ListAuthors :many
SELECT * FROM authors
ORDER BY name;
-- name: CreateAuthor :one
INSERT INTO authors (
name, bio
) VALUES (
?, ?
)
RETURNING *;
-- name: UpdateAuthor :exec
UPDATE authors
set name = ?,
bio = ?
WHERE id = ?;
-- name: DeleteAuthor :exec
DELETE FROM authors
WHERE id = ?;
```
If you prefer, you can alter the `UpdateAuthor` query to return the updated
record:
```sql
-- name: UpdateAuthor :one
UPDATE authors
set name = ?,
bio = ?
WHERE id = ?
RETURNING *;
```
## Generating code
You are now ready to generate code. You shouldn't see any output when you run
the `generate` subcommand, unless something goes wrong:
```shell
sqlc generate
```
You should now have a `tutorial` subdirectory with three files containing Go
source code. These files comprise a Go package named `tutorial`:
```
├── go.mod
├── query.sql
├── schema.sql
├── sqlc.yaml
└── tutorial
├── db.go
├── models.go
└── query.sql.go
```
## Using generated code
You can use your newly-generated `tutorial` package from any Go program.
Create a file named `tutorial.go` and add the following contents:
```go
package main
import (
"context"
"database/sql"
_ "embed"
"log"
"reflect"
_ "modernc.org/sqlite"
"tutorial.sqlc.dev/app/tutorial"
)
//go:embed schema.sql
var ddl string
func run() error {
ctx := context.Background()
db, err := sql.Open("sqlite", ":memory:")
if err != nil {
return err
}
// create tables
if _, err := db.ExecContext(ctx, ddl); err != nil {
return err
}
queries := tutorial.New(db)
// list all authors
authors, err := queries.ListAuthors(ctx)
if err != nil {
return err
}
log.Println(authors)
// create an author
insertedAuthor, err := queries.CreateAuthor(ctx, tutorial.CreateAuthorParams{
Name: "Brian Kernighan",
Bio: sql.NullString{String: "Co-author of The C Programming Language and The Go Programming Language", Valid: true},
})
if err != nil {
return err
}
log.Println(insertedAuthor)
// get the author we just inserted
fetchedAuthor, err := queries.GetAuthor(ctx, insertedAuthor.ID)
if err != nil {
return err
}
// prints true
log.Println(reflect.DeepEqual(insertedAuthor, fetchedAuthor))
return nil
}
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}
```
Before this code will compile you'll need to fetch the relevant SQLite driver:
```shell
go get modernc.org/sqlite
go build .
```
The program should compile without errors, and run successfully. To make that
possible, sqlc generates readable, **idiomatic** Go code that you
otherwise would've had to write yourself. Take a look in `tutorial/query.sql.go`.
You should now have a working program using sqlc's generated Go source code,
and hopefully can see how you'd use sqlc in your own real-world applications.