{"id":15050621,"url":"https://github.com/darlinggo/pan","last_synced_at":"2025-07-31T06:38:37.767Z","repository":{"id":57510777,"uuid":"12402532","full_name":"darlinggo/pan","owner":"darlinggo","description":"SQL generator written in Go.","archived":false,"fork":false,"pushed_at":"2024-12-06T16:09:44.000Z","size":112,"stargazers_count":5,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-10T02:18:21.035Z","etag":null,"topics":["golang","mysql","postgresql","sql","sqlite"],"latest_commit_sha":null,"homepage":"https://darlinggo.co/pan","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/darlinggo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-08-27T09:48:42.000Z","updated_at":"2024-10-05T03:11:50.000Z","dependencies_parsed_at":"2024-01-12T17:28:44.301Z","dependency_job_id":"6c51e255-678d-468c-8bbb-6158d134e13f","html_url":"https://github.com/darlinggo/pan","commit_stats":{"total_commits":87,"total_committers":11,"mean_commits":7.909090909090909,"dds":0.5747126436781609,"last_synced_commit":"1a6be3f9f7035cd672360e733f2cf806dcfc7047"},"previous_names":["secondbit/pan"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/darlinggo/pan","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darlinggo%2Fpan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darlinggo%2Fpan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darlinggo%2Fpan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darlinggo%2Fpan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darlinggo","download_url":"https://codeload.github.com/darlinggo/pan/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darlinggo%2Fpan/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267999928,"owners_count":24178880,"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-07-31T02:00:08.723Z","response_time":66,"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":["golang","mysql","postgresql","sql","sqlite"],"created_at":"2024-09-24T21:28:07.354Z","updated_at":"2025-07-31T06:38:37.744Z","avatar_url":"https://github.com/darlinggo.png","language":"Go","readme":"# Importing pan\n    import \"darlinggo.co/pan\"\n\n# About pan\n\n`pan` is an SQL query building and response unmarshalling library for Go. It is designed to be compatible with MySQL, PostgreSQL, and SQLite, but should be more or less agnostic.\nPlease let us know if your favourite SQL flavour is not supported.\n\nPan is not designed to be an ORM, but it still eliminates much of the boilerplate code around writing queries and scanning over rows.\n\nPan’s design focuses on reducing repetition and hardcoded strings in your queries, but without limiting your ability to write any form of query you want.\nIt is meant to be the smallest possible abstraction on top of SQL.\n\nDocs can be found on [pkg.go.dev](https://pkg.go.dev/darlinggo.co/pan).\n\n# Using pan\n\nPan revolves around structs that fill the `SQLTableNamer` interface, by implementing the `GetSQLTableName() string` function, which just returns the name of the table that should store the data for that struct.\n\nLet's say you have a `Person` in your code.\n\n```go\ntype Person struct {\n    ID    int     `sql_column:\"person_id\"`\n    FName string  `sql_column:\"fname\"`\n    LName string  `sql_column:\"lname\"`\n    Age   int\n}\n```\n\nAnd you have a corresponding `Person` table:\n\n```\n+-----------+-------------+------+-----+---------+-------+\n| Field     | Type        | Null | Key | Default | Extra |\n+-----------+-------------+------+-----+---------+-------+\n| person_id | int         | NO   |     | NULL    |       |\n| fname     | varchar(20) | NO   |     | ''      |       |\n| lname     | varchar(20) | NO   |     | ''      |       |\n| age       | int         | NO   |     | 0       |       |\n+-----------+-------------+------+-----+---------+-------+\n```\n\n\u003e **Note**: Unless you're using sql.NullString or equivalent, it's not recommended to allow `NULL` in your data.\nIt may cause you trouble when unmarshaling.\n\nTo use that `Person` type with pan, you need it to fill the `SQLTableNamer` interface, letting pan know to use the `person` table in your database:\n\n```go\nfunc (p Person) GetSQLTableName() string {\n    return \"person\"\n}\n```\n\n## Creating a query\n\n```go\n// selects all rows\nvar p Person\nquery := pan.New(pan.MYSQL, \"SELECT \"+pan.Columns(p).String()+\" FROM \"+pan.Table(p))\n```\n\nor\n\n```go\n// selects one row\nvar p Person\nquery := pan.New(pan.MYSQL, \"SELECT \"+pan.Columns(p).String()+\" FROM \"+pan.Table(p)).Where()\nquery.Comparison(p, \"ID\", \"=\", 1)\nquery.Flush(\" \")\n```\n\nThat `Flush` command is important: pan works by creating a buffer of strings, and then joining them by some separator character.\nFlush takes the separator character (in this case, a space) and uses it to join all the buffered strings (in this case, the `WHERE` statement and the `person_id = ?` statement), and then adds the result to its query.\n\n\u003e It's safe to call `Flush` even if there are no buffered strings, so a good practice is to just call `Flush` after the entire query is built, just to make sure you don't leave anything buffered.\n\nThe `pan.Columns()` function returns the column names that a struct's properties correspond to.\n`pan.Columns().String()` joins them into a list of columns that can be passed right to the `SELECT` expression, making it easy to support reading only the columns you need, maintaining forward compatibility—your code will never choke on unexpected columns being added.\n\n## Executing the query and reading results\n\n```go\nmysql, err := query.MySQLString() // could also be PostgreSQLString or SQLiteString\nif err != nil {\n\t// handle the error\n}\nrows, err := db.Query(mysql, query.Args...)\nif err != nil {\n\t// handle the error\n}\nvar people []Person\nfor rows.Next() {\n\tvar p Person\n        err := pan.Unmarshal(rows, \u0026p) // put the results into the struct\n        if err != nil {\n        \t// handle the error\n        }\n        people = append(people, p)\n}\n```\n\n## How struct properties map to columns\n\nThere are a couple rules about how struct properties map to column names.\nFirst, only exported struct properties are used; unexported properties are ignored.\n\nBy default, a struct property's name is snake-cased, and that is used as the column name.\nFor example, `Name` would become `name`, and `MyInt` would become `my_int`.\n\nIf you want more control or want to make columns explicit, the `sql_column` struct tag can be used to override this behaviour.\n\n## Column flags\n\nSometimes, you need more than the base column name; you may need the full name (`table.column`) or you may be using special characters/need to quote the column name (`\"column\"` for Postgres, `\\`column`\\` for MySQL).\nTo support these use cases, the `Column` and `Columns` functions take a variable number of flags (including none):\n\n```go\nColumns() // returns column format\nColumns(FlagFull) // returns table.column format\nColumns(FlagDoubleQuoted) // returns \"column\" format\nColumns(FlagTicked) // returns `column` format\nColumns(FlagFull, FlagDoubleQuoted) // returns \"table\".\"column\" format\nColumns(FlagFull, FlagTicked) // returns `table`.`column` format\n```\n\nThis behaviour is not exposed through the convenience functions built on top of `Column` and `Columns`; you'll need to use `Expression` to rebuild them by hand.\nUsually, this can be done simply; look at the source code for those convenience functions for examples.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarlinggo%2Fpan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarlinggo%2Fpan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarlinggo%2Fpan/lists"}