{"id":13412139,"url":"https://github.com/rocketlaunchr/dbq","last_synced_at":"2025-04-05T13:01:41.147Z","repository":{"id":41379909,"uuid":"196304341","full_name":"rocketlaunchr/dbq","owner":"rocketlaunchr","description":"Zero boilerplate database operations for Go","archived":false,"fork":false,"pushed_at":"2021-02-22T23:21:16.000Z","size":353,"stargazers_count":408,"open_issues_count":1,"forks_count":20,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-05T06:55:33.849Z","etag":null,"topics":["database","go","golang","mysql","postgres","postgresql"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rocketlaunchr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"rocketlaunchr"}},"created_at":"2019-07-11T02:17:33.000Z","updated_at":"2025-04-03T01:41:26.000Z","dependencies_parsed_at":"2022-08-31T01:50:59.364Z","dependency_job_id":null,"html_url":"https://github.com/rocketlaunchr/dbq","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rocketlaunchr%2Fdbq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rocketlaunchr%2Fdbq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rocketlaunchr%2Fdbq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rocketlaunchr%2Fdbq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rocketlaunchr","download_url":"https://codeload.github.com/rocketlaunchr/dbq/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247339145,"owners_count":20923012,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","go","golang","mysql","postgres","postgresql"],"created_at":"2024-07-30T20:01:21.418Z","updated_at":"2025-04-05T13:01:41.041Z","avatar_url":"https://github.com/rocketlaunchr.png","language":"Go","readme":"\u003cp align=\"right\"\u003e\n  \u003ca href=\"http://godoc.org/github.com/rocketlaunchr/dbq/v2\"\u003e\u003cimg src=\"http://godoc.org/github.com/rocketlaunchr/dbq?status.svg\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://goreportcard.com/report/github.com/rocketlaunchr/dbq\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/rocketlaunchr/dbq\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/rocketlaunchr/dbq/raw/master/logo.png\" alt=\"dbq\" /\u003e\n\u003c/p\u003e\n\n(Now compatible with MySQL and PostgreSQL!)\n\nEveryone knows that performing simple **DATABASE queries** in Go takes numerous lines of code that is often repetitive. If you want to avoid the cruft, you have two options: A heavy-duty ORM that is not up to the standard of Laravel or Django. Or DBQ!\n\n⚠️ **WARNING: You will seriously reduce your database code to a few lines**\n\n⭐ **the project to show your appreciation.**\n\n## What is included\n\n- Supports ANY type of query\n- **MySQL** and **PostgreSQL** compatible\n- **Convenient** and **Developer Friendly**\n- Accepts any type of slice for query args\n- Flattens query arg slices to individual values\n- Bulk Insert seamlessly\n- Automatically unmarshal query results directly to a struct using [mapstructure](https://github.com/mitchellh/mapstructure) package\n- Lightweight\n- Compatible with [mysql-go](https://github.com/rocketlaunchr/mysql-go) for proper MySQL query cancelation\n- Automatically retry query with exponential backoff if operation fails\n- Transaction management (automatic rollback)\n\n## Dependencies\n\n- [MySQL driver](https://github.com/go-sql-driver/mysql) OR\n- [PostgreSQL driver](https://github.com/lib/pq)\n\n**NOTE:** For mysql driver, [`parseTime=true`](https://github.com/go-sql-driver/mysql#parsetime) setting can interfere with unmarshaling to [`civil.*`](https://pkg.go.dev/cloud.google.com/go/civil?tab=doc) types.\n\n## Installation\n\n```\ngo get -u github.com/rocketlaunchr/dbq/v2\n```\n\n## Examples\n\nLet's assume a table called `users`:\n\n| id  | name  | age | created_at |\n| --- | ----- | --- | ---------- |\n| 1   | Sally | 12  | 2019-03-01 |\n| 2   | Peter | 15  | 2019-02-01 |\n| 3   | Tom   | 18  | 2019-01-01 |\n\n### Query\n\n[`Q`](https://godoc.org/github.com/rocketlaunchr/dbq/v2#Q) ordinarily returns `[]map[string]interface{}` results, but you can automatically\nunmarshal to a struct. You will need to type assert the results.\n\n```go\n\ntype user struct {\n  ID        int       `dbq:\"id\"`\n  Name      string    `dbq:\"name\"`\n  Age       int       `dbq:\"age\"`\n  CreatedAt time.Time `dbq:\"created_at\"`\n}\n\nopts := \u0026dbq.Options{ConcreteStruct: user{}, DecoderConfig:x}\n\nresults, err := dbq.Q(ctx, db, \"SELECT * FROM users\", opts)\nresults, err := dbq.Qs(ctx, db, \"SELECT * FROM users\", user{}, nil)\n\n```\n\nResults:\n\n```groovy\n([]*main.user) (len=6 cap=8) {\n (*main.user)(0xc00009e1c0)({\n  ID: (int) 1,\n  Name: (string) (len=5) \"Sally\",\n  Age: (int) 12,\n  CreatedAt: (time.Time) 2019-03-01 00:00:00 +0000 UTC\n }),\n (*main.user)(0xc00009e300)({\n  ID: (int) 2,\n  Name: (string) (len=5) \"Peter\",\n  Age: (int) 15,\n  CreatedAt: (time.Time) 2019-02-01 00:00:00 +0000 UTC\n }),\n (*main.user)(0xc00009e440)({\n  ID: (int) 3,\n  Name: (string) (len=3) \"Tom\",\n  Age: (int) 18,\n  CreatedAt: (time.Time) 2019-01-01 00:00:00 +0000 UTC\n })\n}\n```\n\n### Query Single Row\n\nIf you know that the query will return at maximum 1 row:\n\n```go\nresult := dbq.MustQ(ctx, db, \"SELECT * FROM users LIMIT 1\", dbq.SingleResult)\nif result == nil {\n  // no result\n} else {\n  result.(map[string]interface{})\n}\n\n```\n\n### Bulk Insert\n\nYou can insert multiple rows at once.\n\n```go\n\ndb, _ := sql.Open(\"mysql\", \"user:password@tcp(localhost:3306)/db\")\n\ntype Row struct {\n  Name      string\n  Age       int\n  CreatedAt time.Time\n}\n\nusers := []interface{}{\n  dbq.Struct(Row{\"Brad\", 45, time.Now()}),\n  dbq.Struct(Row{\"Ange\", 36, time.Now()}),\n  dbq.Struct(Row{\"Emily\", 22, time.Now()}),\n}\n\nstmt := dbq.INSERTStmt(\"users\", []string{\"name\", \"age\", \"created_at\"}, len(users))\n\ndbq.E(ctx, db, stmt, nil, users)\n\n```\n\n### Flatten Query Args\n\nAll slices are flattened automatically.\n\n```go\nargs1 := []string{\"A\", \"B\", \"C\"}\nargs2 := []interface{}{2, \"D\"}\nargs3 := dbq.Struct(Row{\"Brad Pitt\", 45, time.Now()})\n\nresults := dbq.MustQ(ctx, db, stmt, args1, args2, args3)\n\n// Placeholder arguments will get flattened to:\nresults := dbq.MustQ(ctx, db, stmt, \"A\", \"B\", \"C\", 2, \"D\", \"Brad Pitt\", 45, time.Now())\n\n```\n\n**NOTE:** [FlattenArgs](https://godoc.org/github.com/rocketlaunchr/dbq/v2#FlattenArgs) function can be used more generally.\n\n### MySQL cancelation\n\nTo properly cancel a MySQL query, you need to use the [mysql-go](https://github.com/rocketlaunchr/mysql-go) package. `dbq` plays nicely with it.\n\n```go\nimport sql \"github.com/rocketlaunchr/mysql-go\"\n\npool, _ := sql.Open(\"user:password@tcp(localhost:3306)/db\")\n\nconn, err := pool.Conn(ctx)\n\nopts := \u0026dbq.Options{\n  SingleResult: true,\n  PostFetch: func(ctx context.Context) error {\n    return conn.Close()\n  },\n}\n\nresult := dbq.MustQ(ctx, conn, \"SELECT * FROM users LIMIT 1\", opts)\nif result == nil {\n  // no result\n} else {\n  result.(map[string]interface{})\n}\n```\n\n### PostUnmarshaler\n\nAfter fetching the results, you can further modify the results by implementing the [`PostUnmarshaler`](https://godoc.org/github.com/rocketlaunchr/dbq/v2#PostUnmarshaler) interface. The `PostUnmarshal` function must be attached to the pointer of the struct.\n\n```go\ntype user struct {\n  ID        int       `dbq:\"id\"`\n  Name      string    `dbq:\"name\"`\n  Age       int       `dbq:\"age\"`\n  CreatedAt time.Time `dbq:\"created_at\"`\n  HashedID  string    `dbq:\"-\"`          // Obfuscate ID\n}\n\nfunc (u *user) PostUnmarshal(ctx context.Context, row, total int) error {\n  u.HashedID = obfuscate(u.ID)\n  return nil\n}\n```\n\n### ScanFaster\n\nThe [`ScanFaster`](https://godoc.org/github.com/rocketlaunchr/dbq/v2#ScanFaster) interface eradicates the use of the reflect package when unmarshaling. If you don't need to perform fancy time conversions or interpret weakly typed data, then it is more performant.\n\n```go\ntype user struct {\n  ID       int    `dbq:\"id\"`\n  Name     string `dbq:\"name\"`\n}\n\nfunc (u *user) ScanFast() []interface{} {\n  return []interface{}{\u0026u.ID, \u0026u.Name}\n}\n```\n\n### Retry with Exponential Backoff\n\nIf the database operation fails, you can automatically retry with exponentially increasing intervals between each retry attempt. You can also set the maximum number of retries.\n\n```go\nopts := \u0026dbq.Options{\n  RetryPolicy:  dbq.ExponentialRetryPolicy(60 * time.Second, 3),\n}\n```\n\n### Transaction Management\n\nYou can conveniently perform numerous complex database operations within a transaction without having to worry about rolling back. Unless you explicitly commit, it will automatically rollback.\n\nYou have access to the `Q` and `E` function as well as the underlying `tx` for performance purposes.\n\n```go\nctx := context.Background()\npool, _ := sql.Open(\"mysql\", \"user:password@tcp(localhost:3306)/db\")\n\ndbq.Tx(ctx, pool, func(tx interface{}, Q dbq.QFn, E dbq.EFn, txCommit dbq.TxCommit) {\n  \n  stmt := dbq.INSERTStmt(\"table\", []string{\"name\", \"age\", \"created_at\"}, 1)\n  res, err := E(ctx, stmt, nil, \"test name\", 34, time.Now())\n  if err != nil {\n    return // Automatic rollback\n  }\n  txCommit() // Commit\n})\n```\n\n## Custom Queries\n\nThe `v2/x` subpackage will house functions to perform custom SQL queries. If they are general to both MySQL and PostgreSQL, they are inside the `x` subpackage. If they are specific to MySQL xor PostgreSQL, they are in the `x/mysql` xor `x/pg` subpackage respectively.\n\n\n### This is your package too!\n\nIf you want your own custom functions included, just submit a PR and place it in your **own directory** inside `v2/x`. As long as it compiles and is well documented it is welcome.\n\n### Bulk Update\n\nAs a warmup, I have included a [Bulk Update](https://godoc.org/github.com/rocketlaunchr/dbq/v2/x#BulkUpdate) function that works with MySQL and PostgreSQL. It allows you to update thousands of rows in 1 query without a transaction!\n\n## Difference between v1 and v2\n\nWhen a `ConcreteStruct` is provided, in `v1`, the `Q` and `MustQ` functions return `[]interface{}` while in `v2` they return `[]*struct`.\n\n**NOTE:** `v1` is obsolete and will no longer receive updates.\n\n## Other useful packages\n\n- [dataframe-go](https://github.com/rocketlaunchr/dataframe-go) - Statistics and data manipulation\n- [electron-alert](https://github.com/rocketlaunchr/electron-alert) - SweetAlert2 for Electron Applications\n- [igo](https://github.com/rocketlaunchr/igo) - A Go transpiler with cool new syntax such as fordefer (defer for for-loops)\n- [mysql-go](https://github.com/rocketlaunchr/mysql-go) - Properly cancel slow MySQL queries\n- [react](https://github.com/rocketlaunchr/react) - Build front end applications using Go\n- [remember-go](https://github.com/rocketlaunchr/remember-go) - Cache slow database queries\n\n#\n\n### Legal Information\n\nThe license is a modified MIT license. Refer to the `LICENSE` file for more details.\n\n**© 2019-20 PJ Engineering and Business Solutions Pty. Ltd.**\n\n### Final Notes\n\nFeel free to enhance features by issuing pull-requests. Note that the project is written in [igo](https://github.com/rocketlaunchr/igo) and transpiled into Go.\n","funding_links":["https://github.com/sponsors/rocketlaunchr"],"categories":["数据库","Database","开源类库","Uncategorized","SQL Builders","Open source library","Go","数据库  `go语言实现的数据库`","Data Integration Frameworks","Generators"],"sub_categories":["SQL 查询语句构建库","SQL Query Builders","数据库","Database","Advanced Console UIs","SQL查询生成器"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frocketlaunchr%2Fdbq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frocketlaunchr%2Fdbq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frocketlaunchr%2Fdbq/lists"}