Generate type safe Go from SQL

sqlc: A SQL Compiler

go Go Report Card

sqlc generates type-safe code from SQL. Here's how it works:

  1. You write queries in SQL.
  2. You run sqlc to generate code with type-safe interfaces to those queries.
  3. You write application code that calls the generated code.

Check out an interactive example to see it in action.

Overview

Sponsors

sqlc development is funded by our generous sponsors, including the following companies:

If you use sqlc at your company, please consider becoming a sponsor today.

Sponsors receive priority support via the sqlc Slack organization.

Acknowledgements

sqlc was inspired by PugSQL and HugSQL.

Comments
  • SQLite support

    SQLite support

    Hi all, great works on this project. Is it possible to add SQLite support ? Right now I'm working on embedded device and often uses SQLite, so it will be awesome for me.

  • Add support for pgx

    Add support for pgx

    Get out the trumpets and ready the 21-gun salute, lib/pq is deprecated (#470). This means it's time to support it's successor, pgx.

    This will be the main tracking issue for pgx. It supersedes #28, as I have no intention of adding support for any additional PostgreSQL drivers beyond pgx.

  • Kotlin prototype

    Kotlin prototype

    Updated TODO:

    • [x] New config format https://github.com/kyleconroy/sqlc/issues/302
    • [x] Adds CI with tests for authors https://github.com/mightyguava/sqlc/pull/2
    • [x] Tests for booktest and ondeck https://github.com/mightyguava/sqlc/pull/4
    • [x] move ktgen.go to kotlin/gen.go https://github.com/mightyguava/sqlc/pull/3
    • [x] Rewrite $1 to ? in query parsing instead of with a HACK in code generation https://github.com/mightyguava/sqlc/pull/5
    • [x] Get some Kotlin folks to review generated code https://github.com/mightyguava/sqlc/pull/6
    • [ ] Support MySQL (probably needs to wait for experimental MySQL parser to stabilize a bit)

    I wanted to learn more about how sqlc works, so I took a stab at https://github.com/kyleconroy/sqlc/issues/287 anyways to see how hard it would be.

    Here's a prototype implementation for Kotlin. It's pretty rough around the edges but tests pass, and I was able to generate and compile all of the existing examples in Kotlin. authors has tests written in Kotlin to confirm that the generated code works. I haven't gotten to the rest. The sqlc codebase is pretty easy to work in! I'm impressed.

    I basically just copied gen.go into ktgen.go and renamed all the functions. It should really be its own package, but that can come if this PR actually has a chance of getting merged 😄While the code follows the same patterns as the Go generator, there were enough changes that I'm not sure much code reuse is possible.

    I split out the generated examples and a working gradle project because it would pollute this PR too much. They can be viewed here: https://github.com/mightyguava/sqlc/pull/1

    Things that work:

    • Primitives
    • NULL primitives
    • Generating schema, param, and return classes
    • one/many/exec queries

    Things that compile but I haven't tested:

    • Enums
    • Dates
    • NULLS for these types
    • Arrays
    • execRow queries

    Things that don't work:

    • Type overrides - there's no fancy Scan() interface in JDBC to support arbitrary types, so this'll require generating code to call Adapter classes for individual types. Not hard, probably, just didn't seem worthwhile exploring in a prototype
    • JSON tags - no such thing in Java/Kotlin
    • MySQL - that part of the codebase seems to be iterating rapidly, so I decided to just look at Postgres for now.

    Things that work differently:

    • Numbered parameters - JDBC seems to only support ? as placeholders. I had to write a HACK to convert things like $1 to ?. This is buggy and terrible. It also means that you can't use $1 multiple times in the same query to reference the same value. If the AST was available in the generator part then I can probably figure out how to do something better.
    • I only generate a single QueriesImpl.kt for the queries instead one for each sql file. This is because you can't have a class span multiple files in Kotlin.
    • Prepared statements - According to both JDBC and Postgres JDBC Driver docs, prepared statements are implicitly cached, so the EmitPreparedQueries option is likely unneeded here.

    Things to think about:

    • The code is in Kotlin, meaning Java projects can use it, but they need to have the Kotlin compiler. An alternative is to have sqlc just generate a self-contained module that will produce a jar for the project to depend on. I could have generated Java instead, but that would have resulted in at least 5X more generated LOC of mostly boilerplate (though I guess technically everything sqlc generates is boilerplate). I also just don't like writing Java.
    • Remove the interface option, make it required: Unlike Go, interfaces are basically mandatory in the JVM if you want to do proper unit testing. You can't just create interfaces for arbitrary classes.
    • I haven't actually spent that much time working with JDBC before, so some of the generated code could be questionable. More tests will help tell!

    Please take a look! While I'd love for this code to get merged, I understand if you don't want to take on the additional maintenance burden that another language would add. Though, I wouldn't mind helping to maintain it.

  • Fix complex packages import paths

    Fix complex packages import paths

    EDIT Please skip directly to this reply as none of what I made matters anymore since I found another import path case which fails with this current PR.

    See #462 and #255

    Attempting to fix the parsing of complex package names by leveraging regex capabilities to capture the relevant parts.

    After smashing my head for an hour I asked for help on Reddit, details of the regex expression can be found here, credits for the regex go to /u/Lee_Dailey.

    I've also added the relevant test entries which used to fail and now they pass.


    Notes

    I've left the original code as commented out for reference, it should be removed if the PR is to be accepted to avoid polluting the code with unnecessary lines.

    The regex expression can be easily batch tested here to ensure it satisfies package import names, I am not aware of any other strange import path other than gopkg.in/guregu/null.v3/zero. To nitpick the issue we should find other packages with complex import paths. I can't guarantee that this will work with every package ever.

    Two assumptions on fully qualified names have been made to build the regex:

    1. A type name is always in the form of pkgName.TypeName
    2. The import path ends with the rightmost forward slash

    This led to formulate these two regex:

    • To match a package type: match everything backwards from the end of the string to the first encountered forward slash /
    • To match a package name: match everything forward from the start of the string till the last dot found
  • RFC: nullability (and other metadata) for input arguments / parameters to a query

    RFC: nullability (and other metadata) for input arguments / parameters to a query

    What do you want to change?

    Kudos Before I start, I wanted to give a huge kudos for sqlc - I love it. As a backend developer who knows SQL very well, I fight every single ORM I have used trying to do any SQL more complicated than CRUD. Thank you for creating this.

    Background I use sqlc alongside Postgres, as sort of a foreign function interface to SQL. I manage a PostgreSQL database with about 100 different tables and working in Typescript and Go to support every stage of solar operations for Bright. We do not currently use sqlc at Bright - but I do use it personally, but I am evaluating it Bright as well.

    The types of problems I work on are not always CRUD-y (though sqlc works really well if they are). And the challenge I am facing is that SQL is a little less-expressive than the target languages in some cases, and therefore using sqlc as a FFI is a little clunky. A quick glance through the some open issues, shows that "nullability" is one of those deficiencies. sqlc does its best to always "do the right thing" and that has gotten it very far indeed. But I think a simple change can give developers full control, and allow for sqlc to keep getting smarter (better interred mappings / types).

    Say for example, instead of finding a really good GeoJSON library in my target language, I wanted to rely on PostGIS.

    - name: WKBToGeoJSON :one
    select ST_AsGeoJSON(ST_GeomFromWKB(sqlc.arg('wkb_bytes'))::text as output;
    

    I would love for this Go code to be generated:

    func (q *Queries) WKBToGeoJSON(ctx context.Context, db DBTX, wkbBytes []byte) (string, error) {
        // ...
    }
    

    Or perhaps a more common use case, partial updates

    -- name: EditThing :exec
    update thing
    set
      name = coalesce(sqlc.arg('name'), name),
      description = coalesce(sqlc.arg('description'), description),
      status = coalesce(sqlc.arg('status'), status)
    where thing.id = sqlc.arg(id)
    
    -- name, description and status are all nullable arguments, id is not.
    

    Proposal I think sqlc should expose a way (like overrides) in the query itself to control aspects of the generated code in the target languages.

    Allow sqlc.arg(name) to accept more variadic arguments (similar to jsonb_build_object) to build up string key, and json value pairs of "configuration" for that arguments. I think sqlc itself should not really know too much about the semantics of these key/value pairs, and just pass them along to the code generators in the target language.

    -- name: EditThing :exec
    update thing
    set
      name = coalesce(sqlc.arg('new_name', 'nullable', true, 'type', 'string'), name),
      description = coalesce(sqlc.arg('description', nullable, true), description),
      status = coalesce(sqlc.arg('status', 'nullable', true), status)
    where thing.id = sqlc.arg(id)
    

    This also allows the developer to control the API interface much better, even if the database is a little wacky. Imagine if there was a column name that was nullable for historical reasons, but any new insert to name it should be non null. sqlc should support that use case too.

    I am not a super-polyglot, but if there were a C++ backend for sqlc, you probably wouldn't just want nullable but also maybe an option for the type of pointer that should be generated raw pointer? std::shared_ptr? std::unique_ptr? boost::? std::optional ?

    -- name: GetThingForCpp :one
    select
      id,
      first_name,
      last_name,
      sqlc.output(concat(first_name, ' ', last_name), 'nullable', false, 'ref_counted', true) as display_name
    where ....
    

    This is very similar to overrides, but on a query-by-query basis, and expressed directly in SQL instead of away from the code in a config file.

    Implementation I got pretty far along in the implementation, and I'd be happy to push it all the way through - but I hit a big snag at the SQL rewriting. Rewriting the AST is no big deal (and I had the code working for that). But the way in which sqlc rewrites the original source seems to be engine independent, and a little hacky. Performing the source rewrites with an AST "deparse" (like in pg_query_go) would solve this with almost no problem. Or if the AST has more source location info in it (not just a start location, but also an end location), that might work too. But this seemed like a bigger refactor, and I wanted to get feedback on it first.

    I'd love to know your thoughts @kyleconroy and from the general sqlc community too. I'd be happy to help and make this a reality.

    What database engines need to be changed?

    PostgreSQL, MySQL

    What programming language backends need to be changed?

    No response

  • Update configuration structure to support multiple languages

    Update configuration structure to support multiple languages

    The current version of the configuration file can't support multiple languages. Packages have Go-specific settings that do not apply to other languages.

  • Feat/nullable enums

    Feat/nullable enums

    With this PR now custom Enums have a nullable structure like all the sql.NullXXXX

    The Null structure is generated for every Enum. When enums are present on the model we import database/sql/driver The database type matching is a little bit dirty I think something better can be done, let me know if you have an idea.

    Also, how should I go about creating tests for this?

  • Failing to install sqlc v1.5.0 / latest

    Failing to install sqlc v1.5.0 / latest

    Issue

    go install github.com/kyleconroy/sqlc/cmd/sqlc seems to be failing due to dolphin changes

    How to reproduce

    As there are some C dependencies in sqlc, we have the following target on our Makefile:

    install-generators:
    	# more tools...
    	tmp_dir=sqlc-$(shell date +'%s') && mkdir -p /tmp/$$tmp_dir && cd /tmp/$$tmp_dir && go mod init tmp && GO11MODULE=on go install github.com/kyleconroy/sqlc/cmd/sqlc && cd - # it has C dependencies that would be a headache using go mod vendor
    

    But now it crashes with the following error:

    go: creating new go.mod: module tmp
    go: finding module for package github.com/kyleconroy/sqlc/cmd/sqlc
    go: found github.com/kyleconroy/sqlc/cmd/sqlc in github.com/kyleconroy/sqlc v1.5.0
    # github.com/kyleconroy/sqlc/internal/engine/dolphin
    /Users/brunosilva/go/pkg/mod/github.com/kyleconroy/[email protected]/internal/engine/dolphin/convert.go:197:13: n.Schema undefined (type *"github.com/pingcap/parser/ast".FuncCallExpr has no field or method Schema)
    /Users/brunosilva/go/pkg/mod/github.com/kyleconroy/[email protected]/internal/engine/dolphin/convert.go:216:14: n.Offset undefined (type *"github.com/pingcap/parser/ast".FuncCallExpr has no field or method Offset)
    

    Solution for now:

    We've changed the script to download a specific version for now

    install-generators:
    	# more tools...
    	tmp_dir=sqlc-$(shell date +'%s') && mkdir -p /tmp/$$tmp_dir && cd /tmp/$$tmp_dir && go mod init tmp && go mod edit -require github.com/kyleconroy/[email protected] && go install github.com/kyleconroy/sqlc/cmd/sqlc && cd - # it has C dependencies that would be a headache using go mod vendor
    

    EDIT: Above solution as a bash/shell script (above one is for Makefile):

    tmp_dir=sqlc-$(date +'%s') && \
    mkdir -p /tmp/$tmp_dir && \
    cd /tmp/$tmp_dir && \
    go mod init tmp && \
    go mod edit -replace github.com/pingcap/parser=github.com/kyleconroy/[email protected] && \
    go get github.com/kyleconroy/sqlc/cmd/[email protected] && \
    cd - # it has C dependencies that would be a headache using go mod vendor
    
  • syntax error at or near

    syntax error at or near "$"

    Copying the 25 line sample config exactly as shown, pasting it into a file, and running it with sqlc compile or sqlc generate leaves me with the following errors:

    test.sql:9:15: syntax error at or near "$"
    test.sql:8:1: failed to parse query leading comment
    test.sql:19:5: syntax error at or near "$"
    test.sql:20:1: syntax error at or near "2"
    test.sql:25:14: syntax error at or near "$"
    

    I tried with an sqlc init YAML file and the JSON file design in https://github.com/kyleconroy/sqlc/tree/master/examples/authors.

    sqlc version: v1.2.1-devel

  • Add pg_tables and pg_views to catalog

    Add pg_tables and pg_views to catalog

    Fixes: https://github.com/kyleconroy/sqlc/issues/1747

    Problem - I was unable to write a query against pg_timezone_names.

    Actual failing query

    select
      name,
      abbrev,
      utc_offset,
      to_char((current_timestamp at time zone name), 'HH:MI am') as current_time
    from pg_catalog.pg_timezone_names
    order by utc_offset;
    

    This because sqlc did not know about these built-in tables / views.

    Warning I tried to make sqlc-pg-gen and make regen, but I was getting slightly different output, so in this commit I only committed the changes that affected the tables, not the existing functions (which I do not know why they were changed, perhaps a different version of postgres).

  • Add support for emitting pointer types for nullable columns

    Add support for emitting pointer types for nullable columns

    pgx/v4 supports passing and scanning into pointer types for nullable columns instead of using the standard library Null<Type> representation, which is super handy if you wind up interfacing a lot with, say, generated Protocol Buffer files using the proto3 optional flag.

    This PR adds a new configuration option emit_pointers_for_null_types, which, as per the documentation line added:

    If true and sql_package is set to pgx/v4, generated types for nullable types are emitted as pointers (ie. *string) instead of database/sql null types (ie. NullString). Defaults to false.

    This change would be a significant quality-of-life improvement for me, but I obviously don't know if it generally fits with the philosophy of sqlc, so consider this a suggestion and please feel free to provide any feedback (including, but not limited to bike-shedding of the choice of name for the configuration parameter, if we see this feature fit for sqlc.)

    Lastly, thanks all for building this tool. It's genuinely saved me tons of hours writing the same pesky boiler plate with limited guarantees.

  • SQLC generated files do not pass errcheck checks

    SQLC generated files do not pass errcheck checks

    Version

    1.16.0

    What happened?

    When running errcheck on files generated by sqlc (https://github.com/kisielk/errcheck), the following line makes the check fail (the error is not checked):

    	defer rows.Close()
    

    Here's the generated code:

    	rows, err := q.db.QueryContext(ctx, ..., arg.Offset, arg.Limit)
    	if err != nil {
    		return nil, err
    	}
    	defer rows.Close() // this line
    
            ...
    
    	if err := rows.Close(); err != nil { // Why do we have the same line here?
    		return nil, err
    	}
    	if err := rows.Err(); err != nil {
    		return nil, err
    	}
    	return items, nil
    

    It would be nice to change the way this line is generated (or even to remove it, as rows.Close() is called at the end of the code) to make it errcheck compliant.

    Relevant log output

    No response

    Database schema

    No response

    SQL queries

    SELECT *
    FROM organizations
    ORDER BY name
    OFFSET $1 LIMIT $2;
    

    Configuration

    version: 1
    packages:
      - path: "app/sqlc"
        name: "sqlc"
        engine: "postgresql"
        schema: "./app/sqlc/schemas/"
        queries: "./app/sqlc/queries/"
        emit_json_tags: true
        emit_interface: true
    

    Playground URL

    No response

    What operating system are you using?

    Linux

    What database engines are you using?

    PostgreSQL

    What type of code are you generating?

    Go

  • syntax error at or near

    syntax error at or near "engine" In Create table sql including engine

    What do you want to change?

    Please support engine definition when creating schema create table if not exists role ( id binary(16) not null, k varchar(32) not null ) engine=InnoDB; alter table role add primary key(id);

    What database engines need to be changed?

    PostgreSQL, MySQL

    What programming language backends need to be changed?

    No response

  • Being able to mark generated files with go:build tags

    Being able to mark generated files with go:build tags

    What do you want to change?

    It could be useful to be able to emit // go:build some-tag into the golang generated files

    This way I can, for example, exclude them when running coverage tests 😇

    What database engines need to be changed?

    No response

    What programming language backends need to be changed?

    Go

  • Add time.Time to override

    Add time.Time to override

    as time.Time is not a basic Go type, and the way in which override evaluates packages, trying to swap in time.Time for date causes an error to be thrown.

  • MySQL generator doesn't enforce existence of columns

    MySQL generator doesn't enforce existence of columns

    Version

    1.15.0

    What happened?

    I'm using sqlc with MySQL. In a query, if I use bogus field names in JOIN, WHERE or ORDER BY clauses, the code generator will not complain. It seems that field names in the SELECT clause are validated, but not anywhere else.

    Relevant log output

    No response

    Database schema

    create table t1 (
      id int(11)      not null,
      s  varchar(128) not null,
      primary key (id)    
    ) 
    ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
    
    create table t2 (
      id    int(11) not null,
      t1_id int(11) not null,
      
      primary key (id),
      key t1_id (t1_id),
      foreign key (t1_id) references t1 (id)
    )
    ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
    

    SQL queries

    -- name: Broken :many
    SELECT
      t1.*
    FROM
      t1 LEFT JOIN t2 on t1.id = t2.t1_id
    WHERE
      t1.bar = 'x' AND t2.baz = 'y'
    ORDER BY
      t1.xyz > t2.abc
    

    Configuration

    No response

    Playground URL

    https://play.sqlc.dev/p/bf880aa2e19616101663a8bf3e1a4c02a99e234d1aac598c65541e5e11823488

    What operating system are you using?

    Linux

    What database engines are you using?

    MySQL

    What type of code are you generating?

    Go

  • Adding the ability to change the default scheme to generate DTO and queries

    Adding the ability to change the default scheme to generate DTO and queries

    PostgreSQL allows you to store your tables in different schemas instead of the public one.

    I haven't found the solution to generate code for the tables in the schema that differs from public. So, I have created a fix to do it.

    How it works:

    1. Place your table test in the schema, for example, test.
    2. Add the option default_schema: "test" to your sqlc.yaml
    sql:
        engine: "postgresql"
        default_schema: "test"
    
    1. In your queries file type the table name with the schema
    -- name: GetTestItem :one
    select * from "test"."test" where id=$1 limit 1;
    
Type safe SQL query builder and struct mapper for Go

sq (Structured Query) ?? ?? sq is a code-generated, type safe query builder and struct mapper for Go. ?? ?? Documentation • Reference • Examples This

Dec 19, 2022
Command line tool to generate idiomatic Go code for SQL databases supporting PostgreSQL, MySQL, SQLite, Oracle, and Microsoft SQL Server

About xo xo is a command-line tool to generate Go code based on a database schema or a custom query. xo works by using database metadata and SQL intro

Jan 8, 2023
Go fearless SQL. Sqlvet performs static analysis on raw SQL queries in your Go code base.

Sqlvet Sqlvet performs static analysis on raw SQL queries in your Go code base to surface potential runtime errors at build time. Feature highlights:

Dec 19, 2022
Query git repositories with SQL. Generate reports, perform status checks, analyze codebases. 🔍 📊

askgit askgit is a command-line tool for running SQL queries on git repositories. It's meant for ad-hoc querying of git repositories on disk through a

Jan 5, 2023
A Golang library for using SQL.

dotsql A Golang library for using SQL. It is not an ORM, it is not a query builder. Dotsql is a library that helps you keep sql files in one place and

Dec 27, 2022
a golang library for sql builder

Gendry gendry is a Go library that helps you operate database. Based on go-sql-driver/mysql, it provides a series of simple but useful tools to prepar

Dec 26, 2022
Database Abstraction Layer (dbal) for Go. Support SQL builder and get result easily (now only support mysql)

godbal Database Abstraction Layer (dbal) for go (now only support mysql) Motivation I wanted a DBAL that No ORM、No Reflect、Concurrency Save, support S

Nov 17, 2022
SQL builder and query library for golang

__ _ ___ __ _ _ _ / _` |/ _ \ / _` | | | | | (_| | (_) | (_| | |_| | \__, |\___/ \__, |\__,_| |___/ |_| goqu is an expressive SQL bu

Dec 30, 2022
SQL query builder for Go

GoSQL Query builder with some handy utility functions. Documentation For full documentation see the pkg.go.dev or GitBook. Examples // Open database a

Dec 12, 2022
A Go (golang) package that enhances the standard database/sql package by providing powerful data retrieval methods as well as DB-agnostic query building capabilities.

ozzo-dbx Summary Description Requirements Installation Supported Databases Getting Started Connecting to Database Executing Queries Binding Parameters

Dec 31, 2022
Write your SQL queries in raw files with all benefits of modern IDEs, use them in an easy way inside your application with all the profit of compile time constants

About qry is a general purpose library for storing your raw database queries in .sql files with all benefits of modern IDEs, instead of strings and co

Dec 25, 2022
Fast SQL query builder for Go

sqlf A fast SQL query builder for Go. sqlf statement builder provides a way to: Combine SQL statements from fragments of raw SQL and arguments that ma

Dec 23, 2022
💥 A lightweight DSL & ORM which helps you to write SQL in Go.
💥 A lightweight DSL & ORM which helps you to write SQL in Go.

sqlingo is a SQL DSL (a.k.a. SQL Builder or ORM) library in Go. It generates code from the database and lets you write SQL queries in an elegant way.

Jan 2, 2023
Fluent SQL generation for golang

sqrl - fat-free version of squirrel - fluent SQL generator for Go Non thread safe fork of squirrel. The same handy fluffy helper, but with extra lette

Dec 16, 2022
Fluent SQL generation for golang

Squirrel is "complete". Bug fixes will still be merged (slowly). Bug reports are welcome, but I will not necessarily respond to them. If another fork

Jan 6, 2023
GraphJin - Build APIs in 5 minutes with GraphQL. An instant GraphQL to SQL compiler.
GraphJin - Build APIs in 5 minutes with GraphQL. An instant GraphQL to SQL compiler.

GraphJin - Build APIs in 5 minutes GraphJin gives you a high performance GraphQL API without you having to write any code. GraphQL is automagically co

Jan 4, 2023
golang orm and sql builder

gosql gosql is a easy ORM library for Golang. Style: var userList []UserModel err := db.FetchAll(&userList, gosql.Columns("id","name"), gosql.

Dec 22, 2022
Analyzer: helps uncover bugs by reporting a diagnostic for mistakes of *sql.Rows usage.

sqlrows sqlrows is a static code analyzer which helps uncover bugs by reporting a diagnostic for mistakes of sql.Rows usage. Install You can get sqlro

Mar 24, 2022
LBADD: An experimental, distributed SQL database
LBADD: An experimental, distributed SQL database

LBADD Let's build a distributed database. LBADD is an experimental distributed SQL database, written in Go. The goal of this project is to build a dat

Nov 29, 2022