Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/emicklei/pgtalk
generics package and code generator to access PostgreSQL tables and views on top of pgx
https://github.com/emicklei/pgtalk
generics golang orm pgx
Last synced: about 2 months ago
JSON representation
generics package and code generator to access PostgreSQL tables and views on top of pgx
- Host: GitHub
- URL: https://github.com/emicklei/pgtalk
- Owner: emicklei
- License: mit
- Created: 2021-06-21T21:13:01.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-09-25T07:00:43.000Z (3 months ago)
- Last Synced: 2024-10-04T13:25:24.148Z (3 months ago)
- Topics: generics, golang, orm, pgx
- Language: Go
- Homepage:
- Size: 340 KB
- Stars: 19
- Watchers: 4
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# pgtalk
[![GoDoc](https://pkg.go.dev/badge/github.com/emicklei/pgtalk)](https://pkg.go.dev/github.com/emicklei/pgtalk)
More type safe SQL query building and execution using Go code generated (pgtalk-gen) from PostgreSQL table definitions.
After code generation, you get a Go type for each table or view with functions to create a QuerySet or MutationSet value.
Except for query exectution, all operations on a QuerySet or MutationSet will return a copy of that value.
This package requires Go SDK version 1.18+ because it uses type parameterization.## status
This package is used in production https://ag5.com and https://go-toad.com and its programming API is stable since v1.0.0.
## install
go install github.com/emicklei/pgtalk/cmd/pgtalk-gen@latest
## examples
These examples are from the test package in which a few database tables files (categories,products,things) are generated.
### Insert
m := products.Insert(
products.ID.Set(10),
products.Code.Set("testit"),
products.CategoryID.Set(1))it := m.Exec(aConnection)
if err := it.Err(); err != nil {
....
}or by example:
p := new(products.Product)
p.SetID(10).SetCode("testit").SetCategoryID(1)
m := products.Insert(p.Setters()...)### Update
m := products.Update(
products.Code.Set("testme"),
products.CategoryID.Set(1)).
Where(products.ID.Equals(10)).
Returning(products.Code)it := m.Exec(aConnection)
for it.HasNext() {
p, err := products.Next(p) // p is a *product.Product
t.Logf("%s,%s", *p.Code)
}or by example
p := new(products.Product)
p.SetID(10).SetCode("testme").SetCategoryID(1)
m := products.Update(p.Setters()...).
Where(products.ID.Equals(p.ID)).
Returning(products.Code)### Delete
m := products.Delete().Where(products.ID.Equals(10))
_ = m.Exec(aConnection)
### Select
q := products.Select(products.Code).Where(products.Code.Equals("F42"))
products, err := q.Exec(aConnection) // products is a []*product.Product
### Arbitrary SQL expressions
q := products.Select(products.ID, pgtalk. SQLAs("UPPER(p1.Code)", "upper"))
// SELECT p1.id,UPPER(p1.Code) AS upper FROM public.products p1
list, _ := q.Exec(context.Background(),aConnection)
for _, each := range list {
upper := each.GetExpressionResult("upper").(string)
...
}### SQL query records as maps
q := products.Select(products.ID, pgtalk. SQLAs("UPPER(p1.Code)", "upper"))
// SELECT p1.id,UPPER(p1.Code) AS upper FROM public.products p1
listOfMaps, _ := q.ExecIntoMaps(context.Background(),aConnection)
for _, each := range listOfMaps {
id := products.ID.Get(each).(pgtype.UUID)
upper := each["upper"].(string)
...
}## Using Query parameter
p := NewParameter("F42")
q := products.Select(products.Code).Where(products.Code.Equals(p))// SELECT p1.code FROM public.products p1 WHERE (p1.code = $1)
// with $1 = "F42"## Joins
### Left Outer Join
q :=products.Select(products.Code).Where(products.Code.Equals("F42")).
LeftOuterJoin(categories.Select(categories.Title)).
On(products.ID.Equals(categories.ID))it, _ := q.Exec(aConnection)
for it.HasNext() {
p := new(products.Product)
c := new(categories.Category)
_ = it.Next(p, c)
t.Logf("%s,%s", *p.Code, *c.Title)
}### Multi Join
q := offer.Select(offer.Columns()...).
Where(offer.ID.In("01F674G8MDRAPBWA6SB1HWE2VC").And(offer.IsActive.Equals(true))).
LeftOuterJoin(offer_buyer_permission_rel.Select(offer_buyer_permission_rel.BuyerPermission)).
On(offer_buyer_permission_rel.OfferId.Equals(offer.ID)).
LeftOuterJoin(offer_market_rel.Select(offer_market_rel.MarketId)).
On(offer_market_rel.OfferId.Equals(offer.ID)).
LeftOuterJoin(buyer_market_rel.Select().Where(buyer_market_rel.BuyerId.Equals("X1010_0100002"))).
On(offer_market_rel.MarketId.Equals(offer_market_rel.MarketId))t.Log(pgtalk.PrettySQL(q))
it, err := q.Exec(context.Background(), testConnect)
if err != nil {
t.Fatal(err)
}
for it.HasNext() {
offer := new(offer.Offer)
permission := new(offer_buyer_permission_rel.OfferBuyerPermissionRel)
market := new(offer_market_rel.OfferMarketRel)
// The order and types of the entities must match the order of the non-empty Select functions used in the query
err := it.Next(offer, permission, market)
if err != nil {
t.Fatal(err)
}
t.Log(offer)
t.Log(permission)
t.Log(market)
}## supported Column Types
- bigint
- integer
- jsonb
- json
- uuid
- point
- interval
- timestamp with time zone
- date
- text
- character varying
- numeric
- boolean
- timestamp without time zone
- daterange
- bytea
- text[]
- citext
- double precision
- decimalSend 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.
## how to run the generator
The user in the connection string must have the right privileges to read schema information.
PGTALK_CONN=postgresql://usr:pwd@host:5432/database pgtalk-gen -o yourpackage
go fmt ./...If you want to include and/or exclude table names, use additional flags such as:
pgtalk-gen -o yourpackage -include "address.*,employee.*" -exclude "org.*"
or views
pgtalk-gen -views -o yourpackage -include "skills.*"
(c) 2023, https://ernestmicklei.com. MIT License.