github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/go-xorm/tidb/tidb_dialect.go (about) 1 // Copyright 2015 The Xorm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package tidb 6 7 import ( 8 "errors" 9 "fmt" 10 "strconv" 11 "strings" 12 13 "github.com/insionng/yougam/libraries/go-xorm/core" 14 ) 15 16 type tidb struct { 17 core.Base 18 } 19 20 func (db *tidb) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error { 21 return db.Base.Init(d, db, uri, drivername, dataSourceName) 22 } 23 24 func (db *tidb) SqlType(c *core.Column) string { 25 var res string 26 switch t := c.SQLType.Name; t { 27 case core.Bool: 28 res = core.Bool 29 case core.Serial: 30 c.IsAutoIncrement = true 31 c.IsPrimaryKey = true 32 c.Nullable = false 33 res = core.Int 34 case core.BigSerial: 35 c.IsAutoIncrement = true 36 c.IsPrimaryKey = true 37 c.Nullable = false 38 res = core.BigInt 39 case core.Bytea: 40 res = core.Blob 41 case core.TimeStampz: 42 res = core.Char 43 c.Length = 64 44 case core.Enum: //mysql enum 45 res = core.Enum 46 res += "(" 47 opts := "" 48 for v, _ := range c.EnumOptions { 49 opts += fmt.Sprintf(",'%v'", v) 50 } 51 res += strings.TrimLeft(opts, ",") 52 res += ")" 53 case core.Set: //mysql set 54 res = core.Set 55 res += "(" 56 opts := "" 57 for v, _ := range c.SetOptions { 58 opts += fmt.Sprintf(",'%v'", v) 59 } 60 res += strings.TrimLeft(opts, ",") 61 res += ")" 62 case core.NVarchar: 63 res = core.Varchar 64 case core.Uuid: 65 res = core.Varchar 66 c.Length = 40 67 case core.Json: 68 res = core.Text 69 default: 70 res = t 71 } 72 73 var hasLen1 bool = (c.Length > 0) 74 var hasLen2 bool = (c.Length2 > 0) 75 76 if res == core.BigInt && !hasLen1 && !hasLen2 { 77 c.Length = 20 78 hasLen1 = true 79 } 80 81 if hasLen2 { 82 res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")" 83 } else if hasLen1 { 84 res += "(" + strconv.Itoa(c.Length) + ")" 85 } 86 return res 87 } 88 89 func (db *tidb) SupportInsertMany() bool { 90 return true 91 } 92 93 func (db *tidb) IsReserved(name string) bool { 94 return false 95 } 96 97 func (db *tidb) Quote(name string) string { 98 return "`" + name + "`" 99 } 100 101 func (db *tidb) QuoteStr() string { 102 return "`" 103 } 104 105 func (db *tidb) SupportEngine() bool { 106 return false 107 } 108 109 func (db *tidb) AutoIncrStr() string { 110 return "AUTO_INCREMENT" 111 } 112 113 func (db *tidb) SupportCharset() bool { 114 return false 115 } 116 117 func (db *tidb) IndexOnTable() bool { 118 return true 119 } 120 121 func (db *tidb) IndexCheckSql(tableName, idxName string) (string, []interface{}) { 122 args := []interface{}{db.DbName, tableName, idxName} 123 sql := "SELECT `INDEX_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS`" 124 sql += " WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `INDEX_NAME`=?" 125 return sql, args 126 } 127 128 func (db *tidb) TableCheckSql(tableName string) (string, []interface{}) { 129 args := []interface{}{db.DbName, tableName} 130 sql := "SELECT `TABLE_NAME` from `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? and `TABLE_NAME`=?" 131 return sql, args 132 } 133 134 func (db *tidb) GetColumns(tableName string) ([]string, map[string]*core.Column, error) { 135 args := []interface{}{db.DbName, tableName} 136 s := "SELECT `COLUMN_NAME`, `IS_NULLABLE`, `COLUMN_DEFAULT`, `COLUMN_TYPE`," + 137 " `COLUMN_KEY`, `EXTRA` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?" 138 139 rows, err := db.DB().Query(s, args...) 140 db.LogSQL(s, args) 141 142 if err != nil { 143 return nil, nil, err 144 } 145 defer rows.Close() 146 147 cols := make(map[string]*core.Column) 148 colSeq := make([]string, 0) 149 for rows.Next() { 150 col := new(core.Column) 151 col.Indexes = make(map[string]int) 152 153 var columnName, isNullable, colType, colKey, extra string 154 var colDefault *string 155 err = rows.Scan(&columnName, &isNullable, &colDefault, &colType, &colKey, &extra) 156 if err != nil { 157 return nil, nil, err 158 } 159 col.Name = strings.Trim(columnName, "` ") 160 if "YES" == isNullable { 161 col.Nullable = true 162 } 163 164 if colDefault != nil { 165 col.Default = *colDefault 166 if col.Default == "" { 167 col.DefaultIsEmpty = true 168 } 169 } 170 171 cts := strings.Split(colType, "(") 172 colName := cts[0] 173 colType = strings.ToUpper(colName) 174 var len1, len2 int 175 if len(cts) == 2 { 176 idx := strings.Index(cts[1], ")") 177 if colType == core.Enum && cts[1][0] == '\'' { //enum 178 options := strings.Split(cts[1][0:idx], ",") 179 col.EnumOptions = make(map[string]int) 180 for k, v := range options { 181 v = strings.TrimSpace(v) 182 v = strings.Trim(v, "'") 183 col.EnumOptions[v] = k 184 } 185 } else if colType == core.Set && cts[1][0] == '\'' { 186 options := strings.Split(cts[1][0:idx], ",") 187 col.SetOptions = make(map[string]int) 188 for k, v := range options { 189 v = strings.TrimSpace(v) 190 v = strings.Trim(v, "'") 191 col.SetOptions[v] = k 192 } 193 } else { 194 lens := strings.Split(cts[1][0:idx], ",") 195 len1, err = strconv.Atoi(strings.TrimSpace(lens[0])) 196 if err != nil { 197 return nil, nil, err 198 } 199 if len(lens) == 2 { 200 len2, err = strconv.Atoi(lens[1]) 201 if err != nil { 202 return nil, nil, err 203 } 204 } 205 } 206 } 207 if colType == "FLOAT UNSIGNED" { 208 colType = "FLOAT" 209 } 210 col.Length = len1 211 col.Length2 = len2 212 if _, ok := core.SqlTypes[colType]; ok { 213 col.SQLType = core.SQLType{colType, len1, len2} 214 } else { 215 return nil, nil, errors.New(fmt.Sprintf("unkonw colType %v", colType)) 216 } 217 218 if colKey == "PRI" { 219 col.IsPrimaryKey = true 220 } 221 if colKey == "UNI" { 222 //col.is 223 } 224 225 if extra == "auto_increment" { 226 col.IsAutoIncrement = true 227 } 228 229 if col.SQLType.IsText() || col.SQLType.IsTime() { 230 if col.Default != "" { 231 col.Default = "'" + col.Default + "'" 232 } else { 233 if col.DefaultIsEmpty { 234 col.Default = "''" 235 } 236 } 237 } 238 cols[col.Name] = col 239 colSeq = append(colSeq, col.Name) 240 } 241 return colSeq, cols, nil 242 } 243 244 func (db *tidb) GetTables() ([]*core.Table, error) { 245 args := []interface{}{db.DbName} 246 s := "SELECT `TABLE_NAME`, `ENGINE`, `TABLE_ROWS`, `AUTO_INCREMENT` from " + 247 "`INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? AND (`ENGINE`='MyISAM' OR `ENGINE` = 'InnoDB')" 248 249 rows, err := db.DB().Query(s, args...) 250 db.LogSQL(s, args) 251 if err != nil { 252 return nil, err 253 } 254 defer rows.Close() 255 256 tables := make([]*core.Table, 0) 257 for rows.Next() { 258 table := core.NewEmptyTable() 259 var name, engine, tableRows string 260 var autoIncr *string 261 err = rows.Scan(&name, &engine, &tableRows, &autoIncr) 262 if err != nil { 263 return nil, err 264 } 265 266 table.Name = name 267 table.StoreEngine = engine 268 tables = append(tables, table) 269 } 270 return tables, nil 271 } 272 273 func (db *tidb) GetIndexes(tableName string) (map[string]*core.Index, error) { 274 args := []interface{}{db.DbName, tableName} 275 s := "SELECT `INDEX_NAME`, `NON_UNIQUE`, `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?" 276 277 rows, err := db.DB().Query(s, args...) 278 db.LogSQL(s, args) 279 if err != nil { 280 return nil, err 281 } 282 defer rows.Close() 283 284 indexes := make(map[string]*core.Index, 0) 285 for rows.Next() { 286 var indexType int 287 var indexName, colName, nonUnique string 288 err = rows.Scan(&indexName, &nonUnique, &colName) 289 if err != nil { 290 return nil, err 291 } 292 293 if indexName == "PRIMARY" { 294 continue 295 } 296 297 if "YES" == nonUnique || nonUnique == "1" { 298 indexType = core.IndexType 299 } else { 300 indexType = core.UniqueType 301 } 302 303 colName = strings.Trim(colName, "` ") 304 var isRegular bool 305 if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) { 306 indexName = indexName[5+len(tableName) : len(indexName)] 307 isRegular = true 308 } 309 310 var index *core.Index 311 var ok bool 312 if index, ok = indexes[indexName]; !ok { 313 index = new(core.Index) 314 index.IsRegular = isRegular 315 index.Type = indexType 316 index.Name = indexName 317 indexes[indexName] = index 318 } 319 index.AddColumn(colName) 320 } 321 return indexes, nil 322 } 323 324 func (db *tidb) Filters() []core.Filter { 325 return []core.Filter{&core.IdFilter{}} 326 }