Skip to content

Commit d9ffa86

Browse files
committed
Support for quoted identifiers.
1 parent 7fc99ac commit d9ffa86

27 files changed

+268671
-318
lines changed

.gitattributes

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
*.sql linguist-detectable=false
3+
*.json linguist-detectable=false

generator/postgres-metadata/schema_info.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ func getTableInfos(db *sql.DB, dbName, schemaName string) ([]metadata.MetaData,
3838
query := `
3939
SELECT table_name
4040
FROM information_schema.tables
41-
where table_catalog = $1 and table_schema = $2 and table_type = 'BASE TABLE';`
41+
where table_catalog = $1 and table_schema = $2 and table_type = 'BASE TABLE';
42+
`
4243

4344
rows, err := db.Query(query, dbName, schemaName)
4445

sqlbuilder/bool_expression_test.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,41 @@ import (
66

77
func TestBoolExpressionEQ(t *testing.T) {
88
assertClauseSerializeErr(t, table1ColBool.EQ(nil), "nil rhs")
9-
assertClauseSerialize(t, table1ColBool.EQ(table2ColBool), "(table1.colBool = table2.colBool)")
10-
assertClauseSerialize(t, table1ColBool.EQ(Bool(true)), "(table1.colBool = $1)", true)
9+
assertClauseSerialize(t, table1ColBool.EQ(table2ColBool), "(table1.col_bool = table2.col_bool)")
10+
assertClauseSerialize(t, table1ColBool.EQ(Bool(true)), "(table1.col_bool = $1)", true)
1111
}
1212

1313
func TestBoolExpressionNOT_EQ(t *testing.T) {
14-
assertClauseSerialize(t, table1ColBool.NOT_EQ(table2ColBool), "(table1.colBool != table2.colBool)")
15-
assertClauseSerialize(t, table1ColBool.NOT_EQ(Bool(true)), "(table1.colBool != $1)", true)
14+
assertClauseSerialize(t, table1ColBool.NOT_EQ(table2ColBool), "(table1.col_bool != table2.col_bool)")
15+
assertClauseSerialize(t, table1ColBool.NOT_EQ(Bool(true)), "(table1.col_bool != $1)", true)
1616
}
1717

1818
func TestBoolExpressionIS_TRUE(t *testing.T) {
19-
assertClauseSerialize(t, table1ColBool.IS_TRUE(), "table1.colBool IS TRUE")
19+
assertClauseSerialize(t, table1ColBool.IS_TRUE(), "table1.col_bool IS TRUE")
2020
assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE(),
21-
`($1 = table1.colInt) IS TRUE`, int64(2))
21+
`($1 = table1.col_int) IS TRUE`, int64(2))
2222
assertClauseSerialize(t, (Int(2).EQ(table1ColInt)).IS_TRUE().AND(Int(4).EQ(table2ColInt)),
23-
`(($1 = table1.colInt) IS TRUE AND ($2 = table2.colInt))`, int64(2), int64(4))
23+
`(($1 = table1.col_int) IS TRUE AND ($2 = table2.col_int))`, int64(2), int64(4))
2424
}
2525

2626
func TestBoolExpressionIS_NOT_TRUE(t *testing.T) {
27-
assertClauseSerialize(t, table1ColBool.IS_NOT_TRUE(), "table1.colBool IS NOT TRUE")
27+
assertClauseSerialize(t, table1ColBool.IS_NOT_TRUE(), "table1.col_bool IS NOT TRUE")
2828
}
2929

3030
func TestBoolExpressionIS_FALSE(t *testing.T) {
31-
assertClauseSerialize(t, table1ColBool.IS_FALSE(), "table1.colBool IS FALSE")
31+
assertClauseSerialize(t, table1ColBool.IS_FALSE(), "table1.col_bool IS FALSE")
3232
}
3333

3434
func TestBoolExpressionIS_NOT_FALSE(t *testing.T) {
35-
assertClauseSerialize(t, table1ColBool.IS_NOT_FALSE(), "table1.colBool IS NOT FALSE")
35+
assertClauseSerialize(t, table1ColBool.IS_NOT_FALSE(), "table1.col_bool IS NOT FALSE")
3636
}
3737

3838
func TestBoolExpressionIS_UNKNOWN(t *testing.T) {
39-
assertClauseSerialize(t, table1ColBool.IS_UNKNOWN(), "table1.colBool IS UNKNOWN")
39+
assertClauseSerialize(t, table1ColBool.IS_UNKNOWN(), "table1.col_bool IS UNKNOWN")
4040
}
4141

4242
func TestBoolExpressionIS_NOT_UNKNOWN(t *testing.T) {
43-
assertClauseSerialize(t, table1ColBool.IS_NOT_UNKNOWN(), "table1.colBool IS NOT UNKNOWN")
43+
assertClauseSerialize(t, table1ColBool.IS_NOT_UNKNOWN(), "table1.col_bool IS NOT UNKNOWN")
4444
}
4545

4646
func TestBinaryBoolExpression(t *testing.T) {

sqlbuilder/clause.go

+10
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,16 @@ func (q *queryData) writeString(str string) {
154154
q.write([]byte(str))
155155
}
156156

157+
func (q *queryData) writeIdentifier(name string) {
158+
quoteWrap := name != strings.ToLower(name) || strings.Contains(name, ".")
159+
160+
if quoteWrap {
161+
q.writeString(`"` + name + `"`)
162+
} else {
163+
q.writeString(name)
164+
}
165+
}
166+
157167
func (q *queryData) writeByte(b byte) {
158168
q.write([]byte{b})
159169
}

sqlbuilder/column.go

+4-29
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22

33
package sqlbuilder
44

5-
import (
6-
"strings"
7-
)
8-
95
type column interface {
106
Name() string
117
TableName() string
@@ -60,15 +56,7 @@ func (c *columnImpl) defaultAlias() string {
6056
func (c *columnImpl) serializeForOrderBy(statement statementType, out *queryData) error {
6157
if statement == set_statement {
6258
// set Statement (UNION, EXCEPT ...) can reference only select projections in order by clause
63-
columnRef := ""
64-
65-
if c.tableName != "" {
66-
columnRef += c.tableName + "."
67-
}
68-
69-
columnRef += c.name
70-
71-
out.writeString(`"` + columnRef + `"`)
59+
out.writeString(`"` + c.defaultAlias() + `"`) //always quote
7260

7361
return nil
7462
}
@@ -90,25 +78,12 @@ func (c columnImpl) serializeForProjection(statement statementType, out *queryDa
9078

9179
func (c columnImpl) serialize(statement statementType, out *queryData, options ...serializeOption) error {
9280

93-
columnRef := ""
94-
9581
if c.tableName != "" {
96-
columnRef += c.tableName + "."
97-
}
98-
99-
wrapColumnName := strings.Contains(c.name, ".")
100-
101-
if wrapColumnName {
102-
columnRef += `"`
103-
}
104-
105-
columnRef += c.name
106-
107-
if wrapColumnName {
108-
columnRef += `"`
82+
out.writeIdentifier(c.tableName)
83+
out.writeByte('.')
10984
}
11085

111-
out.writeString(columnRef)
86+
out.writeIdentifier(c.name)
11287

11388
return nil
11489
}

sqlbuilder/column_types_test.go

+20-20
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,38 @@ var subQuery = table1.SELECT(table1ColFloat, table1ColInt).AsTable("sub_query")
88

99
func TestNewBoolColumn(t *testing.T) {
1010
boolColumn := BoolColumn("colBool").From(subQuery)
11-
assertClauseSerialize(t, boolColumn, "sub_query.colBool")
12-
assertClauseSerialize(t, boolColumn.EQ(Bool(true)), "(sub_query.colBool = $1)", true)
13-
assertProjectionSerialize(t, boolColumn, `sub_query.colBool AS "sub_query.colBool"`)
11+
assertClauseSerialize(t, boolColumn, `sub_query."colBool"`)
12+
assertClauseSerialize(t, boolColumn.EQ(Bool(true)), `(sub_query."colBool" = $1)`, true)
13+
assertProjectionSerialize(t, boolColumn, `sub_query."colBool" AS "sub_query.colBool"`)
1414

1515
boolColumn2 := table1ColBool.From(subQuery)
16-
assertClauseSerialize(t, boolColumn2, `sub_query."table1.colBool"`)
17-
assertClauseSerialize(t, boolColumn2.EQ(Bool(true)), `(sub_query."table1.colBool" = $1)`, true)
18-
assertProjectionSerialize(t, boolColumn2, `sub_query."table1.colBool" AS "sub_query.table1.colBool"`)
16+
assertClauseSerialize(t, boolColumn2, `sub_query."table1.col_bool"`)
17+
assertClauseSerialize(t, boolColumn2.EQ(Bool(true)), `(sub_query."table1.col_bool" = $1)`, true)
18+
assertProjectionSerialize(t, boolColumn2, `sub_query."table1.col_bool" AS "sub_query.table1.col_bool"`)
1919
}
2020

2121
func TestNewIntColumn(t *testing.T) {
22-
intColumn := IntegerColumn("colInt").From(subQuery)
23-
assertClauseSerialize(t, intColumn, "sub_query.colInt")
24-
assertClauseSerialize(t, intColumn.EQ(Int(12)), "(sub_query.colInt = $1)", int64(12))
25-
assertProjectionSerialize(t, intColumn, `sub_query.colInt AS "sub_query.colInt"`)
22+
intColumn := IntegerColumn("col_int").From(subQuery)
23+
assertClauseSerialize(t, intColumn, "sub_query.col_int")
24+
assertClauseSerialize(t, intColumn.EQ(Int(12)), "(sub_query.col_int = $1)", int64(12))
25+
assertProjectionSerialize(t, intColumn, `sub_query.col_int AS "sub_query.col_int"`)
2626

2727
intColumn2 := table1ColInt.From(subQuery)
28-
assertClauseSerialize(t, intColumn2, `sub_query."table1.colInt"`)
29-
assertClauseSerialize(t, intColumn2.EQ(Int(14)), `(sub_query."table1.colInt" = $1)`, int64(14))
30-
assertProjectionSerialize(t, intColumn2, `sub_query."table1.colInt" AS "sub_query.table1.colInt"`)
28+
assertClauseSerialize(t, intColumn2, `sub_query."table1.col_int"`)
29+
assertClauseSerialize(t, intColumn2.EQ(Int(14)), `(sub_query."table1.col_int" = $1)`, int64(14))
30+
assertProjectionSerialize(t, intColumn2, `sub_query."table1.col_int" AS "sub_query.table1.col_int"`)
3131

3232
}
3333

3434
func TestNewFloatColumnColumn(t *testing.T) {
35-
floatColumn := FloatColumn("colFloat").From(subQuery)
36-
assertClauseSerialize(t, floatColumn, "sub_query.colFloat")
37-
assertClauseSerialize(t, floatColumn.EQ(Float(1.11)), "(sub_query.colFloat = $1)", float64(1.11))
38-
assertProjectionSerialize(t, floatColumn, `sub_query.colFloat AS "sub_query.colFloat"`)
35+
floatColumn := FloatColumn("col_float").From(subQuery)
36+
assertClauseSerialize(t, floatColumn, "sub_query.col_float")
37+
assertClauseSerialize(t, floatColumn.EQ(Float(1.11)), "(sub_query.col_float = $1)", float64(1.11))
38+
assertProjectionSerialize(t, floatColumn, `sub_query.col_float AS "sub_query.col_float"`)
3939

4040
floatColumn2 := table1ColFloat.From(subQuery)
41-
assertClauseSerialize(t, floatColumn2, `sub_query."table1.colFloat"`)
42-
assertClauseSerialize(t, floatColumn2.EQ(Float(2.22)), `(sub_query."table1.colFloat" = $1)`, float64(2.22))
43-
assertProjectionSerialize(t, floatColumn2, `sub_query."table1.colFloat" AS "sub_query.table1.colFloat"`)
41+
assertClauseSerialize(t, floatColumn2, `sub_query."table1.col_float"`)
42+
assertClauseSerialize(t, floatColumn2.EQ(Float(2.22)), `(sub_query."table1.col_float" = $1)`, float64(2.22))
43+
assertProjectionSerialize(t, floatColumn2, `sub_query."table1.col_float" AS "sub_query.table1.col_float"`)
4444

4545
}

0 commit comments

Comments
 (0)