mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 11:28:24 +00:00 
			
		
		
		
	* Dropped unused codekit config * Integrated dynamic and static bindata for public * Ignore public bindata * Add a general generate make task * Integrated flexible public assets into web command * Updated vendoring, added all missiong govendor deps * Made the linter happy with the bindata and dynamic code * Moved public bindata definition to modules directory * Ignoring the new bindata path now * Updated to the new public modules import path * Updated public bindata command and drop the new prefix
		
			
				
	
	
		
			327 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			327 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2015 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 tidb
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/go-xorm/core"
 | |
| )
 | |
| 
 | |
| type tidb struct {
 | |
| 	core.Base
 | |
| }
 | |
| 
 | |
| func (db *tidb) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error {
 | |
| 	return db.Base.Init(d, db, uri, drivername, dataSourceName)
 | |
| }
 | |
| 
 | |
| func (db *tidb) SqlType(c *core.Column) string {
 | |
| 	var res string
 | |
| 	switch t := c.SQLType.Name; t {
 | |
| 	case core.Bool:
 | |
| 		res = core.Bool
 | |
| 	case core.Serial:
 | |
| 		c.IsAutoIncrement = true
 | |
| 		c.IsPrimaryKey = true
 | |
| 		c.Nullable = false
 | |
| 		res = core.Int
 | |
| 	case core.BigSerial:
 | |
| 		c.IsAutoIncrement = true
 | |
| 		c.IsPrimaryKey = true
 | |
| 		c.Nullable = false
 | |
| 		res = core.BigInt
 | |
| 	case core.Bytea:
 | |
| 		res = core.Blob
 | |
| 	case core.TimeStampz:
 | |
| 		res = core.Char
 | |
| 		c.Length = 64
 | |
| 	case core.Enum: //mysql enum
 | |
| 		res = core.Enum
 | |
| 		res += "("
 | |
| 		opts := ""
 | |
| 		for v, _ := range c.EnumOptions {
 | |
| 			opts += fmt.Sprintf(",'%v'", v)
 | |
| 		}
 | |
| 		res += strings.TrimLeft(opts, ",")
 | |
| 		res += ")"
 | |
| 	case core.Set: //mysql set
 | |
| 		res = core.Set
 | |
| 		res += "("
 | |
| 		opts := ""
 | |
| 		for v, _ := range c.SetOptions {
 | |
| 			opts += fmt.Sprintf(",'%v'", v)
 | |
| 		}
 | |
| 		res += strings.TrimLeft(opts, ",")
 | |
| 		res += ")"
 | |
| 	case core.NVarchar:
 | |
| 		res = core.Varchar
 | |
| 	case core.Uuid:
 | |
| 		res = core.Varchar
 | |
| 		c.Length = 40
 | |
| 	case core.Json:
 | |
| 		res = core.Text
 | |
| 	default:
 | |
| 		res = t
 | |
| 	}
 | |
| 
 | |
| 	var hasLen1 bool = (c.Length > 0)
 | |
| 	var hasLen2 bool = (c.Length2 > 0)
 | |
| 
 | |
| 	if res == core.BigInt && !hasLen1 && !hasLen2 {
 | |
| 		c.Length = 20
 | |
| 		hasLen1 = true
 | |
| 	}
 | |
| 
 | |
| 	if hasLen2 {
 | |
| 		res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
 | |
| 	} else if hasLen1 {
 | |
| 		res += "(" + strconv.Itoa(c.Length) + ")"
 | |
| 	}
 | |
| 	return res
 | |
| }
 | |
| 
 | |
| func (db *tidb) SupportInsertMany() bool {
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func (db *tidb) IsReserved(name string) bool {
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func (db *tidb) Quote(name string) string {
 | |
| 	return "`" + name + "`"
 | |
| }
 | |
| 
 | |
| func (db *tidb) QuoteStr() string {
 | |
| 	return "`"
 | |
| }
 | |
| 
 | |
| func (db *tidb) SupportEngine() bool {
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func (db *tidb) AutoIncrStr() string {
 | |
| 	return "AUTO_INCREMENT"
 | |
| }
 | |
| 
 | |
| func (db *tidb) SupportCharset() bool {
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func (db *tidb) IndexOnTable() bool {
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func (db *tidb) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
 | |
| 	args := []interface{}{db.DbName, tableName, idxName}
 | |
| 	sql := "SELECT `INDEX_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS`"
 | |
| 	sql += " WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `INDEX_NAME`=?"
 | |
| 	return sql, args
 | |
| }
 | |
| 
 | |
| func (db *tidb) TableCheckSql(tableName string) (string, []interface{}) {
 | |
| 	args := []interface{}{db.DbName, tableName}
 | |
| 	sql := "SELECT `TABLE_NAME` from `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? and `TABLE_NAME`=?"
 | |
| 	return sql, args
 | |
| }
 | |
| 
 | |
| func (db *tidb) GetColumns(tableName string) ([]string, map[string]*core.Column, error) {
 | |
| 	args := []interface{}{db.DbName, tableName}
 | |
| 	s := "SELECT `COLUMN_NAME`, `IS_NULLABLE`, `COLUMN_DEFAULT`, `COLUMN_TYPE`," +
 | |
| 		" `COLUMN_KEY`, `EXTRA` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?"
 | |
| 
 | |
| 	rows, err := db.DB().Query(s, args...)
 | |
| 	db.LogSQL(s, args)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return nil, nil, err
 | |
| 	}
 | |
| 	defer rows.Close()
 | |
| 
 | |
| 	cols := make(map[string]*core.Column)
 | |
| 	colSeq := make([]string, 0)
 | |
| 	for rows.Next() {
 | |
| 		col := new(core.Column)
 | |
| 		col.Indexes = make(map[string]int)
 | |
| 
 | |
| 		var columnName, isNullable, colType, colKey, extra string
 | |
| 		var colDefault *string
 | |
| 		err = rows.Scan(&columnName, &isNullable, &colDefault, &colType, &colKey, &extra)
 | |
| 		if err != nil {
 | |
| 			return nil, nil, err
 | |
| 		}
 | |
| 		col.Name = strings.Trim(columnName, "` ")
 | |
| 		if "YES" == isNullable {
 | |
| 			col.Nullable = true
 | |
| 		}
 | |
| 
 | |
| 		if colDefault != nil {
 | |
| 			col.Default = *colDefault
 | |
| 			if col.Default == "" {
 | |
| 				col.DefaultIsEmpty = true
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		cts := strings.Split(colType, "(")
 | |
| 		colName := cts[0]
 | |
| 		colType = strings.ToUpper(colName)
 | |
| 		var len1, len2 int
 | |
| 		if len(cts) == 2 {
 | |
| 			idx := strings.Index(cts[1], ")")
 | |
| 			if colType == core.Enum && cts[1][0] == '\'' { //enum
 | |
| 				options := strings.Split(cts[1][0:idx], ",")
 | |
| 				col.EnumOptions = make(map[string]int)
 | |
| 				for k, v := range options {
 | |
| 					v = strings.TrimSpace(v)
 | |
| 					v = strings.Trim(v, "'")
 | |
| 					col.EnumOptions[v] = k
 | |
| 				}
 | |
| 			} else if colType == core.Set && cts[1][0] == '\'' {
 | |
| 				options := strings.Split(cts[1][0:idx], ",")
 | |
| 				col.SetOptions = make(map[string]int)
 | |
| 				for k, v := range options {
 | |
| 					v = strings.TrimSpace(v)
 | |
| 					v = strings.Trim(v, "'")
 | |
| 					col.SetOptions[v] = k
 | |
| 				}
 | |
| 			} else {
 | |
| 				lens := strings.Split(cts[1][0:idx], ",")
 | |
| 				len1, err = strconv.Atoi(strings.TrimSpace(lens[0]))
 | |
| 				if err != nil {
 | |
| 					return nil, nil, err
 | |
| 				}
 | |
| 				if len(lens) == 2 {
 | |
| 					len2, err = strconv.Atoi(lens[1])
 | |
| 					if err != nil {
 | |
| 						return nil, nil, err
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		if colType == "FLOAT UNSIGNED" {
 | |
| 			colType = "FLOAT"
 | |
| 		}
 | |
| 		col.Length = len1
 | |
| 		col.Length2 = len2
 | |
| 		if _, ok := core.SqlTypes[colType]; ok {
 | |
| 			col.SQLType = core.SQLType{colType, len1, len2}
 | |
| 		} else {
 | |
| 			return nil, nil, errors.New(fmt.Sprintf("unkonw colType %v", colType))
 | |
| 		}
 | |
| 
 | |
| 		if colKey == "PRI" {
 | |
| 			col.IsPrimaryKey = true
 | |
| 		}
 | |
| 		if colKey == "UNI" {
 | |
| 			//col.is
 | |
| 		}
 | |
| 
 | |
| 		if extra == "auto_increment" {
 | |
| 			col.IsAutoIncrement = true
 | |
| 		}
 | |
| 
 | |
| 		if col.SQLType.IsText() || col.SQLType.IsTime() {
 | |
| 			if col.Default != "" {
 | |
| 				col.Default = "'" + col.Default + "'"
 | |
| 			} else {
 | |
| 				if col.DefaultIsEmpty {
 | |
| 					col.Default = "''"
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		cols[col.Name] = col
 | |
| 		colSeq = append(colSeq, col.Name)
 | |
| 	}
 | |
| 	return colSeq, cols, nil
 | |
| }
 | |
| 
 | |
| func (db *tidb) GetTables() ([]*core.Table, error) {
 | |
| 	args := []interface{}{db.DbName}
 | |
| 	s := "SELECT `TABLE_NAME`, `ENGINE`, `TABLE_ROWS`, `AUTO_INCREMENT` from " +
 | |
| 		"`INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? AND (`ENGINE`='MyISAM' OR `ENGINE` = 'InnoDB')"
 | |
| 
 | |
| 	rows, err := db.DB().Query(s, args...)
 | |
| 	db.LogSQL(s, args)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer rows.Close()
 | |
| 
 | |
| 	tables := make([]*core.Table, 0)
 | |
| 	for rows.Next() {
 | |
| 		table := core.NewEmptyTable()
 | |
| 		var name, engine, tableRows string
 | |
| 		var autoIncr *string
 | |
| 		err = rows.Scan(&name, &engine, &tableRows, &autoIncr)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		table.Name = name
 | |
| 		table.StoreEngine = engine
 | |
| 		tables = append(tables, table)
 | |
| 	}
 | |
| 	return tables, nil
 | |
| }
 | |
| 
 | |
| func (db *tidb) GetIndexes(tableName string) (map[string]*core.Index, error) {
 | |
| 	args := []interface{}{db.DbName, tableName}
 | |
| 	s := "SELECT `INDEX_NAME`, `NON_UNIQUE`, `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?"
 | |
| 
 | |
| 	rows, err := db.DB().Query(s, args...)
 | |
| 	db.LogSQL(s, args)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer rows.Close()
 | |
| 
 | |
| 	indexes := make(map[string]*core.Index, 0)
 | |
| 	for rows.Next() {
 | |
| 		var indexType int
 | |
| 		var indexName, colName, nonUnique string
 | |
| 		err = rows.Scan(&indexName, &nonUnique, &colName)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		if indexName == "PRIMARY" {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		if "YES" == nonUnique || nonUnique == "1" {
 | |
| 			indexType = core.IndexType
 | |
| 		} else {
 | |
| 			indexType = core.UniqueType
 | |
| 		}
 | |
| 
 | |
| 		colName = strings.Trim(colName, "` ")
 | |
| 		var isRegular bool
 | |
| 		if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
 | |
| 			indexName = indexName[5+len(tableName) : len(indexName)]
 | |
| 			isRegular = true
 | |
| 		}
 | |
| 
 | |
| 		var index *core.Index
 | |
| 		var ok bool
 | |
| 		if index, ok = indexes[indexName]; !ok {
 | |
| 			index = new(core.Index)
 | |
| 			index.IsRegular = isRegular
 | |
| 			index.Type = indexType
 | |
| 			index.Name = indexName
 | |
| 			indexes[indexName] = index
 | |
| 		}
 | |
| 		index.AddColumn(colName)
 | |
| 	}
 | |
| 	return indexes, nil
 | |
| }
 | |
| 
 | |
| func (db *tidb) Filters() []core.Filter {
 | |
| 	return []core.Filter{&core.IdFilter{}}
 | |
| }
 |