Convert Figma logo to code with AI

doug-martin logogoqu

SQL builder and query library for golang

2,347
205
2,347
132

Top Related Projects

Fluent SQL generation for golang

15,960

general purpose extensions to golang's database/sql

36,491

The fantastic ORM library for Golang, aims to be developer friendly

12,095

Generate type-safe code from SQL

Generate a Go ORM tailored to your database schema.

6,660

Simple and Powerful ORM for Go, support mysql,postgres,tidb,sqlite3,mssql,oracle, Moved to https://gitea.com/xorm/xorm

Quick Overview

Goqu is a powerful SQL query builder and database abstraction layer for Go. It provides an expressive and fluent API for constructing complex SQL queries, supporting multiple database dialects and offering features like automatic query generation, parameter binding, and result scanning.

Pros

  • Expressive and type-safe query building API
  • Support for multiple database dialects (PostgreSQL, MySQL, SQLite, and more)
  • Automatic query generation and parameter binding
  • Comprehensive documentation and examples

Cons

  • Learning curve for developers new to query builders
  • May introduce overhead for simple queries
  • Limited support for advanced database-specific features
  • Dependency on third-party library in projects

Code Examples

  1. Basic SELECT query:
import (
    "github.com/doug-martin/goqu/v9"
    _ "github.com/doug-martin/goqu/v9/dialect/postgres"
)

db := goqu.New("postgres", dbConnection)
ds := db.From("users").Where(goqu.Ex{"active": true})

sql, _, _ := ds.Select("id", "name", "email").ToSQL()
fmt.Println(sql)
// SELECT "id", "name", "email" FROM "users" WHERE "active" IS TRUE
  1. JOIN and ORDER BY:
sql, _, _ := db.From("orders").
    InnerJoin(goqu.T("users"), goqu.On(goqu.Ex{"orders.user_id": goqu.I("users.id")})).
    Select("orders.id", "users.name", "orders.amount").
    Order(goqu.I("orders.created_at").Desc()).
    Limit(10).
    ToSQL()

fmt.Println(sql)
// SELECT "orders"."id", "users"."name", "orders"."amount" FROM "orders" INNER JOIN "users" ON ("orders"."user_id" = "users"."id") ORDER BY "orders"."created_at" DESC LIMIT 10
  1. INSERT with returning clause:
ds := db.Insert("users").Rows(
    goqu.Record{"name": "John", "email": "john@example.com"},
).Returning("id")

sql, args, _ := ds.ToSQL()
fmt.Println(sql)
fmt.Println(args)
// INSERT INTO "users" ("name", "email") VALUES ($1, $2) RETURNING "id"
// ["John", "john@example.com"]

Getting Started

To use Goqu in your Go project:

  1. Install the library:

    go get -u github.com/doug-martin/goqu/v9
    
  2. Import and initialize:

    import (
        "github.com/doug-martin/goqu/v9"
        _ "github.com/doug-martin/goqu/v9/dialect/postgres"
    )
    
    db := goqu.New("postgres", dbConnection)
    
  3. Start building queries:

    ds := db.From("users").Where(goqu.Ex{"active": true})
    sql, args, _ := ds.Select("id", "name").ToSQL()
    

Competitor Comparisons

Fluent SQL generation for golang

Pros of Squirrel

  • More established project with a longer history and larger community
  • Supports a wider range of SQL dialects out of the box
  • Simpler API, which can be easier for beginners to learn

Cons of Squirrel

  • Less feature-rich compared to Goqu
  • Lacks advanced query building capabilities like complex joins and subqueries
  • Not as actively maintained, with fewer recent updates

Code Comparison

Squirrel:

users := sq.Select("*").From("users").Where(sq.Eq{"name": "bob"})
sql, args, err := users.ToSql()

Goqu:

sql, args, err := goqu.From("users").Select("*").Where(goqu.C("name").Eq("bob")).ToSQL()

Both libraries provide similar functionality for basic query building, but Goqu offers more advanced features for complex queries. Squirrel's syntax is slightly more verbose but may be more intuitive for some developers. Goqu's approach is more concise and offers greater flexibility for advanced use cases.

15,960

general purpose extensions to golang's database/sql

Pros of sqlx

  • Lightweight and close to raw SQL, offering more control and flexibility
  • Supports named parameters and struct scanning for easier query handling
  • Provides a simpler learning curve for developers familiar with SQL

Cons of sqlx

  • Lacks advanced query building features and abstractions
  • Requires more manual SQL writing, which can be error-prone
  • Limited support for complex joins and subqueries compared to goqu

Code Comparison

sqlx:

rows, err := db.Queryx("SELECT * FROM users WHERE name = ?", name)
var user User
for rows.Next() {
    err := rows.StructScan(&user)
}

goqu:

users, err := db.From("users").Where(goqu.Ex{"name": name}).ScanStructs(&users)

Summary

sqlx is a lightweight SQL package that provides a thin layer of abstraction over database/sql, offering named parameters and struct scanning. It's ideal for developers who prefer writing raw SQL and want more control over their queries.

goqu, on the other hand, is a more feature-rich query builder that provides a fluent API for constructing complex SQL queries. It offers advanced features like automatic dialect detection and comprehensive query building capabilities.

Choose sqlx for projects requiring close-to-SQL control and simplicity, while goqu is better suited for applications needing a powerful query builder with extensive features and abstraction.

36,491

The fantastic ORM library for Golang, aims to be developer friendly

Pros of gorm

  • More comprehensive ORM features, including associations, hooks, and migrations
  • Larger community and ecosystem, with more third-party plugins and extensions
  • Better support for complex database operations and relationships

Cons of gorm

  • Steeper learning curve due to its extensive feature set
  • Potentially slower performance for simple queries compared to goqu
  • More "magic" and abstraction, which can make debugging more challenging

Code Comparison

gorm example:

db.Where("name = ?", "jinzhu").First(&user)

goqu example:

sql, _, _ := goqu.From("users").Where(goqu.C("name").Eq("jinzhu")).ToSQL()
db.QueryRow(sql).Scan(&user)

Summary

gorm is a full-featured ORM with a wide range of capabilities, making it suitable for complex database operations and relationships. It offers a more abstracted approach to database interactions, which can be beneficial for larger projects but may introduce overhead for simpler use cases.

goqu, on the other hand, focuses on query building and provides a more lightweight approach. It offers greater control over SQL generation and may be more performant for simple queries. However, it lacks some of the advanced ORM features found in gorm.

The choice between the two depends on project requirements, complexity, and developer preferences regarding abstraction levels and control over database operations.

12,095

Generate type-safe code from SQL

Pros of sqlc

  • Generates type-safe Go code from SQL queries, reducing runtime errors
  • Supports complex queries and joins, offering more flexibility for database operations
  • Integrates well with existing SQL migrations and database schemas

Cons of sqlc

  • Requires writing raw SQL queries, which may be less intuitive for some developers
  • Limited support for dynamic queries compared to Goqu's fluent interface
  • Steeper learning curve for developers not familiar with SQL syntax

Code Comparison

sqlc example:

-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = $1 LIMIT 1;

Goqu example:

query := goqu.From("authors").
    Where(goqu.C("id").Eq(1)).
    Limit(1)

Key Differences

  • sqlc focuses on generating Go code from SQL, while Goqu provides a query builder API
  • sqlc offers stronger type safety and compile-time checks
  • Goqu provides more flexibility for dynamic query construction
  • sqlc requires separate SQL files, whereas Goqu allows inline query building in Go code

Use Cases

  • sqlc: Projects with complex database schemas and a preference for writing raw SQL
  • Goqu: Applications requiring dynamic query construction and a more Go-centric approach to database interactions

Generate a Go ORM tailored to your database schema.

Pros of sqlboiler

  • Generates type-safe Go code from database schema, reducing boilerplate
  • Supports complex queries and relationships out of the box
  • Provides excellent performance with minimal overhead

Cons of sqlboiler

  • Requires code generation, which can be cumbersome in some workflows
  • Less flexible for ad-hoc queries compared to Goqu's fluent API
  • Steeper learning curve for developers new to code generation tools

Code Comparison

sqlboiler:

users, err := models.Users().All(ctx, db)
if err != nil {
    return err
}

Goqu:

users, err := db.From("users").ScanStructs(&users)
if err != nil {
    return err
}

sqlboiler generates type-safe models and query methods, while Goqu uses a more dynamic approach with its fluent API. sqlboiler's generated code provides stronger type checking and IDE support, but Goqu offers more flexibility for constructing queries on the fly.

Both libraries aim to simplify database operations in Go, but take different approaches. sqlboiler is ideal for projects with stable schemas and a preference for type safety, while Goqu is better suited for applications requiring more dynamic query construction and flexibility.

6,660

Simple and Powerful ORM for Go, support mysql,postgres,tidb,sqlite3,mssql,oracle, Moved to https://gitea.com/xorm/xorm

Pros of xorm

  • More comprehensive ORM features, including schema synchronization and migrations
  • Supports a wider range of databases, including MySQL, PostgreSQL, SQLite, and more
  • Provides caching mechanisms for improved performance

Cons of xorm

  • Steeper learning curve due to more complex API and features
  • Less focus on query building, which is goqu's primary strength
  • May have higher overhead for simpler database operations

Code Comparison

xorm example:

engine, _ := xorm.NewEngine("sqlite3", "test.db")
user := new(User)
has, _ := engine.ID(1).Get(user)

goqu example:

db := goqu.New("sqlite3", "test.db")
user := new(User)
found, _ := db.From("users").Where(goqu.C("id").Eq(1)).ScanStruct(user)

Both libraries provide ways to interact with databases, but xorm offers a more ORM-centric approach, while goqu focuses on expressive query building. xorm's API is more abstracted, handling database connections and providing methods like Get, while goqu requires more explicit query construction but offers greater flexibility in building complex queries.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

  __ _  ___   __ _ _   _
 / _` |/ _ \ / _` | | | |
| (_| | (_) | (_| | |_| |
 \__, |\___/ \__, |\__,_|
 |___/          |_|

GitHub tag Test Go Reference codecov Go Report Card

goqu is an expressive SQL builder and executor

If you are upgrading from an older version please read the Migrating Between Versions docs.

Installation

If using go modules.

go get -u github.com/doug-martin/goqu/v9

If you are not using go modules...

NOTE You should still be able to use this package if you are using go version >v1.10 but, you will need to drop the version from the package. import "github.com/doug-martin/goqu/v9 -> import "github.com/doug-martin/goqu"

go get -u github.com/doug-martin/goqu

Migrating Between Versions

Features

goqu comes with many features but here are a few of the more notable ones

  • Query Builder
  • Parameter interpolation (e.g SELECT * FROM "items" WHERE "id" = ? -> SELECT * FROM "items" WHERE "id" = 1)
  • Built from the ground up with multiple dialects in mind
  • Insert, Multi Insert, Update, and Delete support
  • Scanning of rows to struct[s] or primitive value[s]

While goqu may support the scanning of rows into structs it is not intended to be used as an ORM if you are looking for common ORM features like associations, or hooks I would recommend looking at some of the great ORM libraries such as:

Why?

We tried a few other sql builders but each was a thin wrapper around sql fragments that we found error prone. goqu was built with the following goals in mind:

  • Make the generation of SQL easy and enjoyable
  • Create an expressive DSL that would find common errors with SQL at compile time.
  • Provide a DSL that accounts for the common SQL expressions, NOT every nuance for each database.
  • Provide developers the ability to:
    • Use SQL when desired
    • Easily scan results into primitive values and structs
    • Use the native sql.Db methods when desired

Docs

  • Dialect - Introduction to different dialects (mysql, postgres, sqlite3, sqlserver etc)
  • Expressions - Introduction to goqu expressions and common examples.
  • Select Dataset - Docs and examples about creating and executing SELECT sql statements.
  • Insert Dataset - Docs and examples about creating and executing INSERT sql statements.
  • Update Dataset - Docs and examples about creating and executing UPDATE sql statements.
  • Delete Dataset - Docs and examples about creating and executing DELETE sql statements.
  • Prepared Statements - Docs about interpolation and prepared statements in goqu.
  • Database - Docs and examples of using a Database to execute queries in goqu
  • Working with time.Time - Docs on how to use alternate time locations.

Quick Examples

Select

See the select dataset docs for more in depth examples

sql, _, _ := goqu.From("test").ToSQL()
fmt.Println(sql)

Output:

SELECT * FROM "test"
sql, _, _ := goqu.From("test").Where(goqu.Ex{
	"d": []string{"a", "b", "c"},
}).ToSQL()
fmt.Println(sql)

Output:

SELECT * FROM "test" WHERE ("d" IN ('a', 'b', 'c'))

Insert

See the insert dataset docs for more in depth examples

ds := goqu.Insert("user").
	Cols("first_name", "last_name").
	Vals(
		goqu.Vals{"Greg", "Farley"},
		goqu.Vals{"Jimmy", "Stewart"},
		goqu.Vals{"Jeff", "Jeffers"},
	)
insertSQL, args, _ := ds.ToSQL()
fmt.Println(insertSQL, args)

Output:

INSERT INTO "user" ("first_name", "last_name") VALUES ('Greg', 'Farley'), ('Jimmy', 'Stewart'), ('Jeff', 'Jeffers') []
ds := goqu.Insert("user").Rows(
	goqu.Record{"first_name": "Greg", "last_name": "Farley"},
	goqu.Record{"first_name": "Jimmy", "last_name": "Stewart"},
	goqu.Record{"first_name": "Jeff", "last_name": "Jeffers"},
)
insertSQL, args, _ := ds.ToSQL()
fmt.Println(insertSQL, args)

Output:

INSERT INTO "user" ("first_name", "last_name") VALUES ('Greg', 'Farley'), ('Jimmy', 'Stewart'), ('Jeff', 'Jeffers') []
type User struct {
	FirstName string `db:"first_name"`
	LastName  string `db:"last_name"`
}
ds := goqu.Insert("user").Rows(
	User{FirstName: "Greg", LastName: "Farley"},
	User{FirstName: "Jimmy", LastName: "Stewart"},
	User{FirstName: "Jeff", LastName: "Jeffers"},
)
insertSQL, args, _ := ds.ToSQL()
fmt.Println(insertSQL, args)

Output:

INSERT INTO "user" ("first_name", "last_name") VALUES ('Greg', 'Farley'), ('Jimmy', 'Stewart'), ('Jeff', 'Jeffers') []
ds := goqu.Insert("user").Prepared(true).
	FromQuery(goqu.From("other_table"))
insertSQL, args, _ := ds.ToSQL()
fmt.Println(insertSQL, args)

Output:

INSERT INTO "user" SELECT * FROM "other_table" []
ds := goqu.Insert("user").Prepared(true).
	Cols("first_name", "last_name").
	FromQuery(goqu.From("other_table").Select("fn", "ln"))
insertSQL, args, _ := ds.ToSQL()
fmt.Println(insertSQL, args)

Output:

INSERT INTO "user" ("first_name", "last_name") SELECT "fn", "ln" FROM "other_table" []

Update

See the update dataset docs for more in depth examples

sql, args, _ := goqu.Update("items").Set(
	goqu.Record{"name": "Test", "address": "111 Test Addr"},
).ToSQL()
fmt.Println(sql, args)

Output:

UPDATE "items" SET "address"='111 Test Addr',"name"='Test' []
type item struct {
	Address string `db:"address"`
	Name    string `db:"name" goqu:"skipupdate"`
}
sql, args, _ := goqu.Update("items").Set(
	item{Name: "Test", Address: "111 Test Addr"},
).ToSQL()
fmt.Println(sql, args)

Output:

UPDATE "items" SET "address"='111 Test Addr' []
sql, _, _ := goqu.Update("test").
	Set(goqu.Record{"foo": "bar"}).
	Where(goqu.Ex{
		"a": goqu.Op{"gt": 10}
	}).ToSQL()
fmt.Println(sql)

Output:

UPDATE "test" SET "foo"='bar' WHERE ("a" > 10)

Delete

See the delete dataset docs for more in depth examples

ds := goqu.Delete("items")

sql, args, _ := ds.ToSQL()
fmt.Println(sql, args)
sql, _, _ := goqu.Delete("test").Where(goqu.Ex{
		"c": nil
	}).ToSQL()
fmt.Println(sql)

Output:

DELETE FROM "test" WHERE ("c" IS NULL)

Contributions

I am always welcoming contributions of any type. Please open an issue or create a PR if you find an issue with any of the following.

  • An issue with Documentation
  • You found the documentation lacking in some way

If you have an issue with the package please include the following

  • The dialect you are using
  • A description of the problem
  • A short example of how to reproduce (if applicable)

Without those basics it can be difficult to reproduce your issue locally. You may be asked for more information but that is a good starting point.

New Features

New features and/or enhancements are great and I encourage you to either submit a PR or create an issue. In both cases include the following as the need/requirement may not be readily apparent.

  1. The use case
  2. A short example

If you are issuing a PR also include the following

  1. Tests - otherwise the PR will not be merged
  2. Documentation - otherwise the PR will not be merged
  3. Examples - [If applicable] see example_test.go for examples

If you find an issue you want to work on please comment on it letting other people know you are looking at it and I will assign the issue to you.

If want to work on an issue but dont know where to start just leave a comment and I'll be more than happy to point you in the right direction.

Running tests

The test suite requires a postgres, mysql and sqlserver databases. You can override the connection strings with the MYSQL_URI, PG_URI, SQLSERVER_URI environment variables*

go test -v -race ./...

You can also run the tests in a container using docker-compose.

MYSQL_VERSION=8 POSTGRES_VERSION=13.4 SQLSERVER_VERSION=2017-CU8-ubuntu GO_VERSION=latest docker-compose run goqu

License

goqu is released under the MIT License.