Skip to content

Commit

Permalink
json tags omit empty
Browse files Browse the repository at this point in the history
* update readme

* fix readme

* improve update method

* fix WhereParams

* omitempty json tag
  • Loading branch information
sxwebdev authored Feb 4, 2022
1 parent e0182b4 commit 8a169cc
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 47 deletions.
29 changes: 22 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

pgxgen use [`sqlc`](https://github.com/kyleconroy/sqlc) tool with additional improvements.

- Prefere using [`pgx/v4`](https://github.com/jackc/pgx) instead of `database/sql`
- Instead null types like `sql.NullString` used nil type `*string`
- Auto generate CRUD for existing tables in postgresql database
- Json tags: Omit empty and hide

## Install

Expand All @@ -27,10 +27,19 @@ version: 1
# Result SQL file name; default: crud_queries.sql
# Will save to `queries` path from `sqlc.yaml` config
output_crud_sql_file_name: "crud_queries.sql"
json_tags:
# List of struct fields
# Convert: `json:"field_name"` => `json:"field_name,omitempty"`
omitempty:
- created_at
# List of struct fields
# Convert: `json:"field_name"` => `json:"-"`
hide:
- password
crud_params:
# Limit and offset for `Find` method
limit:
# List tables or asterisk (*)
# List of tables or asterisk (*)
- "*"
# Order by for `Find` method
order_by:
Expand All @@ -45,7 +54,7 @@ crud_params:
# u - update
# d - delete
# t - total
# available asterisk (*) for all methods (gfudt) expect create
# available asterisk (*) for all methods (gfudt) except create
- methods: "gfudt"
# List of tables or asterisk (*)
tables:
Expand Down Expand Up @@ -74,8 +83,8 @@ packages:
- path: "./internal/store"
name: "store"
engine: "postgresql"
schema: "migrations"
queries: "sql"
schema: "sql/migrations"
queries: "sql/queries"
sql_package: "pgx/v4"
emit_prepared_queries: false
emit_json_tags: true
Expand All @@ -88,8 +97,14 @@ packages:
emit_params_struct_pointers: false
```

### Generate `db`, `models` and `interface`
### Generate `sqlc`

```bash
pgxgen generate
pgxgen sqlc generate
```

## Roadmap

- Hooks for `Create` and `Update`. Example: `model.Validate()`
- Implement pagination hook for `Find`
- Generate custom fields for `Create`, `Update`, `Get`, `Find` instead of `*`
43 changes: 26 additions & 17 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,38 @@ type SqlcConfig struct {
}

type Package struct {
EmitPreparedQueries bool `yaml:"emit_prepared_queries"`
Path string `yaml:"path"`
Engine string `yaml:"engine"`
EmitDbTags bool `yaml:"emit_db_tags"`
Name string `yaml:"name"`
EmitJsonTags bool `yaml:"emit_json_tags"`
EmitExactTableNames bool `yaml:"emit_exact_table_names"`
EmitEmptySlices bool `yaml:"emit_empty_slices"`
EmitResultStructPointers bool `yaml:"emit_result_struct_pointers"`
EmitParamsStructPointers bool `yaml:"emit_params_struct_pointers"`
Schema string `yaml:"schema"`
Queries string `yaml:"queries"`
SqlPackage string `yaml:"sql_package"`
EmitExportedQueries bool `yaml:"emit_exported_queries"`
EmitInterface bool `yaml:"emit_interface"`
Name string `yaml:"name"`
Path string `yaml:"path"`
Queries string `yaml:"queries"`
Schema string `yaml:"schema"`
Engine string `yaml:"engine"`
EmitPreparedQueries bool `yaml:"emit_prepared_queries"`
EmitInterface bool `yaml:"emit_interface"`
EmitExactTableNames bool `yaml:"emit_exact_table_names"`
EmitEmptySlices bool `yaml:"emit_empty_slices"`
EmitExportedQueries bool `yaml:"emit_exported_queries"`
EmitJsonTags bool `yaml:"emit_json_tags"`
EmitResultStructPointers bool `yaml:"emit_result_struct_pointers"`
EmitParamsStructPointers bool `yaml:"emit_params_struct_pointers"`
EmitMethodsWithDbArgument bool `yaml:"emit_methods_with_db_argument"`
JsonTagsCaseStyle string `yaml:"json_tags_case_style"`
OutputDbFileName string `yaml:"output_db_file_name"`
OutputModelsFileName string `yaml:"output_models_file_name"`
OutputQuerierFileName string `yaml:"output_querier_file_name"`
}

type PgxgenConfig struct {
Version int `yaml:"version"`
OutputCrudSqlFileName string `yaml:"output_crud_sql_file_name"`
JsonTags JsonTags `yaml:"json_tags"`
CrudParams CrudParams `yaml:"crud_params"`
}

type JsonTags struct {
Omitempty []string `yaml:"omitempty"`
Hide []string `yaml:"hide"`
}

type CrudParams struct {
Limit []string `yaml:"limit"`
OrderBy []OrderBy `yaml:"order_by"`
Expand All @@ -53,7 +62,7 @@ type OrderBy struct {
Tables []string `yaml:"tables"`
}

// `Where` used for all method expect `create`. Instead of listing all methods, you can use an asterisk: *
// `Where` used for all method except `create`. Instead of listing all methods, you can use an asterisk: *
type Where struct {
Methods string `yaml:"methods"`
Tables []string `yaml:"tables"`
Expand All @@ -65,7 +74,7 @@ func (p *PgxgenConfig) GetWhereParams(table, method string) []string {

for _, item := range p.CrudParams.Where {
method = strings.ToLower(method)
if method == "c" || (method != "*" && !strings.Contains(strings.ToLower(item.Methods), method)) {
if method == "c" || (item.Methods != "*" && !strings.Contains(strings.ToLower(item.Methods), method)) {
continue
}
if !utils.ExistInArray(item.Tables, "*") && !utils.ExistInArray(item.Tables, table) {
Expand Down
8 changes: 5 additions & 3 deletions internal/pgxgen/crud.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func processUpdate(p processCRUDParams) error {
methodName = string(methodName[:len(methodName)-1])
}

p.builder.WriteString(fmt.Sprintf("-- name: %s :exec\n", methodName))
p.builder.WriteString(fmt.Sprintf("-- name: %s :one\n", methodName))
p.builder.WriteString("UPDATE ")
p.builder.WriteString(p.table)
p.builder.WriteString("\n\tSET ")
Expand Down Expand Up @@ -248,11 +248,13 @@ func processUpdate(p processCRUDParams) error {
return err
}
if lastIndex == 1 {
p.builder.WriteString(fmt.Sprintf("WHERE id=$%d;\n\n", lastIndex))
p.builder.WriteString(fmt.Sprintf("WHERE id=$%d", lastIndex))
} else {
p.builder.WriteString(fmt.Sprintf(" AND id=$%d;\n\n", lastIndex))
p.builder.WriteString(fmt.Sprintf(" AND id=$%d", lastIndex))
}

p.builder.WriteString("\n\tRETURNING *;\n\n")

return nil
}

Expand Down
51 changes: 40 additions & 11 deletions internal/pgxgen/pgxgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"gopkg.in/yaml.v3"
)

var version = "0.0.3"
var version = "0.0.4"

func Start(args []string) error {

Expand Down Expand Up @@ -59,17 +59,19 @@ func Start(args []string) error {

switch args[0] {
case "version":
fmt.Printf("App version: %s;\nGo version: %s\n", version, runtime.Version())
fmt.Printf("Tool version: %s;\nGo version: %s\n", version, runtime.Version())
case "gencrud":
if err := genCRUD(args, c); err != nil {
return err
}
fmt.Println("crud successfully generated")
default:
if err := processSqlc(args, c); err != nil {
case "sqlc":
if err := processSqlc(args[1:], c); err != nil {
return err
}
fmt.Println("sqlc successfully generated")
default:
return fmt.Errorf("undefined command %s", args[0])
}

return nil
Expand All @@ -89,10 +91,21 @@ func processSqlc(args []string, c config.Config) error {
return err
}

modelFileName := p.OutputModelsFileName
if modelFileName == "" {
modelFileName = "models.go"
}

for _, file := range files {
r := regexp.MustCompile(`(\.go)`)
if r.MatchString(file.Name()) {
if err := replaceStructTypes(filepath.Join(p.Path, file.Name())); err != nil {
if err := replace(c, filepath.Join(p.Path, file.Name()), replaceStructTypes); err != nil {
return err
}
}

if file.Name() == modelFileName {
if err := replace(c, filepath.Join(p.Path, file.Name()), replaceJsonTags); err != nil {
return err
}
}
Expand All @@ -102,17 +115,33 @@ func processSqlc(args []string, c config.Config) error {
return nil
}

func replaceStructTypes(path string) error {
func replaceStructTypes(c config.Config, str string) string {
res := str
for old, new := range types {
res = strings.ReplaceAll(res, old, new)
}
return res
}

func replaceJsonTags(c config.Config, str string) string {
res := str
for _, field := range c.Pgxgen.JsonTags.Omitempty {
res = strings.ReplaceAll(res, fmt.Sprintf("json:\"%s\"", field), fmt.Sprintf("json:\"%s,omitempty\"", field))
}
for _, field := range c.Pgxgen.JsonTags.Hide {
res = strings.ReplaceAll(res, fmt.Sprintf("json:\"%s\"", field), "json:\"-\"")
}
return res
}

func replace(c config.Config, path string, fn func(c config.Config, str string) string) error {

models, err := os.ReadFile(path)
file, err := os.ReadFile(path)
if err != nil {
return err
}

result := string(models)
for old, new := range types {
result = strings.ReplaceAll(result, old, new)
}
result := fn(c, string(file))

formated, err := imports.Process(path, []byte(result), nil)
if err != nil {
Expand Down
21 changes: 12 additions & 9 deletions internal/pgxgen/replace.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ package pgxgen

var helpMessage = `Available Commands:
gencrud -c Generate CRUD SQL. -c SQL_CONN_STRING
compile Statically check SQL for syntax and type errors
completion Generate the autocompletion script for the specified shell
generate Generate Go code from SQL
help Help about any command
init Create an empty sqlc.yaml settings file
version Print the pgxgen version number
sqlc
compile Statically check SQL for syntax and type errors
completion Generate the autocompletion script for the specified shell
generate Generate Go code from SQL
help Help about any command
init Create an empty sqlc.yaml settings file
version Print the sqlc version number
Flags:
-x, --experimental enable experimental features (default: false)
-f, --file string specify an alternate config file (default: sqlc.yaml)
-h, --help help for sqlc
Flags:
-x, --experimental enable experimental features (default: false)
-f, --file string specify an alternate config file (default: sqlc.yaml)
-h, --help help for sqlc
`

var types map[string]string = map[string]string{
Expand Down

0 comments on commit 8a169cc

Please sign in to comment.