Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions cli/getConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,23 @@ import (
"encoding/json"
"log"
"os"
"slices"
)

var LogLevels = []string{
"query",
"info",
"warn",
"error",
"all",
"none",
}

type Config struct {
Database DatabaseConfig `json:"database"`
Schema string `json:"schema"`
Output OutputConfig `json:"output"`
Log []string `json:"log"`
}

type DatabaseConfig struct {
Expand All @@ -35,6 +46,20 @@ func GetConfig() *Config {
log.Fatal(err)
return nil
}
// hasAll := false
for _, l := range config.Log {
if l == "all" {
// hasAll = true
}
if !slices.Contains(LogLevels, l) && l != "all" {
log.Fatalf("invalid log level in valkyrie.json: %q (must be one of: query, info, warn, error, all)", l)
return nil
}
}
// if hasAll && len(config.Log) > 1 {
// log.Fatal("invalid log configuration: 'all' must be the only log level specified")
// return nil
// }

return &config
}
2 changes: 1 addition & 1 deletion cli/handleGenerate.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func handleGenerate() {
pkgName = "valkyrie"
}

outputs, err := generator.GenerateClient(*schemaDef, pkgName, embedRelDir, config.Output.Migrations)
outputs, err := generator.GenerateClient(*schemaDef, pkgName, embedRelDir, config.Output.Migrations, config.Log)
if err != nil {
fmt.Printf("failed to generate client: %v\n", err)
return
Expand Down
12 changes: 11 additions & 1 deletion generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,27 @@ type templateData struct {
EmbedDir string
DefaultDiskPath string
Schema schema.Schema
DefaultLogs []string
}

type modelTemplateData struct {
PackageName string
Model *schema.Model
}

func GenerateClient(sch schema.Schema, pkgName string, embedPath string, defaultDiskPath string) (map[string]string, error) {
func GenerateClient(sch schema.Schema, pkgName string, embedPath string, defaultDiskPath string, defaultLogs []string) (map[string]string, error) {
tmpl := template.New("").Funcs(template.FuncMap{
"capitalize": capitalize,
"lowercase": lowercase,
"fkForRelation": fkForRelation,
"hasLog": func(level string) bool {
for _, l := range defaultLogs {
if l == "all" || l == level {
return true
}
}
return false
},
})
tmpl, err := tmpl.ParseFS(templatesFS, "templates/*.gotpl")
if err != nil {
Expand All @@ -47,6 +56,7 @@ func GenerateClient(sch schema.Schema, pkgName string, embedPath string, default
EmbedDir: embedDir,
DefaultDiskPath: defaultDiskPath,
Schema: sch,
DefaultLogs: defaultLogs,
}

outputs := make(map[string]string)
Expand Down
97 changes: 0 additions & 97 deletions generator/generator_test.go

This file was deleted.

8 changes: 4 additions & 4 deletions generator/templates/builders_create.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func executeInsert[M any](

var res M
if q.dialect.SupportsReturning() {
row := q.db.QueryRowContext(ctx, query, vals...)
row := q.queryRow(ctx, query, vals...)

scanTargets := scanFunc(&res, returningCols)
if err := row.Scan(scanTargets...); err != nil {
Expand All @@ -87,7 +87,7 @@ func executeInsert[M any](
}

// Fallback for dialects without RETURNING (MySQL)
result, err := q.db.ExecContext(ctx, query, vals...)
result, err := q.exec(ctx, query, vals...)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -123,7 +123,7 @@ func executeInsert[M any](
selectSb.WriteString(q.dialect.Quote(idCol))
selectSb.WriteString(" = ?")

row := q.db.QueryRowContext(ctx, selectSb.String(), idVal)
row := q.queryRow(ctx, selectSb.String(), idVal)
scanTargets := scanFunc(&res, returningCols)
if err := row.Scan(scanTargets...); err != nil {
return nil, err
Expand Down Expand Up @@ -175,7 +175,7 @@ func loadRelation[P any, C any](
sb.WriteString(")")
query := sb.String()

rows, err := q.db.QueryContext(ctx, query, parentKeys...)
rows, err := q.query(ctx, query, parentKeys...)
if err != nil {
return nil, err
}
Expand Down
119 changes: 117 additions & 2 deletions generator/templates/client.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -83,21 +83,47 @@ func (db *DB) Raw() *sql.DB {
{{- if .EmbedPath }}
// RunMigrations runs all pending migrations from the embedded folder.
func (db *DB) RunMigrations(ctx context.Context) error {
{{- if hasLog "info" }}
log.Println("Running migrations...")
{{- end }}
if err := goose.SetDialect(db.provider); err != nil {
return err
}
goose.SetLogger(goose.NopLogger())
goose.SetBaseFS(migrationsFS)
return goose.UpContext(ctx, db.sqlDB, "{{ .EmbedDir }}")
err := goose.UpContext(ctx, db.sqlDB, "{{ .EmbedDir }}")
if err != nil {
{{- if hasLog "error" }}
log.Printf("Migrations failed: %v", err)
{{- end }}
return err
}
{{- if hasLog "info" }}
log.Println("Migrations completed successfully.")
{{- end }}
return nil
}
{{- else }}
// RunMigrations runs all pending migrations from the disk folder.
func (db *DB) RunMigrations(ctx context.Context) error {
{{- if hasLog "info" }}
log.Println("Running migrations...")
{{- end }}
if err := goose.SetDialect(db.provider); err != nil {
return err
}
goose.SetLogger(goose.NopLogger())
return goose.UpContext(ctx, db.sqlDB, "{{ .DefaultDiskPath }}")
err := goose.UpContext(ctx, db.sqlDB, "{{ .DefaultDiskPath }}")
if err != nil {
{{- if hasLog "error" }}
log.Printf("Migrations failed: %v", err)
{{- end }}
return err
}
{{- if hasLog "info" }}
log.Println("Migrations completed successfully.")
{{- end }}
return nil
}
{{- end }}

Expand All @@ -115,3 +141,92 @@ func (q *Queries) bindVars(count int) string {
}
return sb.String()
}

func (q *Queries) query(ctx context.Context, query string, args ...any) (*sql.Rows, error) {
{{- if hasLog "query" }}
log.Printf("[%s] SQL Query: %s | Args: %v", strings.ToUpper(q.provider), query, args)
{{- end }}
res, err := q.db.QueryContext(ctx, query, args...)
{{- if hasLog "error" }}
if err != nil {
log.Printf("[%s] SQL Error: %v | Query: %s | Args: %v", strings.ToUpper(q.provider), err, query, args)
}
{{- end }}
return res, err
}

func (q *Queries) queryRow(ctx context.Context, query string, args ...any) *sql.Row {
{{- if hasLog "query" }}
log.Printf("[%s] SQL QueryRow: %s | Args: %v", strings.ToUpper(q.provider), query, args)
{{- end }}
return q.db.QueryRowContext(ctx, query, args...)
}

func (q *Queries) exec(ctx context.Context, query string, args ...any) (sql.Result, error) {
{{- if hasLog "query" }}
log.Printf("[%s] SQL Exec: %s | Args: %v", strings.ToUpper(q.provider), query, args)
{{- end }}
res, err := q.db.ExecContext(ctx, query, args...)
{{- if hasLog "error" }}
if err != nil {
log.Printf("[%s] SQL Error: %v | Query: %s | Args: %v", strings.ToUpper(q.provider), err, query, args)
}
{{- end }}
return res, err
}

func (q *Queries) transaction(ctx context.Context, fn func(txQ *Queries) error) error {
if _, ok := q.db.(*sql.Tx); ok {
return fn(q)
}

starter, ok := q.db.(interface {
BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
})
if !ok {
return fn(q)
}

{{- if hasLog "query" }}
log.Printf("[%s] SQL Begin Transaction", strings.ToUpper(q.provider))
{{- end }}
tx, err := starter.BeginTx(ctx, nil)
if err != nil {
return err
}

defer func() {
if p := recover(); p != nil {
{{- if hasLog "query" }}
log.Printf("[%s] SQL Rollback Transaction", strings.ToUpper(q.provider))
{{- end }}
_ = tx.Rollback()
panic(p)
}
}()

txQueries := &Queries{
db: tx,
provider: q.provider,
dialect: q.dialect,
{{- range $enum := .Schema.Enums }}
{{ $enum.Name }}: q.{{ $enum.Name }},
{{- end }}
}
{{- range $model := .Schema.Models }}
txQueries.{{ $model.Name }} = &{{ $model.Name }}Delegate{client: txQueries}
{{- end }}

if err := fn(txQueries); err != nil {
{{- if hasLog "query" }}
log.Printf("[%s] SQL Rollback Transaction", strings.ToUpper(q.provider))
{{- end }}
_ = tx.Rollback()
return err
}

{{- if hasLog "query" }}
log.Printf("[%s] SQL Commit Transaction", strings.ToUpper(q.provider))
{{- end }}
return tx.Commit()
}
1 change: 1 addition & 0 deletions generator/templates/header.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"embed"
{{- end }}
"fmt"
"log"
"strconv"
"strings"
"time"
Expand Down
Loading
Loading