Files
pgm/README.md

82 lines
3.1 KiB
Markdown
Raw Normal View History

2025-07-27 06:08:27 +00:00
# pgm - PostgreSQL Query Mapper
2025-07-26 18:34:56 +05:30
2025-07-27 06:08:27 +00:00
A lightweight ORM built on top of [jackc/pgx](https://github.com/jackc/pgx) database connection pool.
2025-07-26 18:34:56 +05:30
2025-07-27 06:08:27 +00:00
## ORMs I Like in the Go Ecosystem
2025-07-27 06:08:27 +00:00
- [ent](https://github.com/ent/ent)
- [sqlc](https://github.com/sqlc-dev/sqlc)
2025-07-27 06:08:27 +00:00
## Why Not Use `ent`?
2025-07-27 06:08:27 +00:00
`ent` is a feature-rich ORM with schema definition, automatic migrations, integration with `gqlgen` (GraphQL server), and more. It provides nearly everything you could want in an ORM.
2025-07-27 06:08:27 +00:00
However, it can be overkill. The generated code supports a wide range of features, many of which you may not use, significantly increasing the compiled binary size.
2025-07-27 06:08:27 +00:00
## Why Not Use `sqlc`?
2025-07-27 06:08:27 +00:00
`sqlc` is a great tool, but it often feels like the database layer introduces its own models. This forces you to either map your applications models to these database models or use the database models directly, which may not align with your applications design.
2025-07-27 06:08:27 +00:00
## Issues with Existing ORMs
2025-07-27 06:08:27 +00:00
Here are some common pain points with ORMs:
2025-07-27 06:08:27 +00:00
- **Auto Migrations**: Many ORMs either lack robust migration support or implement complex methods for simple schema changes. This can obscure the database schema, making it harder to understand and maintain. A database schema should be defined in clear SQL statements that can be tested in a SQL query editor. Tools like [dbmate](https://github.com/amacneil/dbmate) provide a mature solution for managing migrations, usable via CLI or in code.
2025-07-27 06:08:27 +00:00
- **Excessive Code Generation**: ORMs often generate excessive code for various conditions and scenarios, much of which goes unused.
2025-07-27 06:08:27 +00:00
- **Generated Models for Queries**: Auto-generated models for `SELECT` queries force you to either adopt them or map them to your applications models, adding complexity.
2025-07-27 06:08:27 +00:00
## A Hybrid Approach: Plain SQL Queries with `pgm`
Plain SQL queries are not inherently bad but come with challenges:
- **Schema Change Detection**: Changes in the database schema are not easily detected.
- **SQL Injection Risks**: Without parameterized queries, SQL injection becomes a concern.
`pgm` addresses these issues by providing a lightweight CLI tool that generates Go files for your database schema. These files help you write SQL queries while keeping track of schema changes, avoiding hardcoded table and column names.
## Generating `pgm` Schema Files
Run the following command to generate schema files:
```bash
2025-07-27 06:10:24 +00:00
go run code.partial.tech/go/pgm/cmd -o ./db ./schema.sql
```
once you have the schama files created you can use `pgm` as
```go
package main
2025-07-27 06:12:11 +00:00
import (
"code.partial.tech/go/pgm"
"myapp/db/user" // scham create by pgm/cmd
)
2025-07-27 06:10:24 +00:00
type MyModel struct {
ID string
Email string
}
func main() {
println("Initializing pgx connection pool")
pgm.InitPool(pgm.Config{
ConnString: url,
})
// Select query to fetch the first record
// Assumes the schema is defined in the "db" package with a User table
var v MyModel
2025-07-27 06:12:11 +00:00
err := db.User.Select(user.ID, user.Email).
Where(user.Email.Like("anki%")).
2025-07-27 06:10:24 +00:00
First(context.TODO(), &v.ID, &v.Email)
if err != nil {
println("Error:", err.Error())
return
}
println("User email:", v.Email)
}
```