Giter VIP home page Giter VIP logo

sqlc's Introduction

sqlc

Build Status GoDoc

sqlc is a composable, type safe and fluent API to generate nested and complex SQL queries.

Taking heavy inspiration from JOOQ, sqlc generates SQL queries for you:

var FOO sqlc.TableLike // (optionally) auto-generated by sqlc by introspecting your DDL

var db *db.DB // For integration with database/sql
var d Dialect // Either sqlite, mysql or postgres

row, err := Select(FOO.BAR).From(FOO).Where(FOO.BAZ.Eq("quux")).QueryRow(d, db)

If you don't want to use database/sql, you don't have to - ultimately sqlc is just a string building tool.

String(Dialect) is an API call to just produce the SQL string that you use in any way that you want to:

// Renders `SELECT foo.bar FROM foo WHERE foo.baz = ?`
sql := Select(FOO.BAR).From(FOO).Where(FOO.BAZ.Eq("quux")).String(d)

Installing

To install the runtime libraries and the sqlc command line tool into your $GOPATH:

$ go get github.com/relops/sqlc

Composing Queries

You can compose query objects into reusable and individually executable building blocks. For example, you can create a sub query that is in itself executable:

subQuery := Select(
	CALL_RECORDS.REGION,
	CALL_RECORDS.DURATION.Min(),
	CALL_RECORDS.DURATION.Max(),
	CALL_RECORDS.DURATION.Avg()).
	From(CALL_RECORDS).
	GroupBy(CALL_RECORDS.REGION).
	OrderBy(CALL_RECORDS.REGION)

row, err := subQuery.QueryRow(d, db)

And then you re-use the subquery as part of a new query:

row, err := SelectCount().From(subQuery).QueryRow(d, db)

Type Safety

sqlc provides type safe methods for INSERTs and UPDATEs:

result, err := InsertInto(CALL_RECORDS).
	SetString(CALL_RECORDS.IMSI, "230023741299234").
	SetTime(CALL_RECORDS.TIMESTAMP, time.Now()).
	SetInt(CALL_RECORDS.DURATION, 10).
	SetString(CALL_RECORDS.REGION, "quux").
	SetString(CALL_RECORDS.CALLING_NUMBER, "76581231298").
	SetString(CALL_RECORDS.CALLED_NUMBER, "76754238764").
	Exec(d, db)

For example, the following invocation would not compile:

...
SetTime(CALL_RECORDS.TIMESTAMP, "some string"). // Results in a compile time error
...

If you use the sqlc code generator, you can keep your application in sync with your current DB schema any divergence between your code and the DDL will be flagged by the Go compiler.

INSERTs, UPDATEs, DELETEs

The support for inserting, updating and deleting rows is basic right now:

// Renders `INSERT INTO foo (bar) VALUES (?)` on MySQL
// Renders `INSERT INTO foo (bar) VALUES ($1)` on Postgres
InsertInto(foo).SetString(bar, "quux").String(d)

// Renders `UPDATE foo SET bar = ? WHERE foo.baz = ?"` on MySQL
// Renders `UPDATE foo SET bar = $1 WHERE foo.baz = $2"` on Postgres
Update(foo).SetString(bar, "quux").Where(baz.Eq("gorp")).String(d)

// Renders `DELETE FROM foo WHERE foo.baz = ?`
Delete(foo).Where(baz.Eq("gorp")).String(d)

Currently sqlc assumes that you want to generate prepared statements and (re)bind application parameters.

Aliasing

sqlc allows you to alias your projections easily:

// Renders `SELECT foo.bar AS x, foo.baz AS y FROM foo`
Select(bar.As("x"), baz.As("y")).From(foo).String(d)

By default, columns will be qualified by the name of their parent table. You can override this by aliasing the table, in addition to aliasing just the fields:

// Renders `SELECT f.bar AS x, f.baz AS y FROM foo AS f`
Select(bar.As("x"), baz.As("y")).From(foo.As("f")).String(d)

Functions

Functions can be applied to any field and they can be nested to any depth:

// Renders `SELECT LOWER(HEX(MD5(foo.bar))) FROM foo`
Select(bar.Md5().Hex().Lower()).From(foo).String(d)

Joins

There is basic support for support for joins:

// Renders `SELECT foo.bar, quux.col FROM foo JOIN quux 
//          ON (quux.id = foo.bar AND quux.col = foo.baz)`
Select(bar, col).From(foo).Join(quux).On(id.IsEq(bar), col.IsEq(baz)).String(d)

In addition to INNER JOINs, LEFT OUTER JOINs are also supported:

// Renders `SELECT foo.bar FROM foo LEFT OUTER JOIN quux ON quux.id = foo.bar`
Select(bar).From(foo).LeftOuterJoin(quux).
			On(id.IsEq(bar)).String(d)

An arbrirary number of joins can be constructed:

// Renders `SELECT foo.bar FROM foo 
//          LEFT OUTER JOIN quux ON quux.id = foo.bar
//          LEFT OUTER JOIN gorp ON gorp.porg = foo.bar`
Select(bar).From(foo).LeftOuterJoin(quux).
			On(id.IsEq(bar)).LeftOuterJoin(gorp).
			On(porg.IsEq(bar)).String(d)

Returning From Insert

(This is a Postgres only feature)

You can specify a column from an INSERT to return back to the app:

// Renders `INSERT INTO foo (bar) VALUES ($1) RETURNING id` on Postgres
InsertInto(foo).SetString(bar, "quux").Returning(id).String(d)

Returning() returns a fetchable row that you can bind from:

var id int
row, _ := InsertInto(foo).SetString(bar, "quux").Returning(id).Fetch(d, db)
row.Scan(&id)

Code Generation

Install the sqlc command line tool:

$ go get github.com/relops/sqlc

Make sure sqlc is on your PATH (usually $GOPATH/bin).

Then point sqlc at your sqlite DB file:

$ sqlc -h
Usage:
  sqlc [OPTIONS]

Application Options:
  -f, --file=    The path to the sqlite file
  -u, --url=     The DB URL
  -o, --output=  The path to save the generated objects to
  -p, --package= The package to put the generated objects into
  -t, --type=    The type of the DB (mysql,postgres,sqlite)
  -s, --schema=  The target DB schema (required for MySQL and Postgres)

Help Options:
  -h, --help     Show this help message

Now you can use the generated objects in your app.

Database Support

  • Sqlite
  • MySQL
  • Postgres

Features

  • SELECT ... FROM ... WHERE
  • GROUP BY
  • ORDER BY (assumes ASC right now)
  • INSERTs
  • UPDATEs
  • DELETEs
  • INNER JOINS (integration test only for single columns)
  • LEFT OUTER JOINS (unit tested only, no integration test)
  • Sub queries
  • RETURNING (Postgres only)
  • Data types currently implemented:
    • VARCHAR
    • INT
    • INTEGER
    • TIMESTAMP
  • Functions (implemented on an as needs basis, easily extended):
    • COUNT
    • CAST
    • AVG
    • MAX
    • MIN
    • DIV
    • CEIL
    • MD5
    • LOWER
    • HEX
    • GROUP_CONCAT
    • TRUNC
  • Statement rendering
  • Querying via database/sql
  • Code generation of table and field objects from an exising DB schema

Building

To use the sqlc tool and runtime libraries, all that is required is a simple go get. However, if you want to build sqlc from scratch and run the integration tests, you'll need the following installed locally:

Status

Experimental - this is work in progress. Basically I'm trying to port JOOQ to Go, but I don't know yet whether it will work.

sqlc's People

Contributors

0x6e6562 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

sqlc's Issues

CAST types passed as strings

Currently, to cast a field to a given type, you need to supply the string representation of the underlying SQL type. This is neither type safe nor portable. We should introduce a strongly typed representation that can be adjusted for target dialects.

suggestion to improve the API

I think the API would be nicer if you start with the db. I.e. db.Select(...).From(...).Query(). It also avoids having to specify the dialect each time.

I attempted to do this on my fork (see alokmenghrajani@f441c53), but I'm not sure if you care about keeping the API backwards compatible.

RETURNING syntax

it'd be really nice to be able to automatically produce syntax RETURNING id. i can hack around it with other methods for now.

Target schema is baked into MySQL generator

Right now the MySQl generator assumes that the target schema is called sqlc, which only works for the integration tests. We should probably factor this out by introducing command line options for the MySQL DSN.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.