{"id":15661026,"url":"https://github.com/emicklei/pgtalk","last_synced_at":"2025-04-30T16:07:40.482Z","repository":{"id":42458506,"uuid":"379064121","full_name":"emicklei/pgtalk","owner":"emicklei","description":"Go code generator to access PostgreSQL tables and views on top of pgx","archived":false,"fork":false,"pushed_at":"2025-04-07T08:29:11.000Z","size":376,"stargazers_count":22,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-07T09:32:35.811Z","etag":null,"topics":["generics","golang","orm","pgx"],"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/emicklei.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2021-06-21T21:13:01.000Z","updated_at":"2025-03-26T18:57:10.000Z","dependencies_parsed_at":"2023-01-30T04:45:54.364Z","dependency_job_id":"4d26d495-afd2-4c2d-b997-cef01a644da1","html_url":"https://github.com/emicklei/pgtalk","commit_stats":null,"previous_names":[],"tags_count":103,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emicklei%2Fpgtalk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emicklei%2Fpgtalk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emicklei%2Fpgtalk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emicklei%2Fpgtalk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emicklei","download_url":"https://codeload.github.com/emicklei/pgtalk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251739006,"owners_count":21635891,"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":["generics","golang","orm","pgx"],"created_at":"2024-10-03T13:25:26.727Z","updated_at":"2025-04-30T16:07:40.469Z","avatar_url":"https://github.com/emicklei.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pgtalk\n\n[![GoDoc](https://pkg.go.dev/badge/github.com/emicklei/pgtalk)](https://pkg.go.dev/github.com/emicklei/pgtalk)\n\nMore type safe SQL query building and execution using Go code generated (pgtalk-gen) from PostgreSQL table definitions.\nAfter code generation, you get a Go type for each table or view with functions to create a QuerySet or MutationSet value.\nExcept for query exectution, all operations on a QuerySet or MutationSet will return a copy of that value.\nThis package requires Go SDK version 1.18+ because it uses type parameterization.\n\n## status\n\nThis package is used in production https://ag5.com and https://go-toad.com and its programming API is stable since v1.0.0.\n\n## install\n\n\tgo install github.com/emicklei/pgtalk/cmd/pgtalk-gen@latest\n\n## how to run the generator\n\nThe user in the connection string must have the right privileges to read schema information.\n\n\tPGTALK_CONN=postgresql://usr:pwd@localhost:5432/database pgtalk-gen -s public -o yourpackage\n\tgo fmt ./...\n\nIf you want to include and/or exclude table names, use additional flags such as:\n\n\t-include \"address.*,employee.*\" -exclude \"org.*\"\n\nor views\n\n\t-views -o yourpackage -include \"skills.*\"\n\n## examples\n\nThese examples are from the test package in which a few database tables files (categories,products,things) are generated.\n\n### Insert\n\n\tm := products.Insert(\n\t\tproducts.ID.Set(10),\n\t\tproducts.Code.Set(\"testit\"),\n\t\tproducts.CategoryID.Set(1))\n\n\tit := m.Exec(aConnection)\n\tif err := it.Err(); err != nil {\n\t\t....\n\t}\n\nor by example:\n\n\tp := new(products.Product)\n\tp.SetID(10).SetCode(\"testit\").SetCategoryID(1)\t\t\n\tm := products.Insert(p.Setters()...)\n\n### Update\n\n\tm := products.Update(\n\t\t\tproducts.Code.Set(\"testme\"),\n\t\t\tproducts.CategoryID.Set(1)).\n\t\tWhere(products.ID.Equals(10)).\n\t\tReturning(products.Code)\n\n\tit := m.Exec(aConnection)\t\n\tfor it.HasNext() {\n\t\tp, err := products.Next(p) // p is a *product.Product\n\t\tt.Logf(\"%s,%s\", *p.Code)\n\t}\t\t\n\nor by example\n\n\tp := new(products.Product)\n\tp.SetID(10).SetCode(\"testme\").SetCategoryID(1)\t\t\n\tm := products.Update(p.Setters()...).\n\t\t\tWhere(products.ID.Equals(p.ID)).\n\t\t\tReturning(products.Code)\n\nor by collecting columns first\n\n\tcols := NewColumns()\n\tcols.Add(products.Code.Set(\"testme\"))\n\tif categoryWhasChanged {\n\t\tcols.Add(products.CategoryID.Set(changedValue))\n\t}\n\tm := products.Update(cols...).Where(products.ID.Equals(10)).\n\n### Delete\n\n\tm := products.Delete().Where(products.ID.Equals(10))\n\n\t_ = m.Exec(aConnection)\n\n### Select\n\n\tq := products.Select(products.Code).Where(products.Code.Equals(\"F42\"))\n\n\tproducts, err := q.Exec(aConnection) // products is a []*product.Product\n\n### Arbitrary SQL expressions\n\n\tq := products.Select(products.ID, pgtalk. SQLAs(\"UPPER(p1.Code)\", \"upper\"))\n\t\n\t// SELECT p1.id,UPPER(p1.Code) AS upper FROM public.products p1\n\t\n\tlist, _ := q.Exec(context.Background(),aConnection)\n\tfor _, each := range list {\n\t\tupper := each.GetExpressionResult(\"upper\").(string)\n\t\t...\n\t}\n\n### SQL query records as maps\n\n\tq := products.Select(products.ID, pgtalk. SQLAs(\"UPPER(p1.Code)\", \"upper\"))\n\n\t// SELECT p1.id,UPPER(p1.Code) AS upper FROM public.products p1\n\n\tlistOfMaps, _ := q.ExecIntoMaps(context.Background(),aConnection)\n\tfor _, each := range listOfMaps {\n\t\tid := products.ID.Get(each).(pgtype.UUID)\n\t\tupper := each[\"upper\"].(string)\n\t\t...\n\t}\n\n## Using Query parameter\n\n\tp := NewParameter(\"F42\")\n\tq := products.Select(products.Code).Where(products.Code.Equals(p))\n\n\t// SELECT p1.code FROM public.products p1 WHERE (p1.code = $1)\n\t// with $1 = \"F42\"\n\n## Joins\n\n### Left Outer Join\n\n    q :=products.Select(products.Code).Where(products.Code.Equals(\"F42\")).\n        LeftOuterJoin(categories.Select(categories.Title)).\n        On(products.ID.Equals(categories.ID))\n\n\tit, _ := q.Exec(aConnection)\n\tfor it.HasNext() {\n\t\tp := new(products.Product)\n\t\tc := new(categories.Category)\n\t\t_ = it.Next(p, c)\n\t\tt.Logf(\"%s,%s\", *p.Code, *c.Title)\n\t}\n\n### Multi Join\n\n\tpSet := products.Select(products.ID, products.Code, products.Title)\n\tfSet := features.Select(features.ID, features.Code, features.Title)\n\trSet := product_feature.Select(product_feature.ProductId, product_feature.FeatureId)\n\n\tquery := pSet.LeftOuterJoin(rSet).On(product_feature.ProductId.Equals(products.ID)).\n\t\tLeftOuterJoin(fSet).On(product_feature.FeatureId.Equals(features.ID)).\n\t\tNamed(\"products-and-features\")\n\n\tit, err := query.Exec(ctx, conn)\n\t...\n\t\n\tfor it.HasNext() {\n\t\tvar product products.Product\n\t\tvar feature features.Feature\n\t\tvar relation product_feature.ProductFeature\n\t\terr := it.Next(\u0026product, \u0026relation, \u0026feature)\n\t\t...\n\t}\n\n### Text Search\n\nSetting a string value for a `tsvector` typed column called \"title_tokens\".\n\n\tmut := categories.Insert(\n\t\tcategories.ID.Set(1234),\n\t\tcategories.Title.Set(convert.StringToText(txt)),\n\t\tpgtalk.NewTSVector(categories.TitleTokens, txt),\n\t)\n\nUsing `tsquery` in a search condition\n\n\tq := categories.\n\t\tSelect(categories.Columns()...).\n\t\tWhere(pgtalk.NewTSQuery(categories.TitleTokens, \"quick\"))\n\n### Union, Intersect, Except\n\nQuerySets can be combined into one using any of UNION, INTERSECT or EXCEPT with nesting.\nBecause you typically collect fields from different tables, which are mapped to different Go structs,\nyou can only execute the query with Go maps are results.\n\nIn the example below, each set is extended with a custom SQL expression to have a type indicator.\n\n\tleft := categories.Select(categories.ID, pgtalk.SQLAs(\"'category'\", \"type\"))\n\tright := products.Select(products.ID, pgtalk.SQLAs(\"'product'\", \"type\"))\n\tq := left.Union(right)\n\tlist, err := q.ExecIntoMaps(context.Background(), testConnect)\n\n\n## supported Column Types\n\n- bigint\n- integer\n- jsonb\n- json\n- uuid\n- point\n- interval\n- timestamp with time zone\n- date\n- text\n- character varying\n- numeric\n- boolean\n- timestamp without time zone\n- daterange\n- bytea\n- text[]\n- citext\n- double precision\n- decimal\n\nSend me a PR for a missing type available from https://www.postgresql.org/docs/9.5/datatype.html by modifying `mapping.go` in the `cmd/pgtalk-gen` package.\n\n## custom datatype mappping\n\nIf your datatype can be aliased (use) to one of the supported types then you can define such mapping in a configuration file.\n\n\tpgtalk-gen -mapping your-mapping.json\n\nAn example of such as mapping file `your-mapping.json`:\n\n\t{\n\t\t\"character(26)\": {\n\t\t\t\"use\": \"character varying\"\n\t\t}\n\t}\n\nIf your datatype cannot be aliased then you can write the missing logic for a datatype and an accessor type.\nSee example `test/types/real.go` for such an implementation.\nThe configuration for this mapping is:\n\n\t{\n\t\t\"real\":{\n\t\t\t\"nullableFieldType\":\"types.Real\",\n\t\t\t\"newAccessFuncName\":\"types.NewRealAccess\",\n\t\t\t\"imports\": [\"github.com/emicklei/pgtalk/test/types\"]\n\t\t}\n\t}\n\n(c) 2025, https://ernestmicklei.com. MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femicklei%2Fpgtalk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femicklei%2Fpgtalk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femicklei%2Fpgtalk/lists"}