Data phrasebook pattern and code generation for SQL.
SQL is the right way to interact with relational databases! By adding simple
annotations to SQL a phrasebook creates clear separation between SQL and Go
allowing for template driven code generation. Use go:generate
to export
constants, functions, documentation, tests and more from SQL.
Start with SQL, say repository.sql
and add an -- export
and -- end
annotations to any SQL you'd like to export.
-- List staff with a birthday for @date so you can buy them a beer.
-- export: SelectStaffBirthdaysSQL
select u.*
from users u
where
role_in(u.id, 'staff')
and u.birthday = coalesce(@date, current_date)::date;
-- end
Create a repository.go
package and use const
to generated SQL string constants.
package repository
// go:generate go-gen-phrasebook -package repository -template=const repository.sql
func ListStaffBirthdays() ([]*User, error) {
rows, err := db.Query(SelectStaffBirthdaysSQL, sql.Named("date", time.Now()))
// ...
}
The go:generate
const template generates repository.sql.go
with string constants.
// Generated with ❤ ; DO NOT EDIT
// generator: github.com/techspaceco/phrasebook
// source: repository.sql
// checksum: 7847ef1b36bf2e4b35c76e3a0b1237b9248194ad
// timestamp: 2019-01-02 18:48:32.367803 +0000 UTC
package repository
// List staff with a birthday for @date so you can buy them a beer.
const SelectStaffBirthdaysSQL = "select u.*
from users u
where
role_in(u.id, 'staff')
and u.birthday = coalesce(@date, current_date)::date;"
See the generated documentation and examples.
https://godoc.org/github.com/techspaceco/phrasebook
This phrasebook pattern was a lot more common in the early 2000's before popular ORM libraries started to popularize limiting relational database interaction with SQL abstractions.
https://www.perl.com/pub/2002/10/22/phrasebook.html
This library differs from other Go SQL implementations in the following areas:
- Optional and template driven code generation.
- Optional JSON meta-data retained in export tree allows flexible templates.
- Explicit start/end annotations allow for un-exported comments and source code.
- Leading export comments are matched and retained in generated code.
- The stdlib is the only dependency.
Regexp driven so debugging missing exports due to format errors is a known weakness of the current parser implementation. Luckily the annotation format is very simple.
MIT