{"id":21296858,"url":"https://github.com/reddec/gsql","last_synced_at":"2025-07-11T17:32:01.080Z","repository":{"id":64855897,"uuid":"578645257","full_name":"reddec/gsql","owner":"reddec","description":"Tiny wrapper around SQLX for Generic SQL queries","archived":false,"fork":false,"pushed_at":"2024-10-23T10:36:56.000Z","size":26,"stargazers_count":48,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-02T11:02:01.065Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reddec.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":"2022-12-15T14:46:07.000Z","updated_at":"2025-01-06T15:11:08.000Z","dependencies_parsed_at":"2024-11-28T04:45:17.795Z","dependency_job_id":null,"html_url":"https://github.com/reddec/gsql","commit_stats":{"total_commits":5,"total_committers":1,"mean_commits":5.0,"dds":0.0,"last_synced_commit":"6e829d8c28ae50d66aa1c47b503789d725c5cf95"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/reddec/gsql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Fgsql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Fgsql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Fgsql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Fgsql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reddec","download_url":"https://codeload.github.com/reddec/gsql/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Fgsql/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264862465,"owners_count":23674978,"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":[],"created_at":"2024-11-21T14:30:10.396Z","updated_at":"2025-07-11T17:32:01.074Z","avatar_url":"https://github.com/reddec.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Generic SQL\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/reddec/gsql.svg)](https://pkg.go.dev/github.com/reddec/gsql)\n\nTiny wrapper built around standard Go SQL library and SQLx with generic support.\n\n## Installation\n\n    go get -v github.com/reddec/gsql\n\n## Examples\n\nSchema for the example\n\n```sql\nCREATE TABLE book\n(\n    id     INTEGER NOT NULL PRIMARY KEY,\n    title  TEXT    NOT NULL,\n    author TEXT,\n    year   INTEGER NOT NULL\n)\n```\n\nType in Go\n\n```go\ntype Book struct {\n    ID     int64\n    Title  string\n    Author string\n    Year   int\n}\n```\n\nInitialization\n\n```go\n// ...\nconn, err := sqlx.Open(\"sqlite\", \"database.sqlite\")\n// ...\n```\n\n### Get\n\nGet single book by ID\n\n```go\nbook, err := gsql.Get[Book](ctx, conn, \"SELECT * FROM book WHERE id = ?\", 1234)\n```\n\n### List\n\nList books by author\n\n```go\nbooks, err := gsql.List[Book](ctx, conn, \"SELECT * FROM book WHERE author = ?\", \"O'Really\")\n```\n\n### Iterate\n\nIterate each book one by one\n\n```go\niter := gsql.Iterate[Book](ctx, conn, \"SELECT * FROM book LIMIT ?\", 100)\ndefer iter.Close()\nfor iter.Next() {\n    book, err := iter.Get()\n    // ...\n}\nif iter.Err() != nil {\n    panic(iter.Err()) // use normal handling in real application\n}\n```\n\n### LazyGet\n\nSave query which returns one object and execute it later\n\n```go\ngetBooks := gsql.LazyGet[Book](conn, \"SELECT * FROM book WHERE id = ?\", 123)\n// ...\nbook, err := getBooks(ctx) // can be called many times\n```\n\n### LazyList\n\nSave query which returns multiple objects and execute it later\n\n```go\nlistBooks := gsql.LazyList[Book](conn, \"SELECT * FROM book\")\n// ...\nbooks, err := listBooks(ctx) // can be called many times\n```\n\n### CachedGet\n\nSave query which returns one object and execute it later. Once query executed, result will be cached until `Invalidate`\nor `Refresh` called.\n\n```go\ncache := gsql.CachedGet[Book](conn, \"SELECT * FROM book WHERE id = ?\", 123)\nbook, err := cache.Get(ctx) // first time it will execute the query\n//...\nbook2, err := cache.Get(ctx) // second time it will return cached information\n//...\ncache.Invalidate() // reset cache, the following Get will again execute the query\n```\n\n### CachedList\n\nSave query which returns multiple objects and execute it later. Once query executed, result will be cached\nuntil `Invalidate` or `Refresh` called.\n\n```go\ncache := gsql.CachedList[Book](conn, \"SELECT * FROM book WHERE id = ?\", 123)\nbooks, err := cache.Get(ctx) // first time it will execute the query\n//...\nbooks2, err := cache.Get(ctx) // second time it will return cached information\n//...\ncache.Invalidate() // reset cache, the following Get will again execute the query\n```\n\n\n## Static statements\n\nStatic statements are just plain SQL query wrapped in a type-safe alias.\n\n### Statement\n\nOnly return type is strictly typed. Arguments are positional and can be any type.\n\n```go\nconst (\n\tListBooks gsql.Statement[Book] = `SELECT * FROM book`\n\tGetBook   gsql.Statement[Book] = `SELECT * FROM book WHERE id = ?`\n)\n```\n\nAll query methods supported: `Get`, `List`, `Iterate`\n\n```go\n\nlist, err := ListBooks.List(ctx, conn)\n// ...\nbook, err := GetBook.Get(ctx, conn, 123)\n// ...\n```\n\n### Named statement\n\nBoth return type and arguments are strictly typed. Argument can by struct or a map. \nUses [Named Queries](https://jmoiron.github.io/sqlx/#namedParams).\n\n```go\ntype Query struct {\n    Author string `db:\"author\"`\n}\n\nconst (\n\tFindBookByAuthor gsql.NamedStatement[Book, Query] = `SELECT * FROM book WHERE author = :author`\n)\n```\n\nTypes enforced\n\n\n```go\nbook, err := FindBookByAuthor.Get(ctx, conn, Query{\n    Author: \"Reddec\",\n})\n// ...\n```\n\n## JSON\n\nSimple generic wrapper around any JSON-serializable value: `JSON[T]`.\n\nSupport both reading (scanner) and writing (Value).\n\n### Example\n\nAssuming schema\n\n```sql\nCREATE TABLE book\n(\n    id     INTEGER NOT NULL PRIMARY KEY,\n    title  TEXT    NOT NULL,\n    author TEXT,\n    year   INTEGER NOT NULL,\n    meta   JSONB NOT NULL\n)\n```\n\nGo code\n\n```go\ntype Metadata struct {\n    Zip int\n}\n\ntype Book struct {\n    ID     int64\n    Title  string\n    Author string\n    Year   int\n    Meta   JSON[Metadata]\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freddec%2Fgsql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freddec%2Fgsql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freddec%2Fgsql/lists"}