{"id":13710580,"url":"https://github.com/kovacou/go-database","last_synced_at":"2026-01-17T17:56:45.409Z","repository":{"id":57514793,"uuid":"205430887","full_name":"kovacou/go-database","owner":"kovacou","description":"Go databases manager (Context, Transactions \u0026 Profiler) w/ an intuitive SQL Builder on top of sqlx. Performances oriented.","archived":false,"fork":false,"pushed_at":"2024-01-24T20:30:41.000Z","size":85,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-13T21:44:29.383Z","etag":null,"topics":["builder","database","go","golang","mysql","profiler","transactions"],"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/kovacou.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}},"created_at":"2019-08-30T17:47:50.000Z","updated_at":"2023-01-17T06:48:37.000Z","dependencies_parsed_at":"2024-06-20T06:08:03.968Z","dependency_job_id":null,"html_url":"https://github.com/kovacou/go-database","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovacou%2Fgo-database","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovacou%2Fgo-database/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovacou%2Fgo-database/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovacou%2Fgo-database/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kovacou","download_url":"https://codeload.github.com/kovacou/go-database/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252753612,"owners_count":21798983,"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":["builder","database","go","golang","mysql","profiler","transactions"],"created_at":"2024-08-02T23:00:58.536Z","updated_at":"2026-01-17T17:56:45.403Z","avatar_url":"https://github.com/kovacou.png","language":"Go","funding_links":[],"categories":["Repositories"],"sub_categories":[],"readme":"# go-database\n\nPersonal project.  \n\n`go-database` is a library made for `mysql` which provides a set of extensions on top of [`jmoiron/sqlx`](https://github.com/jmoiron/sqlx) such as a querybuilder, profiler, context \u0026 transactions for performances. **This is not an ORM**.  \nI plan to support `pgsql` in the future.\n\n## ➡ features\n\n- Opening connection with environment variables :\n    - Global variables `DATABASE_*`\n    - Aliases variables for multiple connection `DATABASE_ALIAS_*`\n- Opening connection with Environ\n- A pool to manage all connections opened\n- Transactions\n- Profiling \u0026 Context\n    - Log out queries as string (formated) ordered by execution time grouped by context to detect slow queries.  \n    **Example :** You can profile an application that uses goroutines such as webserver.\n- Query builder for complex query at the SQL layer\n- **This is not an ORM (yet)**\n\n## ➡ install\n\n`go get github.com/kovacou/go-database`\n\n## ➡ usage\n\nBelow is an example which shows some common use cases for go-database. \n\n```ini\n# .env file configuration (default settings)\n\n# You can use DSN\nDATABASE_DSN=\n\n# Or use specfic variables\nDATABASE_DRIVER=mysql\nDATABASE_HOST=172.18.0.1\nDATABASE_USER=test\nDATABASE_PASS=test\nDATABASE_SCHEMA=dbtest\nDATABASE_PORT=3306\n```\n\n```go\npackage main\n\nimport (\n    \"log\"\n\n    \"github.com/kovacou/go-database\"\n    b \"github.com/kovacou/go-database/builder\"\n)\n\ntype User struct {\n    ID   uint64\n    Name string\n}\n\nfunc main() {\n    // Opening a new connection based on environment variables.\n    // By default, the connection is postponed until there is an action. \n    db, err := database.Open()\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    // Example of builder\n    s := b.Select{\n        Table: \"users\",\n        Where: b.ParseWhere(\"id \u003c ?\", 10)\n    }\n\n    println(s.String()) // SELECT * FROM users WHERE id \u003c ?\n\n    // Mapping through a map\n    // (faster than structscan if you look for performance)\n    out := []User{}\n    db.SelectMap(\u0026s, func(values map[string]any){\n        out = append(out, User{\n            ID:   values[\"id\"].(int64),\n            Name: string(values[\"name\"].([]byte)),\n        })\n    })\n\n    // More faster than previous one.\n    out2 := []User{}\n    db.SelectSlice(\u0026s, func(values []any) {\n        out2 = append(out2, User{\n            ID:   values[0].(int64),\n            Name: string(values[1].([]byte)),\n        })\n    })\n\n    // Using raw query\n    out3 := []User{}\n    db.QuerySlice(builder.NewQuery(\"SELECT * FROM users WHERE id \u003c ?\", 10), func(values []any) {\n        out3 = append(out3, User{\n            // ...\n        })\n    })\n\n    // Using upsert\n    i := builder.Insert{\n        Table: \"users\",\n        Values: builder.H{\n            \"id\": 1,\n            \"name\": \"John\",\n        },\n        OnUpdateKeys: builder.Keys{\"name\"},\n    }\n    db.Exec(\u0026i)\n}\n```\n\n## ➡ opening a new connection\n### **With environment variables**\n### **With environ**\n\n## ➡ closing all connections\n```go\nfunc main() {\n    // Defering the close in your main ensure closing \n    // the connection before exiting the program.\n    defer database.Close()\n\n    // your code...\n}\n```\n\n## ➡ transactions\n\nSupport of transactions.\n\n```go\n// tx, err := db.Tx() \ntx, err := db.Tx(sql.LevelSerializable)\nif err != nil {\n    panic(err)\n}\n\n// use tx to run some requests.\n\ntx.Commit()\ntx.Rollback()\n\n// You can't use tx anymore, else an error will occur.\n```\n\n## ➡ profiling \u0026 context\n\n## ➡ statements\n\n### **Select**\n\n```go\ns := builder.Select{\n    Table: \"users\",\n    Columns: builder.ParseColumns(\"id\", \"name\"),\n    Where: builder.ParseWhere(\"id \u003e ?\", 1),\n    OrderBy: builder.ParseOrderBy(\"name ASC\"),\n}\n```\n\n#### Map\nThe columns can be read by key name.\n\n```go\n// Parse 1 row only. \n{\n    out := User{}\n    n, err := db.SelectMapRow(\u0026s, func(v map[string]any) {   \n        // If there is more than 1 row, an error occur.\n        // `n` return 0 or 1.\n        outRow.ID = v[\"id\"].(int64)\n        outRow.Name = string(v[\"name\"].([]byte))\n    })\n}\n\n// Parse multiple rows.\n{\n    out := []User{}\n    n, err := db.SelectMap(\u0026s, func(v map[string]any) {\n        // `n` contains the number of rows returned.\n        out = append(out, User{\n            ID:   v[\"id\"].(int64),\n            Name: string(v[\"name\"].([]byte)),\n        })\n    })\n}\n```\n\n#### Slice\n\nThe columns can be read by indexes from the Column clause (same order).  \n**Note:** Slice is faster than Map. Prefer use Slice when the columns have always the same order.\n```go\n// Parse 1 row only\n{\n    out := User{}\n    n, err := db.SelectSliceRow(\u0026s, func(v []any){\n        // If there is more than1 row, an error occur.\n        // `n` return 0 or 1\n        out.ID = v[0].(int64)\n        out.Name = string(v[1].([]byte))\n    })\n}\n\n// Parse multiple rows\n{\n    out := []User{}\n    n, err := db.SelectSlice(\u0026s, func(v []any){\n        out = append(out, User{\n            ID:   v[0].(int64),\n            Name: string(v[1].([]byte)),\n        })\n    })\n}\n```\n\n### **Exec**\n\n#### Insert\n```go\n// Example of Insert\ni := builder.Insert{\n    Table:      \"users\",\n    IgnoreMode: false, // False by default\n    Values:     builder.H{\n        \"name\": \"John\",\n    },\n}\n\nprintln(i.String()) // INSERT INTO users(name) VALUES(?) \n\nr, err := db.Exec(\u0026i)\n```\n\n#### Upsert\n\n```go\n// Example of Insert with upsert mode.\ni := builder.Insert{\n    Table:        \"users\",\n    Values:       builder.H{\n        \"id\": 15,\n        \"name\": \"John\",\n    },\n    OnUpdateKeys: builder.Keys{\"name\"},\n}\n\nprintln(i.String()) // INSERT INTO users(id, name) VALUES(?, ?) \n                    // ON DUPLICATE KEY UPDATE name = VALUES(name) \n\nr, err := db.Exec(\u0026i)\n```\n\n#### Update\n\n```go\n// Example of Update\nu := builder.Update{\n    Table:  \"users\",\n    Values: builder.H{\n        \"name\": \"John\",\n    },\n    Where: builder.ParseWhere(\"id = ?\", 1) // Used to initiate the value (if needed)\n    // To initiate empty value :\n    // builder.NewWhere()\n}\n\n// You can also use where like following :\n// u.Where.And(\"id = ?\", 1)\n\nprintln(u.String()) // UPDATE users SET name = ? WHERE id = ?\n\nr, err := db.Exec(\u0026u)\n```\n\n#### Delete\n\n```go\n// Example of Delete\nd := builder.Delete{\n    Table: \"users\",\n    Where: builder.ParseWhere(\"id = ?\", 1) // Used to initiate the value (if needed)\n    // To initiate empty value :\n    // builder.NewWhere()\n}\n\n// You can also use where like following :\n// d.Where.And(\"id = ?\", 1)\n\nprintln(d.String()) // DELETE FROM users WHERE id = ?\n\nr, err := db.Exec(\u0026d)\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkovacou%2Fgo-database","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkovacou%2Fgo-database","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkovacou%2Fgo-database/lists"}