aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/xorm.io/xorm/dialects/dialect.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/xorm.io/xorm/dialects/dialect.go')
-rw-r--r--vendor/xorm.io/xorm/dialects/dialect.go278
1 files changed, 278 insertions, 0 deletions
diff --git a/vendor/xorm.io/xorm/dialects/dialect.go b/vendor/xorm.io/xorm/dialects/dialect.go
new file mode 100644
index 0000000000..4fdf35e94e
--- /dev/null
+++ b/vendor/xorm.io/xorm/dialects/dialect.go
@@ -0,0 +1,278 @@
+// Copyright 2019 The Xorm Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package dialects
+
+import (
+ "context"
+ "fmt"
+ "strings"
+ "time"
+
+ "xorm.io/xorm/core"
+ "xorm.io/xorm/schemas"
+)
+
+// URI represents an uri to visit database
+type URI struct {
+ DBType schemas.DBType
+ Proto string
+ Host string
+ Port string
+ DBName string
+ User string
+ Passwd string
+ Charset string
+ Laddr string
+ Raddr string
+ Timeout time.Duration
+ Schema string
+}
+
+// SetSchema set schema
+func (uri *URI) SetSchema(schema string) {
+ if uri.DBType == schemas.POSTGRES {
+ uri.Schema = schema
+ }
+}
+
+// Dialect represents a kind of database
+type Dialect interface {
+ Init(*core.DB, *URI) error
+ URI() *URI
+ DB() *core.DB
+ SQLType(*schemas.Column) string
+ FormatBytes(b []byte) string
+ DefaultSchema() string
+
+ IsReserved(string) bool
+ Quoter() schemas.Quoter
+ SetQuotePolicy(quotePolicy QuotePolicy)
+
+ AutoIncrStr() string
+
+ GetIndexes(ctx context.Context, tableName string) (map[string]*schemas.Index, error)
+ IndexCheckSQL(tableName, idxName string) (string, []interface{})
+ CreateIndexSQL(tableName string, index *schemas.Index) string
+ DropIndexSQL(tableName string, index *schemas.Index) string
+
+ GetTables(ctx context.Context) ([]*schemas.Table, error)
+ IsTableExist(ctx context.Context, tableName string) (bool, error)
+ CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool)
+ DropTableSQL(tableName string) (string, bool)
+
+ GetColumns(ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error)
+ IsColumnExist(ctx context.Context, tableName string, colName string) (bool, error)
+ AddColumnSQL(tableName string, col *schemas.Column) string
+ ModifyColumnSQL(tableName string, col *schemas.Column) string
+
+ ForUpdateSQL(query string) string
+
+ Filters() []Filter
+ SetParams(params map[string]string)
+}
+
+// Base represents a basic dialect and all real dialects could embed this struct
+type Base struct {
+ db *core.DB
+ dialect Dialect
+ uri *URI
+ quoter schemas.Quoter
+}
+
+func (b *Base) Quoter() schemas.Quoter {
+ return b.quoter
+}
+
+func (b *Base) DB() *core.DB {
+ return b.db
+}
+
+func (b *Base) DefaultSchema() string {
+ return ""
+}
+
+func (b *Base) Init(db *core.DB, dialect Dialect, uri *URI) error {
+ b.db, b.dialect, b.uri = db, dialect, uri
+ return nil
+}
+
+func (b *Base) URI() *URI {
+ return b.uri
+}
+
+func (b *Base) DBType() schemas.DBType {
+ return b.uri.DBType
+}
+
+// String generate column description string according dialect
+func (b *Base) String(col *schemas.Column) string {
+ sql := b.dialect.Quoter().Quote(col.Name) + " "
+
+ sql += b.dialect.SQLType(col) + " "
+
+ if col.IsPrimaryKey {
+ sql += "PRIMARY KEY "
+ if col.IsAutoIncrement {
+ sql += b.dialect.AutoIncrStr() + " "
+ }
+ }
+
+ if col.Default != "" {
+ sql += "DEFAULT " + col.Default + " "
+ }
+
+ if col.Nullable {
+ sql += "NULL "
+ } else {
+ sql += "NOT NULL "
+ }
+
+ return sql
+}
+
+// StringNoPk generate column description string according dialect without primary keys
+func (b *Base) StringNoPk(col *schemas.Column) string {
+ sql := b.dialect.Quoter().Quote(col.Name) + " "
+
+ sql += b.dialect.SQLType(col) + " "
+
+ if col.Default != "" {
+ sql += "DEFAULT " + col.Default + " "
+ }
+
+ if col.Nullable {
+ sql += "NULL "
+ } else {
+ sql += "NOT NULL "
+ }
+
+ return sql
+}
+
+func (b *Base) FormatBytes(bs []byte) string {
+ return fmt.Sprintf("0x%x", bs)
+}
+
+func (db *Base) DropTableSQL(tableName string) (string, bool) {
+ quote := db.dialect.Quoter().Quote
+ return fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName)), true
+}
+
+func (db *Base) HasRecords(ctx context.Context, query string, args ...interface{}) (bool, error) {
+ rows, err := db.DB().QueryContext(ctx, query, args...)
+ if err != nil {
+ return false, err
+ }
+ defer rows.Close()
+
+ if rows.Next() {
+ return true, nil
+ }
+ return false, nil
+}
+
+func (db *Base) IsColumnExist(ctx context.Context, tableName, colName string) (bool, error) {
+ quote := db.dialect.Quoter().Quote
+ query := fmt.Sprintf(
+ "SELECT %v FROM %v.%v WHERE %v = ? AND %v = ? AND %v = ?",
+ quote("COLUMN_NAME"),
+ quote("INFORMATION_SCHEMA"),
+ quote("COLUMNS"),
+ quote("TABLE_SCHEMA"),
+ quote("TABLE_NAME"),
+ quote("COLUMN_NAME"),
+ )
+ return db.HasRecords(ctx, query, db.uri.DBName, tableName, colName)
+}
+
+func (db *Base) AddColumnSQL(tableName string, col *schemas.Column) string {
+ return fmt.Sprintf("ALTER TABLE %v ADD %v", db.dialect.Quoter().Quote(tableName),
+ db.String(col))
+}
+
+func (db *Base) CreateIndexSQL(tableName string, index *schemas.Index) string {
+ quoter := db.dialect.Quoter()
+ var unique string
+ var idxName string
+ if index.Type == schemas.UniqueType {
+ unique = " UNIQUE"
+ }
+ idxName = index.XName(tableName)
+ return fmt.Sprintf("CREATE%s INDEX %v ON %v (%v)", unique,
+ quoter.Quote(idxName), quoter.Quote(tableName),
+ quoter.Join(index.Cols, ","))
+}
+
+func (db *Base) DropIndexSQL(tableName string, index *schemas.Index) string {
+ quote := db.dialect.Quoter().Quote
+ var name string
+ if index.IsRegular {
+ name = index.XName(tableName)
+ } else {
+ name = index.Name
+ }
+ return fmt.Sprintf("DROP INDEX %v ON %s", quote(name), quote(tableName))
+}
+
+func (db *Base) ModifyColumnSQL(tableName string, col *schemas.Column) string {
+ return fmt.Sprintf("alter table %s MODIFY COLUMN %s", tableName, db.StringNoPk(col))
+}
+
+func (b *Base) ForUpdateSQL(query string) string {
+ return query + " FOR UPDATE"
+}
+
+func (b *Base) SetParams(params map[string]string) {
+}
+
+var (
+ dialects = map[string]func() Dialect{}
+)
+
+// RegisterDialect register database dialect
+func RegisterDialect(dbName schemas.DBType, dialectFunc func() Dialect) {
+ if dialectFunc == nil {
+ panic("core: Register dialect is nil")
+ }
+ dialects[strings.ToLower(string(dbName))] = dialectFunc // !nashtsai! allow override dialect
+}
+
+// QueryDialect query if registered database dialect
+func QueryDialect(dbName schemas.DBType) Dialect {
+ if d, ok := dialects[strings.ToLower(string(dbName))]; ok {
+ return d()
+ }
+ return nil
+}
+
+func regDrvsNDialects() bool {
+ providedDrvsNDialects := map[string]struct {
+ dbType schemas.DBType
+ getDriver func() Driver
+ getDialect func() Dialect
+ }{
+ "mssql": {"mssql", func() Driver { return &odbcDriver{} }, func() Dialect { return &mssql{} }},
+ "odbc": {"mssql", func() Driver { return &odbcDriver{} }, func() Dialect { return &mssql{} }}, // !nashtsai! TODO change this when supporting MS Access
+ "mysql": {"mysql", func() Driver { return &mysqlDriver{} }, func() Dialect { return &mysql{} }},
+ "mymysql": {"mysql", func() Driver { return &mymysqlDriver{} }, func() Dialect { return &mysql{} }},
+ "postgres": {"postgres", func() Driver { return &pqDriver{} }, func() Dialect { return &postgres{} }},
+ "pgx": {"postgres", func() Driver { return &pqDriverPgx{} }, func() Dialect { return &postgres{} }},
+ "sqlite3": {"sqlite3", func() Driver { return &sqlite3Driver{} }, func() Dialect { return &sqlite3{} }},
+ "oci8": {"oracle", func() Driver { return &oci8Driver{} }, func() Dialect { return &oracle{} }},
+ "goracle": {"oracle", func() Driver { return &goracleDriver{} }, func() Dialect { return &oracle{} }},
+ }
+
+ for driverName, v := range providedDrvsNDialects {
+ if driver := QueryDriver(driverName); driver == nil {
+ RegisterDriver(driverName, v.getDriver())
+ RegisterDialect(v.dbType, v.getDialect)
+ }
+ }
+ return true
+}
+
+func init() {
+ regDrvsNDialects()
+}