{"id":13826856,"url":"https://github.com/colinjfw/sqlkit","last_synced_at":"2025-07-09T02:32:29.726Z","repository":{"id":57553592,"uuid":"125319028","full_name":"colinjfw/sqlkit","owner":"colinjfw","description":"SQL builder and powerful database toolkit for Golang","archived":true,"fork":false,"pushed_at":"2019-07-16T05:09:02.000Z","size":104,"stargazers_count":119,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-16T07:46:17.735Z","etag":null,"topics":["golang","query-builder","sql"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/colinjfw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-15T05:53:49.000Z","updated_at":"2024-10-27T04:14:11.000Z","dependencies_parsed_at":"2022-08-28T09:31:43.116Z","dependency_job_id":null,"html_url":"https://github.com/colinjfw/sqlkit","commit_stats":null,"previous_names":["coldog/sqlkit"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colinjfw%2Fsqlkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colinjfw%2Fsqlkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colinjfw%2Fsqlkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colinjfw%2Fsqlkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/colinjfw","download_url":"https://codeload.github.com/colinjfw/sqlkit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225480980,"owners_count":17481131,"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":["golang","query-builder","sql"],"created_at":"2024-08-04T09:01:45.512Z","updated_at":"2024-11-20T06:30:26.401Z","avatar_url":"https://github.com/colinjfw.png","language":"Go","readme":"# SQLKit\n\n[![travis](https://travis-ci.org/colinjfw/sqlkit.svg?branch=master)](https://travis-ci.org/colinjfw/sqlkit.svg?branch=master)\n[![codecov](https://codecov.io/gh/colinjfw/sqlkit/branch/master/graph/badge.svg)](https://codecov.io/gh/colinjfw/sqlkit)\n[![goreport](https://goreportcard.com/badge/github.com/colinjfw/sqlkit)](https://goreportcard.com/report/github.com/colinjfw/sqlkit)\n[![godoc](https://godoc.org/github.com/colinjfw/sqlkit?status.svg)](https://godoc.org/github.com/colinjfw/sqlkit)\n[![release](https://img.shields.io/github/release/colinjfw/sqlkit.svg)](https://github.com/colinjfw/sqlkit/releases)\n[![license](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nMultipurpose SQL packages for GO programs.\n\nWorking with SQL in golang is challenging in certain respects. Some of the main challenges I've encountered have been:\n\n* The way NULL values are handled by the sql package requires using pointers in places where often just the zero value would be used.\n* The lack of nested transactions which are very valuable when trying to wrap an entire test or work with more complex transactions.\n* Lacking a simple and extendable SQL builder.\n\nThis project is designed to fix some of these issues. It is heavily influenced by sqlx https://github.com/jmoiron/sqlx but with more opinions on how SQL should be used in projects.\n\nView the [example](example) to see an example of using this project.\n\n## Status\n\nThis project is currently in an ALPHA state. The api is relatively solid for the `encoding` package but may change for the `db` package.\n\n## Versioning\n\nThis project follows semantic versioning. Best effort will be maintained to keep backwards compatibility as soon as the api stabilizes at 1.0.0.\n\n## Packages\n\n### [`encoding`](encoding)\n\nMarshal to structs to and from SQL. Gracefully handles null values.\n\n```go\ncols, vals, err := encoding.Marshal(user{1})\n_, err = db.Exec(\n\"insert into users (\"+strings.Join(cols, \",\")+\") values \"+\"(?)\", vals...,\n)\n\nusers := []user{}\nrows, err := db.Query(\"select * from users\")\nerr = encoding.Unmarsal(\u0026users, rows)\n```\n\n### [`db`](db)\n\nBasic SQL query builder for SQL which handles marshalling and unmarshalling values using the `sqlkit/encoding` package. Features include:\n\n* Query builder for SQL statements.\n* Nested transactions using savepoints.\n* Support for Postgres, MySQL and other sql flavours.\n* Extensible query logging.\n* Expands placeholders for IN (?) queries.\n\nAn example of common API usage:\n\n```go\nd, err := db.Open(\"sqlite3\", \":memory:\", db.WithLogger(db.StdLogger))\n\ntx, err := d.Begin(context.Background()) // tx implements context.Context.\ndefer tx.Rollback()\n\nerr = d.Exec(tx, d.Insert().Into(\"test\").Value(\"id\", 2)).Err()\n\nvar rows []int\nerr = d.Query(tx, d.Select(\"*\").From(\"test\")).Decode(\u0026rows)\nfmt.Printf(\"%v\\n\", rows) // Can decode a slice of objects or scalars.\n\nvar count int\nerr = d.Query(tx, d.Select(\"count(*)\").From(\"test\")).Decode(\u0026count)\nfmt.Println(count) // Can decode single values.\n```\n\n## Overview\n\n### Transactions\n\nTransactions are implemented as a wrapper over `context.Context` which allows us\nto build transaction unaware database logic in our applications. Instead of\ncalling `tx.Exec` on a transaction we call `db.Exec(ctx, ...)` where context\nwill contain transaction information that we can use.\n\n### Nested Transactions\n\nNested transactions are a feature used heavily in Rails or other frameworks to\nroll back test code to leave the database in a clean state. If you take a look\nat the [example_test.go](example/example_test.go) file you can see how we can\nuse a setup function to rollback on error:\n\n```go\nfunc setup(t *testing.T) (db.TX, func()) {\n\tctx, err := db.Begin(context.Background())\n\trequire.NoError(t, err)\n\treturn ctx, func() { ctx.Rollback() }\n}\n```\n\nTransaction begin takes a `context.Context`, if this is already a transaction,\nwe will initialize a savepoint instead of an additional transaction. Note that\nadditional nesting will continue to initialize savepoints. This isn't a true\nnesting of transactions and rollbacks will not bubble up. It's important to make\nsure that your code handles rolling back transactions appropriately with error\nhandling if you need errors to bubble up.\n\nUsing `db.TX` is the safest way to manage transactions. The function handles\nrollbacks and commit calls based on the error value from the callback function.\n\n```go\ndb.TX(ctx, func(ctx context.Context) error {\n\treturn db.TX(ctx, ...)\n})\n```\n\n### Usage With Other SQL Generators\n\nThe `Query` and `Exec` methods take an `SQL` interface defined below:\n\n```go\ntype SQL interface {\n\tSQL() (string, []interface{}, error)\n}\n```\n\nThis means that as long as a query generator implements this interface, you can\npass this into any for the `db` package functions to execute your query. This\nmeans that you can extend query builders or bring your own query builder.\n\nIf you want to use `squirrel` for example, you can provide a simple little\nhelper to translate the interfaces:\n\n```go\ntype SQ struct { squirrel.Sqlizer }\n\nfunc (s SQ) SQL() (string, []interface{}, error) { return s.ToSql() }\n```\n\n### Encoding\n\nThe encoding package handles taking golang interfaces and converting them from\nsql types to golang types. It uses `sqlx` under the hood to manage this.\n\nOne of the main differences is that it has a different philosophy from the core\ngolang `database/sql` package when it comes to nullable types. Mainly, nullable\ntypes are converted into their default value in golang. Instead of requiring a\npointer.\n\nFor example:\n\n```go\ntype user struct { ID string `db:\"id\"` }\nuser := \u0026user{}\n\nencoding.Unmarshal(user, row) // database/sql#Rows\n```\n\nIn this case, if `id` in the database is `NULL` then it will scan simply as a\nblank string into `user.ID`.\n\nYou can customize the mapping between struct fields and database field names by\nspecifiying a mapper function:\n\n```go\nencoding.NewEncoder().WithMapper(reflectx.NewMapperFunc(\"mytag\", strings.ToLower))\n```\n\n\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcolinjfw%2Fsqlkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcolinjfw%2Fsqlkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcolinjfw%2Fsqlkit/lists"}