grafana/pkg/services/sqlstore/migrator/dialect.go
Sofia Papagiannaki 8c31e25926
AlertingNG: Save alert instances (#30223)
* AlertingNG: Save alert instances

Co-authored-by: Kyle Brandt <kyle@grafana.com>

* Rename alert instance fields/columns

* Include definition title in listing alert instances

* Delete instances when deleting defintion

Co-authored-by: Kyle Brandt <kyle@grafana.com>
2021-01-18 20:57:17 +02:00

291 lines
6.8 KiB
Go

package migrator
import (
"fmt"
"strings"
"xorm.io/xorm"
)
type Dialect interface {
DriverName() string
Quote(string) string
AndStr() string
AutoIncrStr() string
OrStr() string
EqStr() string
ShowCreateNull() bool
SQLType(col *Column) string
SupportEngine() bool
LikeStr() string
Default(col *Column) string
BooleanStr(bool) string
DateTimeFunc(string) string
CreateIndexSQL(tableName string, index *Index) string
CreateTableSQL(table *Table) string
AddColumnSQL(tableName string, col *Column) string
CopyTableData(sourceTable string, targetTable string, sourceCols []string, targetCols []string) string
DropTable(tableName string) string
DropIndexSQL(tableName string, index *Index) string
RenameTable(oldName string, newName string) string
UpdateTableSQL(tableName string, columns []*Column) string
IndexCheckSQL(tableName, indexName string) (string, []interface{})
ColumnCheckSQL(tableName, columnName string) (string, []interface{})
// UpsertSQL returns the upsert sql statement for a dialect
UpsertSQL(tableName string, keyCols, updateCols []string) string
ColString(*Column) string
ColStringNoPk(*Column) string
Limit(limit int64) string
LimitOffset(limit int64, offset int64) string
PreInsertId(table string, sess *xorm.Session) error
PostInsertId(table string, sess *xorm.Session) error
CleanDB() error
TruncateDBTables() error
NoOpSQL() string
IsUniqueConstraintViolation(err error) bool
ErrorMessage(err error) string
IsDeadlock(err error) bool
}
type dialectFunc func(*xorm.Engine) Dialect
var supportedDialects = map[string]dialectFunc{
MySQL: NewMysqlDialect,
SQLite: NewSQLite3Dialect,
Postgres: NewPostgresDialect,
MySQL + "WithHooks": NewMysqlDialect,
SQLite + "WithHooks": NewSQLite3Dialect,
Postgres + "WithHooks": NewPostgresDialect,
}
func NewDialect(engine *xorm.Engine) Dialect {
name := engine.DriverName()
if fn, exist := supportedDialects[name]; exist {
return fn(engine)
}
panic("Unsupported database type: " + name)
}
type BaseDialect struct {
dialect Dialect
engine *xorm.Engine
driverName string
}
func (b *BaseDialect) DriverName() string {
return b.driverName
}
func (b *BaseDialect) ShowCreateNull() bool {
return true
}
func (b *BaseDialect) AndStr() string {
return "AND"
}
func (b *BaseDialect) LikeStr() string {
return "LIKE"
}
func (b *BaseDialect) OrStr() string {
return "OR"
}
func (b *BaseDialect) EqStr() string {
return "="
}
func (b *BaseDialect) Default(col *Column) string {
return col.Default
}
func (b *BaseDialect) DateTimeFunc(value string) string {
return value
}
func (b *BaseDialect) CreateTableSQL(table *Table) string {
sql := "CREATE TABLE IF NOT EXISTS "
sql += b.dialect.Quote(table.Name) + " (\n"
pkList := table.PrimaryKeys
for _, col := range table.Columns {
if col.IsPrimaryKey && len(pkList) == 1 {
sql += col.String(b.dialect)
} else {
sql += col.StringNoPk(b.dialect)
}
sql = strings.TrimSpace(sql)
sql += "\n, "
}
if len(pkList) > 1 {
quotedCols := []string{}
for _, col := range pkList {
quotedCols = append(quotedCols, b.dialect.Quote(col))
}
sql += "PRIMARY KEY ( " + strings.Join(quotedCols, ",") + " ), "
}
sql = sql[:len(sql)-2] + ")"
if b.dialect.SupportEngine() {
sql += " ENGINE=InnoDB DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci"
}
sql += ";"
return sql
}
func (b *BaseDialect) AddColumnSQL(tableName string, col *Column) string {
return fmt.Sprintf("alter table %s ADD COLUMN %s", b.dialect.Quote(tableName), col.StringNoPk(b.dialect))
}
func (b *BaseDialect) CreateIndexSQL(tableName string, index *Index) string {
quote := b.dialect.Quote
var unique string
if index.Type == UniqueIndex {
unique = " UNIQUE"
}
idxName := index.XName(tableName)
quotedCols := []string{}
for _, col := range index.Cols {
quotedCols = append(quotedCols, b.dialect.Quote(col))
}
return fmt.Sprintf("CREATE%s INDEX %v ON %v (%v);", unique, quote(idxName), quote(tableName), strings.Join(quotedCols, ","))
}
func (b *BaseDialect) QuoteColList(cols []string) string {
var sourceColsSQL = ""
for _, col := range cols {
sourceColsSQL += b.dialect.Quote(col)
sourceColsSQL += "\n, "
}
return strings.TrimSuffix(sourceColsSQL, "\n, ")
}
func (b *BaseDialect) CopyTableData(sourceTable string, targetTable string, sourceCols []string, targetCols []string) string {
sourceColsSQL := b.QuoteColList(sourceCols)
targetColsSQL := b.QuoteColList(targetCols)
quote := b.dialect.Quote
return fmt.Sprintf("INSERT INTO %s (%s) SELECT %s FROM %s", quote(targetTable), targetColsSQL, sourceColsSQL, quote(sourceTable))
}
func (b *BaseDialect) DropTable(tableName string) string {
quote := b.dialect.Quote
return fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName))
}
func (b *BaseDialect) RenameTable(oldName string, newName string) string {
quote := b.dialect.Quote
return fmt.Sprintf("ALTER TABLE %s RENAME TO %s", quote(oldName), quote(newName))
}
func (b *BaseDialect) ColumnCheckSQL(tableName, columnName string) (string, []interface{}) {
return "", nil
}
func (b *BaseDialect) DropIndexSQL(tableName string, index *Index) string {
quote := b.dialect.Quote
name := index.XName(tableName)
return fmt.Sprintf("DROP INDEX %v ON %s", quote(name), quote(tableName))
}
func (b *BaseDialect) UpdateTableSQL(tableName string, columns []*Column) string {
return "-- NOT REQUIRED"
}
func (b *BaseDialect) ColString(col *Column) string {
sql := b.dialect.Quote(col.Name) + " "
sql += b.dialect.SQLType(col) + " "
if col.IsPrimaryKey {
sql += "PRIMARY KEY "
if col.IsAutoIncrement {
sql += b.dialect.AutoIncrStr() + " "
}
}
if b.dialect.ShowCreateNull() {
if col.Nullable {
sql += "NULL "
} else {
sql += "NOT NULL "
}
}
if col.Default != "" {
sql += "DEFAULT " + b.dialect.Default(col) + " "
}
return sql
}
func (b *BaseDialect) ColStringNoPk(col *Column) string {
sql := b.dialect.Quote(col.Name) + " "
sql += b.dialect.SQLType(col) + " "
if b.dialect.ShowCreateNull() {
if col.Nullable {
sql += "NULL "
} else {
sql += "NOT NULL "
}
}
if col.Default != "" {
sql += "DEFAULT " + b.dialect.Default(col) + " "
}
return sql
}
func (b *BaseDialect) Limit(limit int64) string {
return fmt.Sprintf(" LIMIT %d", limit)
}
func (b *BaseDialect) LimitOffset(limit int64, offset int64) string {
return fmt.Sprintf(" LIMIT %d OFFSET %d", limit, offset)
}
func (b *BaseDialect) PreInsertId(table string, sess *xorm.Session) error {
return nil
}
func (b *BaseDialect) PostInsertId(table string, sess *xorm.Session) error {
return nil
}
func (b *BaseDialect) CleanDB() error {
return nil
}
func (b *BaseDialect) NoOpSQL() string {
return "SELECT 0;"
}
func (b *BaseDialect) TruncateDBTables() error {
return nil
}
//UpsertSQL returns empty string
func (b *BaseDialect) UpsertSQL(tableName string, keyCols, updateCols []string) string {
return ""
}