github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/go-xorm/xorm/sqlite3_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 xorm
     6  
     7  import (
     8  	"database/sql"
     9  	"errors"
    10  	"fmt"
    11  	"regexp"
    12  	"strings"
    13  
    14  	"github.com/insionng/yougam/libraries/go-xorm/core"
    15  )
    16  
    17  // func init() {
    18  // 	RegisterDialect("sqlite3", &sqlite3{})
    19  // }
    20  
    21  var (
    22  	sqlite3ReservedWords = map[string]bool{
    23  		"ABORT":             true,
    24  		"ACTION":            true,
    25  		"ADD":               true,
    26  		"AFTER":             true,
    27  		"ALL":               true,
    28  		"ALTER":             true,
    29  		"ANALYZE":           true,
    30  		"AND":               true,
    31  		"AS":                true,
    32  		"ASC":               true,
    33  		"ATTACH":            true,
    34  		"AUTOINCREMENT":     true,
    35  		"BEFORE":            true,
    36  		"BEGIN":             true,
    37  		"BETWEEN":           true,
    38  		"BY":                true,
    39  		"CASCADE":           true,
    40  		"CASE":              true,
    41  		"CAST":              true,
    42  		"CHECK":             true,
    43  		"COLLATE":           true,
    44  		"COLUMN":            true,
    45  		"COMMIT":            true,
    46  		"CONFLICT":          true,
    47  		"CONSTRAINT":        true,
    48  		"CREATE":            true,
    49  		"CROSS":             true,
    50  		"CURRENT_DATE":      true,
    51  		"CURRENT_TIME":      true,
    52  		"CURRENT_TIMESTAMP": true,
    53  		"DATABASE":          true,
    54  		"DEFAULT":           true,
    55  		"DEFERRABLE":        true,
    56  		"DEFERRED":          true,
    57  		"DELETE":            true,
    58  		"DESC":              true,
    59  		"DETACH":            true,
    60  		"DISTINCT":          true,
    61  		"DROP":              true,
    62  		"EACH":              true,
    63  		"ELSE":              true,
    64  		"END":               true,
    65  		"ESCAPE":            true,
    66  		"EXCEPT":            true,
    67  		"EXCLUSIVE":         true,
    68  		"EXISTS":            true,
    69  		"EXPLAIN":           true,
    70  		"FAIL":              true,
    71  		"FOR":               true,
    72  		"FOREIGN":           true,
    73  		"FROM":              true,
    74  		"FULL":              true,
    75  		"GLOB":              true,
    76  		"GROUP":             true,
    77  		"HAVING":            true,
    78  		"IF":                true,
    79  		"IGNORE":            true,
    80  		"IMMEDIATE":         true,
    81  		"IN":                true,
    82  		"INDEX":             true,
    83  		"INDEXED":           true,
    84  		"INITIALLY":         true,
    85  		"INNER":             true,
    86  		"INSERT":            true,
    87  		"INSTEAD":           true,
    88  		"INTERSECT":         true,
    89  		"INTO":              true,
    90  		"IS":                true,
    91  		"ISNULL":            true,
    92  		"JOIN":              true,
    93  		"KEY":               true,
    94  		"LEFT":              true,
    95  		"LIKE":              true,
    96  		"LIMIT":             true,
    97  		"MATCH":             true,
    98  		"NATURAL":           true,
    99  		"NO":                true,
   100  		"NOT":               true,
   101  		"NOTNULL":           true,
   102  		"NULL":              true,
   103  		"OF":                true,
   104  		"OFFSET":            true,
   105  		"ON":                true,
   106  		"OR":                true,
   107  		"ORDER":             true,
   108  		"OUTER":             true,
   109  		"PLAN":              true,
   110  		"PRAGMA":            true,
   111  		"PRIMARY":           true,
   112  		"QUERY":             true,
   113  		"RAISE":             true,
   114  		"RECURSIVE":         true,
   115  		"REFERENCES":        true,
   116  		"REGEXP":            true,
   117  		"REINDEX":           true,
   118  		"RELEASE":           true,
   119  		"RENAME":            true,
   120  		"REPLACE":           true,
   121  		"RESTRICT":          true,
   122  		"RIGHT":             true,
   123  		"ROLLBACK":          true,
   124  		"ROW":               true,
   125  		"SAVEPOINT":         true,
   126  		"SELECT":            true,
   127  		"SET":               true,
   128  		"TABLE":             true,
   129  		"TEMP":              true,
   130  		"TEMPORARY":         true,
   131  		"THEN":              true,
   132  		"TO":                true,
   133  		"TRANSACTI":         true,
   134  		"TRIGGER":           true,
   135  		"UNION":             true,
   136  		"UNIQUE":            true,
   137  		"UPDATE":            true,
   138  		"USING":             true,
   139  		"VACUUM":            true,
   140  		"VALUES":            true,
   141  		"VIEW":              true,
   142  		"VIRTUAL":           true,
   143  		"WHEN":              true,
   144  		"WHERE":             true,
   145  		"WITH":              true,
   146  		"WITHOUT":           true,
   147  	}
   148  )
   149  
   150  type sqlite3 struct {
   151  	core.Base
   152  }
   153  
   154  func (db *sqlite3) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error {
   155  	return db.Base.Init(d, db, uri, drivername, dataSourceName)
   156  }
   157  
   158  func (db *sqlite3) SqlType(c *core.Column) string {
   159  	switch t := c.SQLType.Name; t {
   160  	case core.Bool:
   161  		if c.Default == "true" {
   162  			c.Default = "1"
   163  		} else if c.Default == "false" {
   164  			c.Default = "0"
   165  		}
   166  		return core.Integer
   167  	case core.Date, core.DateTime, core.TimeStamp, core.Time:
   168  		return core.DateTime
   169  	case core.TimeStampz:
   170  		return core.Text
   171  	case core.Char, core.Varchar, core.NVarchar, core.TinyText,
   172  		core.Text, core.MediumText, core.LongText, core.Json:
   173  		return core.Text
   174  	case core.Bit, core.TinyInt, core.SmallInt, core.MediumInt, core.Int, core.Integer, core.BigInt:
   175  		return core.Integer
   176  	case core.Float, core.Double, core.Real:
   177  		return core.Real
   178  	case core.Decimal, core.Numeric:
   179  		return core.Numeric
   180  	case core.TinyBlob, core.Blob, core.MediumBlob, core.LongBlob, core.Bytea, core.Binary, core.VarBinary:
   181  		return core.Blob
   182  	case core.Serial, core.BigSerial:
   183  		c.IsPrimaryKey = true
   184  		c.IsAutoIncrement = true
   185  		c.Nullable = false
   186  		return core.Integer
   187  	default:
   188  		return t
   189  	}
   190  }
   191  
   192  func (db *sqlite3) FormatBytes(bs []byte) string {
   193  	return fmt.Sprintf("X'%x'", bs)
   194  }
   195  
   196  func (db *sqlite3) SupportInsertMany() bool {
   197  	return true
   198  }
   199  
   200  func (db *sqlite3) IsReserved(name string) bool {
   201  	_, ok := sqlite3ReservedWords[name]
   202  	return ok
   203  }
   204  
   205  func (db *sqlite3) Quote(name string) string {
   206  	return "`" + name + "`"
   207  }
   208  
   209  func (db *sqlite3) QuoteStr() string {
   210  	return "`"
   211  }
   212  
   213  func (db *sqlite3) AutoIncrStr() string {
   214  	return "AUTOINCREMENT"
   215  }
   216  
   217  func (db *sqlite3) SupportEngine() bool {
   218  	return false
   219  }
   220  
   221  func (db *sqlite3) SupportCharset() bool {
   222  	return false
   223  }
   224  
   225  func (db *sqlite3) IndexOnTable() bool {
   226  	return false
   227  }
   228  
   229  func (db *sqlite3) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
   230  	args := []interface{}{idxName}
   231  	return "SELECT name FROM sqlite_master WHERE type='index' and name = ?", args
   232  }
   233  
   234  func (db *sqlite3) TableCheckSql(tableName string) (string, []interface{}) {
   235  	args := []interface{}{tableName}
   236  	return "SELECT name FROM sqlite_master WHERE type='table' and name = ?", args
   237  }
   238  
   239  func (db *sqlite3) DropIndexSql(tableName string, index *core.Index) string {
   240  	//var unique string
   241  	quote := db.Quote
   242  	idxName := index.Name
   243  
   244  	if !strings.HasPrefix(idxName, "UQE_") &&
   245  		!strings.HasPrefix(idxName, "IDX_") {
   246  		if index.Type == core.UniqueType {
   247  			idxName = fmt.Sprintf("UQE_%v_%v", tableName, index.Name)
   248  		} else {
   249  			idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name)
   250  		}
   251  	}
   252  	return fmt.Sprintf("DROP INDEX %v", quote(idxName))
   253  }
   254  
   255  func (db *sqlite3) ForUpdateSql(query string) string {
   256  	return query
   257  }
   258  
   259  /*func (db *sqlite3) ColumnCheckSql(tableName, colName string) (string, []interface{}) {
   260  	args := []interface{}{tableName}
   261  	sql := "SELECT name FROM sqlite_master WHERE type='table' and name = ? and ((sql like '%`" + colName + "`%') or (sql like '%[" + colName + "]%'))"
   262  	return sql, args
   263  }*/
   264  
   265  func (db *sqlite3) IsColumnExist(tableName, colName string) (bool, error) {
   266  	args := []interface{}{tableName}
   267  	query := "SELECT name FROM sqlite_master WHERE type='table' and name = ? and ((sql like '%`" + colName + "`%') or (sql like '%[" + colName + "]%'))"
   268  	db.LogSQL(query, args)
   269  	rows, err := db.DB().Query(query, args...)
   270  	if err != nil {
   271  		return false, err
   272  	}
   273  	defer rows.Close()
   274  
   275  	if rows.Next() {
   276  		return true, nil
   277  	}
   278  	return false, nil
   279  }
   280  
   281  func (db *sqlite3) GetColumns(tableName string) ([]string, map[string]*core.Column, error) {
   282  	args := []interface{}{tableName}
   283  	s := "SELECT sql FROM sqlite_master WHERE type='table' and name = ?"
   284  	db.LogSQL(s, args)
   285  	rows, err := db.DB().Query(s, args...)
   286  	if err != nil {
   287  		return nil, nil, err
   288  	}
   289  	defer rows.Close()
   290  
   291  	var name string
   292  	for rows.Next() {
   293  		err = rows.Scan(&name)
   294  		if err != nil {
   295  			return nil, nil, err
   296  		}
   297  		break
   298  	}
   299  
   300  	if name == "" {
   301  		return nil, nil, errors.New("no table named " + tableName)
   302  	}
   303  
   304  	nStart := strings.Index(name, "(")
   305  	nEnd := strings.LastIndex(name, ")")
   306  	reg := regexp.MustCompile(`[^\(,\)]*(\([^\(]*\))?`)
   307  	colCreates := reg.FindAllString(name[nStart+1:nEnd], -1)
   308  	cols := make(map[string]*core.Column)
   309  	colSeq := make([]string, 0)
   310  	for _, colStr := range colCreates {
   311  		reg = regexp.MustCompile(`,\s`)
   312  		colStr = reg.ReplaceAllString(colStr, ",")
   313  		fields := strings.Fields(strings.TrimSpace(colStr))
   314  		col := new(core.Column)
   315  		col.Indexes = make(map[string]int)
   316  		col.Nullable = true
   317  		col.DefaultIsEmpty = true
   318  		for idx, field := range fields {
   319  			if idx == 0 {
   320  				col.Name = strings.Trim(field, "`[] ")
   321  				continue
   322  			} else if idx == 1 {
   323  				col.SQLType = core.SQLType{Name: field, DefaultLength: 0, DefaultLength2: 0}
   324  			}
   325  			switch field {
   326  			case "PRIMARY":
   327  				col.IsPrimaryKey = true
   328  			case "AUTOINCREMENT":
   329  				col.IsAutoIncrement = true
   330  			case "NULL":
   331  				if fields[idx-1] == "NOT" {
   332  					col.Nullable = false
   333  				} else {
   334  					col.Nullable = true
   335  				}
   336  			case "DEFAULT":
   337  				col.Default = fields[idx+1]
   338  				col.DefaultIsEmpty = false
   339  			}
   340  		}
   341  		if !col.SQLType.IsNumeric() && !col.DefaultIsEmpty {
   342  			col.Default = "'" + col.Default + "'"
   343  		}
   344  		cols[col.Name] = col
   345  		colSeq = append(colSeq, col.Name)
   346  	}
   347  	return colSeq, cols, nil
   348  }
   349  
   350  func (db *sqlite3) GetTables() ([]*core.Table, error) {
   351  	args := []interface{}{}
   352  	s := "SELECT name FROM sqlite_master WHERE type='table'"
   353  	db.LogSQL(s, args)
   354  
   355  	rows, err := db.DB().Query(s, args...)
   356  	if err != nil {
   357  		return nil, err
   358  	}
   359  	defer rows.Close()
   360  
   361  	tables := make([]*core.Table, 0)
   362  	for rows.Next() {
   363  		table := core.NewEmptyTable()
   364  		err = rows.Scan(&table.Name)
   365  		if err != nil {
   366  			return nil, err
   367  		}
   368  		if table.Name == "sqlite_sequence" {
   369  			continue
   370  		}
   371  		tables = append(tables, table)
   372  	}
   373  	return tables, nil
   374  }
   375  
   376  func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error) {
   377  	args := []interface{}{tableName}
   378  	s := "SELECT sql FROM sqlite_master WHERE type='index' and tbl_name = ?"
   379  	db.LogSQL(s, args)
   380  
   381  	rows, err := db.DB().Query(s, args...)
   382  	if err != nil {
   383  		return nil, err
   384  	}
   385  	defer rows.Close()
   386  
   387  	indexes := make(map[string]*core.Index, 0)
   388  	for rows.Next() {
   389  		var tmpSql sql.NullString
   390  		err = rows.Scan(&tmpSql)
   391  		if err != nil {
   392  			return nil, err
   393  		}
   394  
   395  		if !tmpSql.Valid {
   396  			continue
   397  		}
   398  		sql := tmpSql.String
   399  
   400  		index := new(core.Index)
   401  		nNStart := strings.Index(sql, "INDEX")
   402  		nNEnd := strings.Index(sql, "ON")
   403  		if nNStart == -1 || nNEnd == -1 {
   404  			continue
   405  		}
   406  
   407  		indexName := strings.Trim(sql[nNStart+6:nNEnd], "` []")
   408  		if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
   409  			index.Name = indexName[5+len(tableName) : len(indexName)]
   410  		} else {
   411  			index.Name = indexName
   412  		}
   413  
   414  		if strings.HasPrefix(sql, "CREATE UNIQUE INDEX") {
   415  			index.Type = core.UniqueType
   416  		} else {
   417  			index.Type = core.IndexType
   418  		}
   419  
   420  		nStart := strings.Index(sql, "(")
   421  		nEnd := strings.Index(sql, ")")
   422  		colIndexes := strings.Split(sql[nStart+1:nEnd], ",")
   423  
   424  		index.Cols = make([]string, 0)
   425  		for _, col := range colIndexes {
   426  			index.Cols = append(index.Cols, strings.Trim(col, "` []"))
   427  		}
   428  		indexes[index.Name] = index
   429  	}
   430  
   431  	return indexes, nil
   432  }
   433  
   434  func (db *sqlite3) Filters() []core.Filter {
   435  	return []core.Filter{&core.IdFilter{}}
   436  }