Top Related Projects
Fluent SQL generation for golang
general purpose extensions to golang's database/sql
The fantastic ORM library for Golang, aims to be developer friendly
Generate type-safe code from SQL
Generate a Go ORM tailored to your database schema.
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
- 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
- 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
- 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:
-
Install the library:
go get -u github.com/doug-martin/goqu/v9
-
Import and initialize:
import ( "github.com/doug-martin/goqu/v9" _ "github.com/doug-martin/goqu/v9/dialect/postgres" ) db := goqu.New("postgres", dbConnection)
-
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.
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.
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.
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.
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 designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
__ _ ___ __ _ _ _
/ _` |/ _ \ / _` | | | |
| (_| | (_) | (_| | |_| |
\__, |\___/ \__, |\__,_|
|___/ |_|
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.
- The use case
- A short example
If you are issuing a PR also include the following
- Tests - otherwise the PR will not be merged
- Documentation - otherwise the PR will not be merged
- 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.
Top Related Projects
Fluent SQL generation for golang
general purpose extensions to golang's database/sql
The fantastic ORM library for Golang, aims to be developer friendly
Generate type-safe code from SQL
Generate a Go ORM tailored to your database schema.
Simple and Powerful ORM for Go, support mysql,postgres,tidb,sqlite3,mssql,oracle, Moved to https://gitea.com/xorm/xorm
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot