{"id":28329937,"url":"https://github.com/mibk/dali","last_synced_at":"2025-10-18T10:48:15.737Z","repository":{"id":57480987,"uuid":"44697256","full_name":"mibk/dali","owner":"mibk","description":"a thin layer over Go's database/sql","archived":false,"fork":false,"pushed_at":"2024-02-22T11:57:15.000Z","size":112,"stargazers_count":27,"open_issues_count":4,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-02T01:36:28.115Z","etag":null,"topics":["database","go","golang","golang-library"],"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/mibk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-10-21T18:49:36.000Z","updated_at":"2024-01-03T14:12:54.000Z","dependencies_parsed_at":"2023-11-20T22:26:20.607Z","dependency_job_id":"6082f590-dc65-495b-86b7-f3bdb8462210","html_url":"https://github.com/mibk/dali","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/mibk/dali","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mibk%2Fdali","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mibk%2Fdali/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mibk%2Fdali/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mibk%2Fdali/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mibk","download_url":"https://codeload.github.com/mibk/dali/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mibk%2Fdali/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279516940,"owners_count":26183889,"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","status":"online","status_checked_at":"2025-10-18T02:00:06.492Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","golang-library"],"created_at":"2025-05-26T13:14:38.414Z","updated_at":"2025-10-18T10:48:15.705Z","avatar_url":"https://github.com/mibk.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"![DALí Logo](dali.png) \u0026nbsp;\n[![GoDoc](https://godoc.org/github.com/mibk/dali?status.png)](https://godoc.org/github.com/mibk/dali)\n[![Build Status](https://travis-ci.org/mibk/dali.png)](https://travis-ci.org/mibk/dali)\n\n# Database Abstraction Layer (í)\n\nDALí is not exactly a database abstration layer. It doesn't try to abstract the SQL in a way\nthat the queries could run unchanged on any supported database. It rather abstracts\njust the placeholder manipulation and provides convenient ways for some common situations.\n\nThe main goal of this project is to provide a clean, compact API for communication with\nSQL databases.\n\n## Quickstart\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"time\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n\t\"github.com/mibk/dali\"\n)\n\nfunc main() {\n\tdb, err := dali.Open(\"mysql\", \"root@/example?parseTime=true\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tq := db.Query(`INSERT INTO [group] ?values`, dali.Map{\"name\": \"admins\"})\n\tgroupID, err := dali.LastInsertID(q.Exec())\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t// INSERT INTO `group` (`name`) VALUES ('admins')\n\n\tusers := []User{\n\t\t{0, \"Peter\", \"peter@foo.com\", groupID, time.Now()},\n\t\t{0, \"Nick\", \"nick@bar.org\", groupID, time.Now()},\n\t}\n\t_, err = db.Query(`INSERT INTO [user] ?values...`, users).Exec()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t// ?values... expands a slice of struct into multi insert\n\t// INSERT INTO `user` (`name`, `email`, `group_id`, `created`) VALUES\n\t//\t('Peter', 'peter@foo.com', 1, '2015-11-20 13:59:59'),\n\t//\t('Nick', 'nick@bar.org', 1, '2015-11-20 13:59:59')\n\n\tvar u User\n\tq = db.Query(`SELECT * FROM ?ident WHERE group_id IN (?...) LIMIT 1`,\n\t\t\"user\", []int{1, 2, 5})\n\tfmt.Println(q) // dali.Query implements fmt.Stringer. It prints:\n\t// SELECT * FROM `user` WHERE group_id IN (1, 2, 5) LIMIT 1\n\tif err := q.One(\u0026u); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfmt.Println(u)\n\n\tu.Email = \"peter@foo.net\"\n\tu.GroupID = 2\n\t_, err = db.Query(`UPDATE [user] ?set WHERE [id] = ?`,\n\t\tdali.Map{\n\t\t\t\"email\":    u.Email,\n\t\t\t\"group_id\": u.GroupID,\n\t\t}, 1).Exec()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t// UPDATE `user` SET `email` = 'peter@foo.net', `group_id` = 2\n\t//\tWHERE `id` = 1\n}\n\ntype User struct {\n\tID         int64     `db:\",selectonly\"` // omitted on INSERT, UPDATE, etc.\n\tName       string    `db:\"name\"`\n\tEmail      string    `db:\"email\"`\n\tGroupID    int64     `db:\"group_id\"`\n\tRegistered time.Time `db:\"created\"`\n}\n```\n\n## Instalation\n\n```bash\n$ go get github.com/mibk/dali\n```\n\n## Caveats\n\nDALí processes the query unaware of the actual SQL syntax. This means it is quite stupid\non deciding whether the placeholder is inside a string literal.\n```go\nconn.Query(`SELECT * FROM foo WHERE name = 'really?'`)\n// This will return an error because it would try to replace the `?` with an argument\n// that is missing.\n```\nTo avoid this just use the whole string as a parameter.\n```go\nconn.Query(`SELECT * FROM foo WHERE name = ?`, \"really?\")\n```\n\n## Features\n\n### Identifier escaping\n\nThis feature comes from the need to fix the clumsy way of escaping identifiers in MySQL in\nGo's raw string literals. So instead of\n```go\nsql := `SELECT `+\"`where`\"+`\n\tFROM location`\n```\nyou can use\n```go\nsql := `SELECT [where]\n\tFROM location\n```\nSo there is one way to escape identifiers among all dialects.\n\n### Handy placeholders\n\nAgain, placeholder manipulation is the same for all dialects and besides that it also provides\nsome additional placeholders. The complete list is:\n\n```\n?          primitive value or a value implementing driver.Valuer\n?...       a slice of values which is going to be expanded (especially useful in\n           IN clauses)\n?values    expects either Map, or a struct as an argument. It derives column names\n           from map keys or struct fields and constructs a VALUES clause (e.g.\n           INSERT INTO user ?values)\n?set       similar to ?values but used for SET clauses (e.g. UPDATE user SET ?set)\n?values... expects a slice of structs as an argument which is expanded into multi\n           INSERT clause\n?ident     used for identifiers (column or table name)\n?ident...  expands identifiers and separates them with a comma\n?sql       inserts the parameter, a string or Marshaler, as is (meant for SQL parts)\n```\n\nUsing the placeholders it is easy and quite expressive to write common SQL queries, but it is\nalso possible to adjust these queries to a specific need (which is often not so easy when using\nquery builders).\n\n*Note*: only `?`, `?ident`, `?ident...`, and `?sql` are allowed in prepared statements (see the\nmethod Prepare for more information).\n\n### Profiling and other\n\nUsing the [DB.SetMiddlewareFunc](https://godoc.org/github.com/mibk/dali#DB.SetMiddlewareFunc) it is\npossible to do additional operations before and after execution of every query. This example\nlogs every executed query:\n\n```go\nvar db *dali.DB // init db...\n\nfunc init() {\n\tdb.SetMiddlewareFunc(profile)\n}\n\nfunc profile(e dali.Execer) dali.Execer {\n\treturn profiler{e}\n}\n\ntype profiler struct {\n\tex dali.Execer\n}\n\nfunc (p profiler) Exec(query string, args ...interface{}) (sql.Result, error) {\n\tlog.Println(query, args)\n\treturn p.ex.Exec(query, args...)\n}\n\nfunc (p profiler) Query(query string, args ...interface{}) (*sql.Rows, error) {\n\tlog.Println(query, args)\n\treturn p.ex.Query(query, args...)\n}\n\nfunc (p profiler) QueryRow(query string, args ...interface{}) *sql.Row {\n\tlog.Println(query, args)\n\treturn p.ex.QueryRow(query, args...)\n}\n```\n\n### Faster performance\n\nDALí interpolates all parameters before it gets to the database which has a huge performance\nbenefit. This behaviour is taken from the **gocraft/dbr** library. See\n[this](https://github.com/gocraft/dbr#faster-performance-than-using-using-databasesql-directly)\nfor more information.\n\n### Supported dialects\n\nCurrently, only a MySQL dialect is implemented directly in this package (see [dialects](dialects)\nfor more information). Nevertheless, supporting another dialect should be as easy as creating\na new dialect implementing *dialects.Dialect* interface. The most common dialects will be\nimplemented directly in the future.\n\n## Thanks\n\nIdeas for building this library come mainly from these sources:\n\n- [gocraft/dbr](https://github.com/gocraft/dbr) for interpolation, loading methods and other\n- [nextras/dbal](https://github.com/nextras/dbal) for the placeholders (although it is a PHP library)\n- [jmoiron/sqlx](https://github.com/jmoiron/sqlx) for general ideas\n\n## License\n\nDALí is distributed under the MIT license found in the [LICENSE](LICENSE) file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmibk%2Fdali","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmibk%2Fdali","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmibk%2Fdali/lists"}