From f0221fe220bd82defe131c3052a447b7e60c1774 Mon Sep 17 00:00:00 2001 From: Cyn <39891200+cynsupercat@users.noreply.github.com> Date: Mon, 10 Apr 2023 13:21:21 +1000 Subject: [PATCH 1/3] Add Inline query + args print --- boil/debug.go | 38 +++++++++++++ boil/debug_test.go | 57 +++++++++++++++++++ .../driver/override/main/17_upsert.go.tpl | 6 +- .../driver/override/main/17_upsert.go.tpl | 12 ++-- .../driver/override/main/17_upsert.go.tpl | 6 +- .../driver/override/main/17_upsert.go.tpl | 6 +- queries/query.go | 19 ++----- 7 files changed, 111 insertions(+), 33 deletions(-) create mode 100644 boil/debug_test.go diff --git a/boil/debug.go b/boil/debug.go index 354d08ba7..5be6c90d8 100644 --- a/boil/debug.go +++ b/boil/debug.go @@ -2,8 +2,11 @@ package boil import ( "context" + "fmt" "io" "os" + "regexp" + "strings" ) // DebugMode is a flag controlling whether generated sql statements and @@ -47,3 +50,38 @@ func DebugWriterFrom(ctx context.Context) io.Writer { } return DebugWriter } + +// PrintQuery prints a modified query string with placeholders replaced by their +// corresponding argument values to writer. +func PrintQuery(writer io.Writer, query string, args ...interface{}) { + substitutedQuery := substituteQueryArgs(query, args...) + fmt.Fprintln(writer, substitutedQuery) +} + +// substituteQueryArgs takes a SQL query string and an array of +// // arguments. It returns a modified query string with placeholders replaced by their +// // corresponding argument values. +func substituteQueryArgs(query string, args ...interface{}) string { + // find all occurrences of placeholders ($1, $2, etc.) in the query + re := regexp.MustCompile(`\$\d+`) + matches := re.FindAllString(query, -1) + + for i, match := range matches { + var arg string + + switch v := args[i].(type) { + case string: + arg = fmt.Sprintf("'%s'", v) + case []byte: + arg = fmt.Sprintf("'%s'", string(v)) + default: + arg = fmt.Sprintf("%v", v) + } + + // replace the placeholder with the argument value + query = strings.Replace(query, match, arg, 1) + } + + // return the final query with argument values + return query +} diff --git a/boil/debug_test.go b/boil/debug_test.go new file mode 100644 index 000000000..a91d92956 --- /dev/null +++ b/boil/debug_test.go @@ -0,0 +1,57 @@ +package boil + +import ( + "testing" +) + +func TestSubstituteQueryArgs(t *testing.T) { + tests := []struct { + query string + args []interface{} + want string + }{ + { + query: `INSERT INTO "my_table" ("id","name","age","height","is_active","data") VALUES ($1,$2,$3,$4,$5,$6)`, + args: []interface{}{ + 1, "Alice", 25, 1.68, true, []byte(`{"key":"value"}`), + }, + want: `INSERT INTO "my_table" ("id","name","age","height","is_active","data") VALUES (1,'Alice',25,1.68,true,'{"key":"value"}')`, + }, + { + query: `UPDATE "my_table" SET "name"=$1,"age"=$2,"height"=$3,"is_active"=$4,"data"=$5 WHERE "id"=$6`, + args: []interface{}{ + "Bob", 30, 1.78, false, []byte(`{"key":123}`), 2, + }, + want: `UPDATE "my_table" SET "name"='Bob',"age"=30,"height"=1.78,"is_active"=false,"data"='{"key":123}' WHERE "id"=2`, + }, + { + query: `DELETE FROM "my_table" WHERE "id"=$1`, + args: []interface{}{ + 4, + }, + want: `DELETE FROM "my_table" WHERE "id"=4`, + }, + { + query: `SELECT * FROM "my_table"`, + args: []interface{}{}, + want: `SELECT * FROM "my_table"`, + }, + { + query: `UPDATE "my_table" SET "name"=$1,"age"=$2,"height"=$3,"is_active"=$4,"data"=$5 WHERE "id"=$6`, + args: []interface{}{ + "Bob", 30, 1.78, false, []byte(`{"key":123}`), 2, + }, + want: `UPDATE "my_table" SET "name"='Bob',"age"=30,"height"=1.78,"is_active"=false,"data"='{"key":123}' WHERE "id"=2`, + }, + } + + for _, tt := range tests { + t.Run(tt.query, func(t *testing.T) { + got := substituteQueryArgs(tt.query, tt.args...) + + if got != tt.want { + t.Errorf("substituteQueryArgs() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/drivers/sqlboiler-mssql/driver/override/main/17_upsert.go.tpl b/drivers/sqlboiler-mssql/driver/override/main/17_upsert.go.tpl index 5665d3495..d663aaa7d 100644 --- a/drivers/sqlboiler-mssql/driver/override/main/17_upsert.go.tpl +++ b/drivers/sqlboiler-mssql/driver/override/main/17_upsert.go.tpl @@ -130,14 +130,12 @@ func (o *{{$alias.UpSingular}}) Upsert({{if .NoContext}}exec boil.Executor{{else {{if .NoContext -}} if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, cache.query) - fmt.Fprintln(boil.DebugWriter, vals) + boil.PrintQuery(boil.DebugWriter, cache.query, vals...) } {{else -}} if boil.IsDebug(ctx) { writer := boil.DebugWriterFrom(ctx) - fmt.Fprintln(writer, cache.query) - fmt.Fprintln(writer, vals) + boil.PrintQuery(writer, cache.query, vals...) } {{end -}} diff --git a/drivers/sqlboiler-mysql/driver/override/main/17_upsert.go.tpl b/drivers/sqlboiler-mysql/driver/override/main/17_upsert.go.tpl index a1e4e95a4..83a5891e2 100644 --- a/drivers/sqlboiler-mysql/driver/override/main/17_upsert.go.tpl +++ b/drivers/sqlboiler-mysql/driver/override/main/17_upsert.go.tpl @@ -138,14 +138,12 @@ func (o *{{$alias.UpSingular}}) Upsert({{if .NoContext}}exec boil.Executor{{else {{if .NoContext -}} if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, cache.query) - fmt.Fprintln(boil.DebugWriter, vals) + boil.PrintQuery(boil.DebugWriter, cache.query, vals...) } {{else -}} if boil.IsDebug(ctx) { writer := boil.DebugWriterFrom(ctx) - fmt.Fprintln(writer, cache.query) - fmt.Fprintln(writer, vals) + boil.PrintQuery(writer, cache.query, vals...) } {{end -}} @@ -200,14 +198,12 @@ func (o *{{$alias.UpSingular}}) Upsert({{if .NoContext}}exec boil.Executor{{else {{if .NoContext -}} if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, cache.retQuery) - fmt.Fprintln(boil.DebugWriter, nzUniqueCols...) + boil.PrintQuery(boil.DebugWriter, cache.retQuery, nzUniqueCols...) } {{else -}} if boil.IsDebug(ctx) { writer := boil.DebugWriterFrom(ctx) - fmt.Fprintln(writer, cache.retQuery) - fmt.Fprintln(writer, nzUniqueCols...) + boil.PrintQuery(writer, cache.retQuery, nzUniqueCols...) } {{end -}} diff --git a/drivers/sqlboiler-psql/driver/override/main/17_upsert.go.tpl b/drivers/sqlboiler-psql/driver/override/main/17_upsert.go.tpl index 41c2485f5..98f9dac53 100644 --- a/drivers/sqlboiler-psql/driver/override/main/17_upsert.go.tpl +++ b/drivers/sqlboiler-psql/driver/override/main/17_upsert.go.tpl @@ -130,14 +130,12 @@ func (o *{{$alias.UpSingular}}) Upsert({{if .NoContext}}exec boil.Executor{{else {{if .NoContext -}} if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, cache.query) - fmt.Fprintln(boil.DebugWriter, vals) + boil.PrintQuery(boil.DebugWriter, cache.query, vals...) } {{else -}} if boil.IsDebug(ctx) { writer := boil.DebugWriterFrom(ctx) - fmt.Fprintln(writer, cache.query) - fmt.Fprintln(writer, vals) + boil.PrintQuery(writer, cache.query, vals...) } {{end -}} diff --git a/drivers/sqlboiler-sqlite3/driver/override/main/17_upsert.go.tpl b/drivers/sqlboiler-sqlite3/driver/override/main/17_upsert.go.tpl index 648a061f5..2e00753ce 100644 --- a/drivers/sqlboiler-sqlite3/driver/override/main/17_upsert.go.tpl +++ b/drivers/sqlboiler-sqlite3/driver/override/main/17_upsert.go.tpl @@ -125,14 +125,12 @@ func (o *{{$alias.UpSingular}}) Upsert({{if .NoContext}}exec boil.Executor{{else {{if .NoContext -}} if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, cache.query) - fmt.Fprintln(boil.DebugWriter, vals) + boil.PrintQuery(boil.DebugWriter, cache.query, vals...) } {{else -}} if boil.IsDebug(ctx) { writer := boil.DebugWriterFrom(ctx) - fmt.Fprintln(writer, cache.query) - fmt.Fprintln(writer, vals) + boil.PrintQuery(writer, cache.query, vals...) } {{end -}} diff --git a/queries/query.go b/queries/query.go index ea8052ec8..26ecc0e1d 100644 --- a/queries/query.go +++ b/queries/query.go @@ -3,7 +3,6 @@ package queries import ( "context" "database/sql" - "fmt" "regexp" "github.com/volatiletech/sqlboiler/v4/boil" @@ -118,8 +117,7 @@ func RawG(query string, args ...interface{}) *Query { func (q *Query) Exec(exec boil.Executor) (sql.Result, error) { qs, args := BuildQuery(q) if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, qs) - fmt.Fprintln(boil.DebugWriter, args) + boil.PrintQuery(boil.DebugWriter, qs, args...) } return exec.Exec(qs, args...) } @@ -128,8 +126,7 @@ func (q *Query) Exec(exec boil.Executor) (sql.Result, error) { func (q *Query) QueryRow(exec boil.Executor) *sql.Row { qs, args := BuildQuery(q) if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, qs) - fmt.Fprintln(boil.DebugWriter, args) + boil.PrintQuery(boil.DebugWriter, qs, args...) } return exec.QueryRow(qs, args...) } @@ -138,8 +135,7 @@ func (q *Query) QueryRow(exec boil.Executor) *sql.Row { func (q *Query) Query(exec boil.Executor) (*sql.Rows, error) { qs, args := BuildQuery(q) if boil.DebugMode { - fmt.Fprintln(boil.DebugWriter, qs) - fmt.Fprintln(boil.DebugWriter, args) + boil.PrintQuery(boil.DebugWriter, qs, args...) } return exec.Query(qs, args...) } @@ -149,8 +145,7 @@ func (q *Query) ExecContext(ctx context.Context, exec boil.ContextExecutor) (sql qs, args := BuildQuery(q) if boil.IsDebug(ctx) { writer := boil.DebugWriterFrom(ctx) - fmt.Fprintln(writer, qs) - fmt.Fprintln(writer, args) + boil.PrintQuery(writer, qs, args...) } return exec.ExecContext(ctx, qs, args...) } @@ -160,8 +155,7 @@ func (q *Query) QueryRowContext(ctx context.Context, exec boil.ContextExecutor) qs, args := BuildQuery(q) if boil.IsDebug(ctx) { writer := boil.DebugWriterFrom(ctx) - fmt.Fprintln(writer, qs) - fmt.Fprintln(writer, args) + boil.PrintQuery(writer, qs, args...) } return exec.QueryRowContext(ctx, qs, args...) } @@ -171,8 +165,7 @@ func (q *Query) QueryContext(ctx context.Context, exec boil.ContextExecutor) (*s qs, args := BuildQuery(q) if boil.IsDebug(ctx) { writer := boil.DebugWriterFrom(ctx) - fmt.Fprintln(writer, qs) - fmt.Fprintln(writer, args) + boil.PrintQuery(writer, qs, args...) } return exec.QueryContext(ctx, qs, args...) } From fd6a4c86ee491ee5750749a209f1fb20a6002db5 Mon Sep 17 00:00:00 2001 From: Cyn <39891200+cynsupercat@users.noreply.github.com> Date: Mon, 10 Apr 2023 13:37:18 +1000 Subject: [PATCH 2/3] Updated func comment (remove extraneous //) --- boil/debug.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/boil/debug.go b/boil/debug.go index 5be6c90d8..d4b337e83 100644 --- a/boil/debug.go +++ b/boil/debug.go @@ -58,9 +58,9 @@ func PrintQuery(writer io.Writer, query string, args ...interface{}) { fmt.Fprintln(writer, substitutedQuery) } -// substituteQueryArgs takes a SQL query string and an array of -// // arguments. It returns a modified query string with placeholders replaced by their -// // corresponding argument values. +// substituteQueryArgs takes a query string and an array of arguments. +// It returns a modified query string with placeholders replaced by their +// corresponding argument values. func substituteQueryArgs(query string, args ...interface{}) string { // find all occurrences of placeholders ($1, $2, etc.) in the query re := regexp.MustCompile(`\$\d+`) From 8f3b938991c3f2501a97792a5e6e6bc2db86aac7 Mon Sep 17 00:00:00 2001 From: Cyn <39891200+cynsupercat@users.noreply.github.com> Date: Mon, 10 Apr 2023 13:46:59 +1000 Subject: [PATCH 3/3] Updated test to remove redundant test cases --- boil/debug_test.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/boil/debug_test.go b/boil/debug_test.go index a91d92956..1b0f16ac8 100644 --- a/boil/debug_test.go +++ b/boil/debug_test.go @@ -17,20 +17,6 @@ func TestSubstituteQueryArgs(t *testing.T) { }, want: `INSERT INTO "my_table" ("id","name","age","height","is_active","data") VALUES (1,'Alice',25,1.68,true,'{"key":"value"}')`, }, - { - query: `UPDATE "my_table" SET "name"=$1,"age"=$2,"height"=$3,"is_active"=$4,"data"=$5 WHERE "id"=$6`, - args: []interface{}{ - "Bob", 30, 1.78, false, []byte(`{"key":123}`), 2, - }, - want: `UPDATE "my_table" SET "name"='Bob',"age"=30,"height"=1.78,"is_active"=false,"data"='{"key":123}' WHERE "id"=2`, - }, - { - query: `DELETE FROM "my_table" WHERE "id"=$1`, - args: []interface{}{ - 4, - }, - want: `DELETE FROM "my_table" WHERE "id"=4`, - }, { query: `SELECT * FROM "my_table"`, args: []interface{}{},