Skip to content

Commit d12008c

Browse files
committed
Making the Dollar placeholder format default.
1 parent b47d367 commit d12008c

13 files changed

+105
-172
lines changed

case_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func TestCaseWithVal(t *testing.T) {
2323
expectedSQL := "SELECT CASE number " +
2424
"WHEN 1 THEN one " +
2525
"WHEN 2 THEN two " +
26-
"ELSE ? " +
26+
"ELSE $1 " +
2727
"END " +
2828
"FROM table"
2929
assert.Equal(t, expectedSQL, sql)
@@ -44,7 +44,7 @@ func TestCaseWithComplexVal(t *testing.T) {
4444

4545
assert.NoError(t, err)
4646

47-
expectedSQL := "SELECT (CASE ? > ? " +
47+
expectedSQL := "SELECT (CASE $1 > $2 " +
4848
"WHEN true THEN 'T' " +
4949
"END) AS complexCase " +
5050
"FROM table"
@@ -66,8 +66,8 @@ func TestCaseWithNoVal(t *testing.T) {
6666
assert.NoError(t, err)
6767

6868
expectedSQL := "SELECT CASE " +
69-
"WHEN x = ? THEN x is zero " +
70-
"WHEN x > ? THEN CONCAT('x is greater than ', ?) " +
69+
"WHEN x = $1 THEN x is zero " +
70+
"WHEN x > $2 THEN CONCAT('x is greater than ', $3) " +
7171
"END " +
7272
"FROM table"
7373

@@ -88,8 +88,8 @@ func TestCaseWithExpr(t *testing.T) {
8888

8989
assert.NoError(t, err)
9090

91-
expectedSQL := "SELECT CASE x = ? " +
92-
"WHEN true THEN ? " +
91+
expectedSQL := "SELECT CASE x = $1 " +
92+
"WHEN true THEN $2 " +
9393
"ELSE 42 " +
9494
"END " +
9595
"FROM table"
@@ -119,8 +119,8 @@ func TestMultipleCase(t *testing.T) {
119119
assert.NoError(t, err)
120120

121121
expectedSQL := "SELECT " +
122-
"(CASE x = ? WHEN true THEN ? ELSE 42 END) AS case_noval, " +
123-
"(CASE WHEN x = ? THEN 'x is zero' WHEN x > ? THEN CONCAT('x is greater than ', ?) END) AS case_expr " +
122+
"(CASE x = $1 WHEN true THEN $2 ELSE 42 END) AS case_noval, " +
123+
"(CASE WHEN x = $3 THEN 'x is zero' WHEN x > $4 THEN CONCAT('x is greater than ', $5) END) AS case_expr " +
124124
"FROM table"
125125

126126
assert.Equal(t, expectedSQL, sql)

delete.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,6 @@ func init() {
8383
builder.Register(DeleteBuilder{}, deleteData{})
8484
}
8585

86-
// Format methods
87-
88-
// PlaceholderFormat sets PlaceholderFormat (e.g. Question or Dollar) for the
89-
// query.
90-
func (b DeleteBuilder) PlaceholderFormat(f PlaceholderFormat) DeleteBuilder {
91-
return builder.Set(b, "PlaceholderFormat", f).(DeleteBuilder)
92-
}
93-
9486
// SQL methods
9587

9688
// SQL builds the query into a SQL string and bound args.
@@ -155,3 +147,11 @@ func (b DeleteBuilder) Suffix(sql string, args ...any) DeleteBuilder {
155147
func (b DeleteBuilder) SuffixExpr(expr SQLizer) DeleteBuilder {
156148
return builder.Append(b, "Suffixes", expr).(DeleteBuilder)
157149
}
150+
151+
// Format methods
152+
153+
// PlaceholderFormat sets PlaceholderFormat (e.g. Question or Dollar) for the
154+
// query.
155+
func (b DeleteBuilder) PlaceholderFormat(f PlaceholderFormat) DeleteBuilder {
156+
return builder.Set(b, "PlaceholderFormat", f).(DeleteBuilder)
157+
}

delete_test.go

+4-7
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ func TestDeleteBuilderSQL(t *testing.T) {
2121
assert.NoError(t, err)
2222

2323
expectedSQL :=
24-
"WITH prefix AS ? " +
25-
"DELETE FROM a WHERE b = ? ORDER BY c LIMIT 2 OFFSET 3 " +
26-
"RETURNING ?"
24+
"WITH prefix AS $1 " +
25+
"DELETE FROM a WHERE b = $2 ORDER BY c LIMIT 2 OFFSET 3 " +
26+
"RETURNING $3"
2727
assert.Equal(t, expectedSQL, sql)
2828

2929
expectedArgs := []any{0, 1, 4}
@@ -50,10 +50,7 @@ func TestDeleteBuilderPlaceholders(t *testing.T) {
5050
t.Parallel()
5151
b := Delete("test").Where("x = ? AND y = ?", 1, 2)
5252

53-
sql, _, _ := b.PlaceholderFormat(Question).SQL()
54-
assert.Equal(t, "DELETE FROM test WHERE x = ? AND y = ?", sql)
55-
56-
sql, _, _ = b.PlaceholderFormat(Dollar).SQL()
53+
sql, _, _ := b.PlaceholderFormat(Dollar).SQL()
5754
assert.Equal(t, "DELETE FROM test WHERE x = $1 AND y = $2", sql)
5855
}
5956

insert.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,6 @@ func init() {
143143
builder.Register(InsertBuilder{}, insertData{})
144144
}
145145

146-
// Format methods
147-
148-
// PlaceholderFormat sets PlaceholderFormat (e.g. Question or Dollar) for the
149-
// query.
150-
func (b InsertBuilder) PlaceholderFormat(f PlaceholderFormat) InsertBuilder {
151-
return builder.Set(b, "PlaceholderFormat", f).(InsertBuilder)
152-
}
153-
154146
// SQL methods
155147

156148
// SQL builds the query into a SQL string and bound args.
@@ -239,3 +231,11 @@ func (b InsertBuilder) Select(sb SelectBuilder) InsertBuilder {
239231
func (b InsertBuilder) statementKeyword(keyword string) InsertBuilder {
240232
return builder.Set(b, "StatementKeyword", keyword).(InsertBuilder)
241233
}
234+
235+
// Format methods
236+
237+
// PlaceholderFormat sets PlaceholderFormat (e.g. Question or Dollar) for the
238+
// query.
239+
func (b InsertBuilder) PlaceholderFormat(f PlaceholderFormat) InsertBuilder {
240+
return builder.Set(b, "PlaceholderFormat", f).(InsertBuilder)
241+
}

insert_test.go

+8-11
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ func TestInsertBuilderSQL(t *testing.T) {
2121
assert.NoError(t, err)
2222

2323
expectedSQL :=
24-
"WITH prefix AS ? " +
25-
"INSERT DELAYED IGNORE INTO a (b,c) VALUES (?,?),(?,? + 1) " +
26-
"RETURNING ?"
24+
"WITH prefix AS $1 " +
25+
"INSERT DELAYED IGNORE INTO a (b,c) VALUES ($2,$3),($4,$5 + 1) " +
26+
"RETURNING $6"
2727
assert.Equal(t, expectedSQL, sql)
2828

2929
expectedArgs := []any{0, 1, 2, 3, 4, 5}
@@ -53,18 +53,15 @@ func TestInsertBuilderPlaceholders(t *testing.T) {
5353
t.Parallel()
5454
b := Insert("test").Values(1, 2)
5555

56-
sql, _, _ := b.PlaceholderFormat(Question).SQL()
57-
assert.Equal(t, "INSERT INTO test VALUES (?,?)", sql)
58-
59-
sql, _, _ = b.PlaceholderFormat(Dollar).SQL()
56+
sql, _, _ := b.PlaceholderFormat(Dollar).SQL()
6057
assert.Equal(t, "INSERT INTO test VALUES ($1,$2)", sql)
6158
}
6259

6360
func TestInsertBuilderRunners(t *testing.T) {
6461
t.Parallel()
6562
b := Insert("test").Values(1)
6663

67-
expectedSQL := "INSERT INTO test VALUES (?)"
64+
expectedSQL := "INSERT INTO test VALUES ($1)"
6865

6966
got, args := b.MustSQL()
7067
assert.Equal(t, expectedSQL, got)
@@ -78,7 +75,7 @@ func TestInsertBuilderSetMap(t *testing.T) {
7875
sql, args, err := b.SQL()
7976
assert.NoError(t, err)
8077

81-
expectedSQL := "INSERT INTO table (field1,field2,field3) VALUES (?,?,?)"
78+
expectedSQL := "INSERT INTO table (field1,field2,field3) VALUES ($1,$2,$3)"
8279
assert.Equal(t, expectedSQL, sql)
8380

8481
expectedArgs := []any{1, 2, 3}
@@ -93,7 +90,7 @@ func TestInsertBuilderSelect(t *testing.T) {
9390
sql, args, err := ib.SQL()
9491
assert.NoError(t, err)
9592

96-
expectedSQL := "INSERT INTO table2 (field1) SELECT field1 FROM table1 WHERE field1 = ?"
93+
expectedSQL := "INSERT INTO table2 (field1) SELECT field1 FROM table1 WHERE field1 = $1"
9794
assert.Equal(t, expectedSQL, sql)
9895

9996
expectedArgs := []any{1}
@@ -104,7 +101,7 @@ func TestInsertBuilderReplace(t *testing.T) {
104101
t.Parallel()
105102
b := Replace("table").Values(1)
106103

107-
expectedSQL := "REPLACE INTO table VALUES (?)"
104+
expectedSQL := "REPLACE INTO table VALUES ($1)"
108105

109106
sql, _, err := b.SQL()
110107
assert.NoError(t, err)

pgq_test.go

+29-81
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,44 @@
11
package pgq
22

33
import (
4-
"strings"
54
"testing"
6-
7-
"github.com/stretchr/testify/assert"
85
)
96

10-
var sqlizer = Select("test")
11-
var sqlStr = "SELECT test"
12-
13-
var testDebugUpdateSQL = Update("table").SetMap(Eq{"x": 1, "y": "val"})
14-
var expectedDebugUpateSQL = "UPDATE table SET x = '1', y = 'val'"
15-
16-
func TestDebugSQLizerUpdateDollar(t *testing.T) {
17-
t.Parallel()
18-
testDebugUpdateSQL.PlaceholderFormat(Dollar)
19-
assert.Equal(t, expectedDebugUpateSQL, Debug(testDebugUpdateSQL))
20-
}
21-
22-
func TestDebugSQLizerUpdateQuestion(t *testing.T) {
23-
t.Parallel()
24-
testDebugUpdateSQL.PlaceholderFormat(Question)
25-
assert.Equal(t, expectedDebugUpateSQL, Debug(testDebugUpdateSQL))
26-
}
27-
28-
var testDebugDeleteSQL = Delete("table").Where(And{
29-
Eq{"column": "val"},
30-
Eq{"other": 1},
31-
})
32-
var expectedDebugDeleteSQL = "DELETE FROM table WHERE (column = 'val' AND other = '1')"
33-
34-
func TestDebugSQLizerDeleteDollar(t *testing.T) {
35-
t.Parallel()
36-
testDebugDeleteSQL.PlaceholderFormat(Dollar)
37-
assert.Equal(t, expectedDebugDeleteSQL, Debug(testDebugDeleteSQL))
38-
}
39-
40-
func TestDebugSQLizerDeleteQuestion(t *testing.T) {
41-
t.Parallel()
42-
testDebugDeleteSQL.PlaceholderFormat(Question)
43-
assert.Equal(t, expectedDebugDeleteSQL, Debug(testDebugDeleteSQL))
44-
}
45-
46-
var testDebugInsertSQL = Insert("table").Values(1, "test")
47-
var expectedDebugInsertSQL = "INSERT INTO table VALUES ('1','test')"
48-
49-
func TestDebugSQLizerInsertDollar(t *testing.T) {
50-
t.Parallel()
51-
testDebugInsertSQL.PlaceholderFormat(Dollar)
52-
assert.Equal(t, expectedDebugInsertSQL, Debug(testDebugInsertSQL))
53-
}
54-
55-
func TestDebugSQLizerInsertQuestion(t *testing.T) {
56-
t.Parallel()
57-
testDebugInsertSQL.PlaceholderFormat(Question)
58-
assert.Equal(t, expectedDebugInsertSQL, Debug(testDebugInsertSQL))
59-
}
60-
61-
var testDebugSelectSQL = Select("*").From("table").Where(And{
62-
Eq{"column": "val"},
63-
Eq{"other": 1},
64-
})
65-
var expectedDebugSelectSQL = "SELECT * FROM table WHERE (column = 'val' AND other = '1')"
66-
67-
func TestDebugSQLizerSelectDollar(t *testing.T) {
68-
t.Parallel()
69-
testDebugSelectSQL.PlaceholderFormat(Dollar)
70-
assert.Equal(t, expectedDebugSelectSQL, Debug(testDebugSelectSQL))
71-
}
72-
73-
func TestDebugSQLizerSelectQuestion(t *testing.T) {
74-
t.Parallel()
75-
testDebugSelectSQL.PlaceholderFormat(Question)
76-
assert.Equal(t, expectedDebugSelectSQL, Debug(testDebugSelectSQL))
77-
}
78-
797
func TestDebug(t *testing.T) {
808
t.Parallel()
819
sqlizer := Expr("x = ? AND y = ? AND z = '??'", 1, "text")
8210
expectedDebug := "x = '1' AND y = 'text' AND z = '?'"
83-
assert.Equal(t, expectedDebug, Debug(sqlizer))
11+
if got := Debug(sqlizer); got != expectedDebug {
12+
t.Errorf("expected %q, got %q instead", got, expectedDebug)
13+
}
8414
}
8515

8616
func TestDebugSQLizerErrors(t *testing.T) {
8717
t.Parallel()
88-
errorMsg := Debug(Expr("x = ?", 1, 2)) // Not enough placeholders
89-
assert.True(t, strings.HasPrefix(errorMsg, "[DebugSQLizer error: "))
90-
91-
errorMsg = Debug(Expr("x = ? AND y = ?", 1)) // Too many placeholders
92-
assert.True(t, strings.HasPrefix(errorMsg, "[DebugSQLizer error: "))
93-
94-
errorMsg = Debug(Lt{"x": nil}) // Cannot use nil values with Lt
95-
assert.True(t, strings.HasPrefix(errorMsg, "[SQL error: "))
18+
var errorMessages = []struct {
19+
s SQLizer
20+
want string
21+
}{
22+
// Not enough placeholders
23+
{
24+
s: Expr("x = ?", 1, 2),
25+
want: "[DebugSQLizer error: not enough placeholders in \"\" for 2 args]",
26+
},
27+
// Too many placeholders
28+
{
29+
s: Expr("x = ? AND y = ?", 1),
30+
want: "[DebugSQLizer error: too many placeholders in \" AND y = ?\" for 1 args]",
31+
},
32+
// Cannot use nil values with Lt
33+
{
34+
s: Lt{"x": nil},
35+
want: "[SQL error: cannot use null with less than or greater than operators]",
36+
},
37+
}
38+
39+
for _, m := range errorMessages {
40+
if msg := Debug(m.s); msg != m.want {
41+
t.Errorf("expected %q, got error message = %q instead", m.want, msg)
42+
}
43+
}
9644
}

placeholder_test.go

-7
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,6 @@ import (
77
"github.com/stretchr/testify/assert"
88
)
99

10-
func TestQuestion(t *testing.T) {
11-
t.Parallel()
12-
sql := "x = ? AND y = ?"
13-
s, _ := Question.ReplacePlaceholders(sql)
14-
assert.Equal(t, sql, s)
15-
}
16-
1710
func TestDollar(t *testing.T) {
1811
t.Parallel()
1912
sql := "x = ? AND y = ?"

select.go

+10-9
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,6 @@ func init() {
142142
builder.Register(SelectBuilder{}, selectData{})
143143
}
144144

145-
// Format methods
146-
147-
// PlaceholderFormat sets PlaceholderFormat (e.g. Question or Dollar) for the
148-
// query.
149-
func (b SelectBuilder) PlaceholderFormat(f PlaceholderFormat) SelectBuilder {
150-
return builder.Set(b, "PlaceholderFormat", f).(SelectBuilder)
151-
}
152-
153145
// SQL methods
154146

155147
// SQL builds the query into a SQL string and bound args.
@@ -225,7 +217,8 @@ func (b SelectBuilder) From(from string) SelectBuilder {
225217

226218
// FromSelect sets a subquery into the FROM clause of the query.
227219
func (b SelectBuilder) FromSelect(from SelectBuilder, alias string) SelectBuilder {
228-
// Prevent misnumbered parameters in nested selects (#183).
220+
// Prevent misnumbered parameters in nested selects
221+
// See https://github.com/Masterminds/squirrel/issues/183
229222
from = from.PlaceholderFormat(Question)
230223
return builder.Set(b, "From", Alias(from, alias)).(SelectBuilder)
231224
}
@@ -342,3 +335,11 @@ func (b SelectBuilder) Suffix(sql string, args ...any) SelectBuilder {
342335
func (b SelectBuilder) SuffixExpr(expr SQLizer) SelectBuilder {
343336
return builder.Append(b, "Suffixes", expr).(SelectBuilder)
344337
}
338+
339+
// Format methods
340+
341+
// PlaceholderFormat sets PlaceholderFormat (e.g. Question or Dollar) for the
342+
// query.
343+
func (b SelectBuilder) PlaceholderFormat(f PlaceholderFormat) SelectBuilder {
344+
return builder.Set(b, "PlaceholderFormat", f).(SelectBuilder)
345+
}

0 commit comments

Comments
 (0)