-
Notifications
You must be signed in to change notification settings - Fork 22
/
dialect.go
95 lines (82 loc) · 3.61 KB
/
dialect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package schema
import (
"database/sql"
"strings"
)
type dialect interface {
escapeIdent(ident string) string
ColumnTypes(db *sql.DB, schema, name string) ([]*sql.ColumnType, error)
PrimaryKey(db *sql.DB, schema, name string) ([]string, error)
TableNames(db *sql.DB) ([][2]string, error)
ViewNames(db *sql.DB) ([][2]string, error)
}
// driverDialect is a registry, mapping database/sql driver names to database dialects.
// This is somewhat fragile.
var driverDialect = map[string]dialect{
"*sqlite3.SQLiteDriver": sqliteDialect{}, // github.com/mattn/go-sqlite3
"*sqlite.impl": sqliteDialect{}, // github.com/gwenn/gosqlite
"sqlite3.Driver": sqliteDialect{}, // github.com/mxk/go-sqlite
"*pq.Driver": postgresDialect{}, // github.com/lib/pq
"*stdlib.Driver": postgresDialect{}, // github.com/jackc/pgx
"*pgsqldriver.postgresDriver": postgresDialect{}, // github.com/jbarham/gopgsqldriver
"*gosnowflake.SnowflakeDriver": postgresDialect{}, // github.com/snowflakedb/gosnowflake
"*mysql.MySQLDriver": mysqlDialect{}, // github.com/go-sql-driver/mysql
"*godrv.Driver": mysqlDialect{}, // github.com/ziutek/mymysql
"vitessdriver.drv": mysqlDialect{}, // github.com/vitessio/vitess
"*mssql.Driver": mssqlDialect{}, // github.com/denisenkom/go-mssqldb
"*mssql.MssqlDriver": mssqlDialect{}, // github.com/denisenkom/go-mssqldb
"*freetds.MssqlDriver": mssqlDialect{}, // github.com/minus5/gofreetds
"*goracle.drv": oracleDialect{}, // gopkg.in/goracle.v2
"*godror.drv": oracleDialect{}, // github.com/godror/godror
"*ora.Drv": oracleDialect{}, // gopkg.in/rana/ora.v4
"*oci8.OCI8DriverStruct": oracleDialect{}, // github.com/mattn/go-oci8
"*oci8.OCI8Driver": oracleDialect{}, // github.com/mattn/go-oci8
}
// TODO Should we expose a method of registering a driver string/dialect in our registry?
// -- It would allow folk to work around the fragility. e.g.
//
// func Register(driver sql.Driver, d *Dialect) {}
//
// // pack a string, normalising its whitespace.
// func pack(s string) string {
// return strings.Join(strings.Fields(s), " ")
// }
// escapeWithDoubleQuotes implements double-quote escaping of a string,
// in accordance with SQL:1999 standard.
func escapeWithDoubleQuotes(s string) string {
return escape(s, '"', '"')
}
// escapeWithBackticks implements backtick escaping of a string.
func escapeWithBackticks(s string) string {
return escape(s, '`', '`')
}
// escapeWithBrackets implements bracket escaping of a string.
func escapeWithBrackets(s string) string {
return escape(s, '[', ']')
}
// escapeWithBraces implements brace escaping of a string.
func escapeWithBraces(s string) string {
return escape(s, '{', '}')
}
// escape escapes a string identifier.
func escape(s string, escBegin, escEnd byte) string {
// It would be nice to know when not to escape,
// but a regex (e.g. "^[a-zA-Z_][a-zA-Z0-9_#@$]*$")
// doesn't solve this, because it would not catch keywords.
// Which is why we simply always escape identifiers.
// TODO(js) Correct handling of backslash escaping of identifiers needs
// further investigation: different dialects look to handle it differently
// - removed for now.
// Please file an issue if you encounter a problem regarding backslash escaping.
var b strings.Builder
b.WriteByte(escBegin)
for i := 0; i < len(s); i++ {
c := s[i]
b.WriteByte(c)
if c == escEnd { // || c == '\\' {
b.WriteByte(c)
}
}
b.WriteByte(escEnd)
return b.String()
}