2019-06-23 15:22:43 +00:00
|
|
|
// 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.
|
|
|
|
|
2020-03-22 15:12:55 +00:00
|
|
|
package schemas
|
2016-11-03 22:16:01 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// DBType represents a database type
|
2020-03-22 15:12:55 +00:00
|
|
|
type DBType string
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// enumerates all database types
|
2016-11-03 22:16:01 +00:00
|
|
|
const (
|
2020-03-22 15:12:55 +00:00
|
|
|
POSTGRES DBType = "postgres"
|
|
|
|
SQLITE DBType = "sqlite3"
|
|
|
|
MYSQL DBType = "mysql"
|
|
|
|
MSSQL DBType = "mssql"
|
|
|
|
ORACLE DBType = "oracle"
|
2016-11-03 22:16:01 +00:00
|
|
|
)
|
|
|
|
|
2020-03-22 15:12:55 +00:00
|
|
|
// SQLType represents SQL types
|
2016-11-03 22:16:01 +00:00
|
|
|
type SQLType struct {
|
|
|
|
Name string
|
|
|
|
DefaultLength int
|
|
|
|
DefaultLength2 int
|
|
|
|
}
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// enumerates all columns types
|
2016-11-03 22:16:01 +00:00
|
|
|
const (
|
|
|
|
UNKNOW_TYPE = iota
|
|
|
|
TEXT_TYPE
|
|
|
|
BLOB_TYPE
|
|
|
|
TIME_TYPE
|
|
|
|
NUMERIC_TYPE
|
2020-03-22 15:12:55 +00:00
|
|
|
ARRAY_TYPE
|
2016-11-03 22:16:01 +00:00
|
|
|
)
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// IsType reutrns ture if the column type is the same as the parameter
|
2016-11-03 22:16:01 +00:00
|
|
|
func (s *SQLType) IsType(st int) bool {
|
|
|
|
if t, ok := SqlTypes[s.Name]; ok && t == st {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// IsText returns true if column is a text type
|
2016-11-03 22:16:01 +00:00
|
|
|
func (s *SQLType) IsText() bool {
|
|
|
|
return s.IsType(TEXT_TYPE)
|
|
|
|
}
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// IsBlob returns true if column is a binary type
|
2016-11-03 22:16:01 +00:00
|
|
|
func (s *SQLType) IsBlob() bool {
|
|
|
|
return s.IsType(BLOB_TYPE)
|
|
|
|
}
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// IsTime returns true if column is a time type
|
2016-11-03 22:16:01 +00:00
|
|
|
func (s *SQLType) IsTime() bool {
|
|
|
|
return s.IsType(TIME_TYPE)
|
|
|
|
}
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// IsNumeric returns true if column is a numeric type
|
2016-11-03 22:16:01 +00:00
|
|
|
func (s *SQLType) IsNumeric() bool {
|
|
|
|
return s.IsType(NUMERIC_TYPE)
|
|
|
|
}
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// IsArray returns true if column is an array type
|
2020-03-22 15:12:55 +00:00
|
|
|
func (s *SQLType) IsArray() bool {
|
|
|
|
return s.IsType(ARRAY_TYPE)
|
|
|
|
}
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// IsJson returns true if column is an array type
|
2016-11-03 22:16:01 +00:00
|
|
|
func (s *SQLType) IsJson() bool {
|
2017-01-03 08:20:28 +00:00
|
|
|
return s.Name == Json || s.Name == Jsonb
|
2016-11-03 22:16:01 +00:00
|
|
|
}
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// IsXML returns true if column is an xml type
|
2021-02-17 03:47:24 +00:00
|
|
|
func (s *SQLType) IsXML() bool {
|
|
|
|
return s.Name == XML
|
|
|
|
}
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// enumerates all the database column types
|
2016-11-03 22:16:01 +00:00
|
|
|
var (
|
2021-05-14 19:17:06 +00:00
|
|
|
Bit = "BIT"
|
|
|
|
UnsignedBit = "UNSIGNED BIT"
|
|
|
|
TinyInt = "TINYINT"
|
|
|
|
SmallInt = "SMALLINT"
|
|
|
|
MediumInt = "MEDIUMINT"
|
|
|
|
Int = "INT"
|
|
|
|
UnsignedInt = "UNSIGNED INT"
|
|
|
|
Integer = "INTEGER"
|
|
|
|
BigInt = "BIGINT"
|
|
|
|
UnsignedBigInt = "UNSIGNED BIGINT"
|
2016-11-03 22:16:01 +00:00
|
|
|
|
|
|
|
Enum = "ENUM"
|
|
|
|
Set = "SET"
|
|
|
|
|
2018-07-20 02:10:17 +00:00
|
|
|
Char = "CHAR"
|
|
|
|
Varchar = "VARCHAR"
|
2019-06-23 15:22:43 +00:00
|
|
|
NChar = "NCHAR"
|
2018-07-20 02:10:17 +00:00
|
|
|
NVarchar = "NVARCHAR"
|
|
|
|
TinyText = "TINYTEXT"
|
|
|
|
Text = "TEXT"
|
|
|
|
NText = "NTEXT"
|
|
|
|
Clob = "CLOB"
|
|
|
|
MediumText = "MEDIUMTEXT"
|
|
|
|
LongText = "LONGTEXT"
|
|
|
|
Uuid = "UUID"
|
|
|
|
UniqueIdentifier = "UNIQUEIDENTIFIER"
|
|
|
|
SysName = "SYSNAME"
|
2016-11-03 22:16:01 +00:00
|
|
|
|
2019-08-27 02:17:23 +00:00
|
|
|
Date = "DATE"
|
|
|
|
DateTime = "DATETIME"
|
|
|
|
SmallDateTime = "SMALLDATETIME"
|
|
|
|
Time = "TIME"
|
|
|
|
TimeStamp = "TIMESTAMP"
|
|
|
|
TimeStampz = "TIMESTAMPZ"
|
2019-09-29 12:52:39 +00:00
|
|
|
Year = "YEAR"
|
2019-08-27 02:17:23 +00:00
|
|
|
|
|
|
|
Decimal = "DECIMAL"
|
|
|
|
Numeric = "NUMERIC"
|
|
|
|
Money = "MONEY"
|
2019-06-23 15:22:43 +00:00
|
|
|
SmallMoney = "SMALLMONEY"
|
2016-11-03 22:16:01 +00:00
|
|
|
|
|
|
|
Real = "REAL"
|
|
|
|
Float = "FLOAT"
|
|
|
|
Double = "DOUBLE"
|
|
|
|
|
|
|
|
Binary = "BINARY"
|
|
|
|
VarBinary = "VARBINARY"
|
|
|
|
TinyBlob = "TINYBLOB"
|
|
|
|
Blob = "BLOB"
|
|
|
|
MediumBlob = "MEDIUMBLOB"
|
|
|
|
LongBlob = "LONGBLOB"
|
|
|
|
Bytea = "BYTEA"
|
|
|
|
|
2017-09-13 05:18:22 +00:00
|
|
|
Bool = "BOOL"
|
|
|
|
Boolean = "BOOLEAN"
|
2016-11-03 22:16:01 +00:00
|
|
|
|
|
|
|
Serial = "SERIAL"
|
|
|
|
BigSerial = "BIGSERIAL"
|
|
|
|
|
|
|
|
Json = "JSON"
|
|
|
|
Jsonb = "JSONB"
|
|
|
|
|
2021-02-17 03:47:24 +00:00
|
|
|
XML = "XML"
|
2020-03-22 15:12:55 +00:00
|
|
|
Array = "ARRAY"
|
|
|
|
|
2016-11-03 22:16:01 +00:00
|
|
|
SqlTypes = map[string]int{
|
2021-05-14 19:17:06 +00:00
|
|
|
Bit: NUMERIC_TYPE,
|
|
|
|
UnsignedBit: NUMERIC_TYPE,
|
|
|
|
TinyInt: NUMERIC_TYPE,
|
|
|
|
SmallInt: NUMERIC_TYPE,
|
|
|
|
MediumInt: NUMERIC_TYPE,
|
|
|
|
Int: NUMERIC_TYPE,
|
|
|
|
UnsignedInt: NUMERIC_TYPE,
|
|
|
|
Integer: NUMERIC_TYPE,
|
|
|
|
BigInt: NUMERIC_TYPE,
|
|
|
|
UnsignedBigInt: NUMERIC_TYPE,
|
2016-11-03 22:16:01 +00:00
|
|
|
|
|
|
|
Enum: TEXT_TYPE,
|
|
|
|
Set: TEXT_TYPE,
|
|
|
|
Json: TEXT_TYPE,
|
|
|
|
Jsonb: TEXT_TYPE,
|
|
|
|
|
2021-02-17 03:47:24 +00:00
|
|
|
XML: TEXT_TYPE,
|
|
|
|
|
2016-11-03 22:16:01 +00:00
|
|
|
Char: TEXT_TYPE,
|
2019-06-23 15:22:43 +00:00
|
|
|
NChar: TEXT_TYPE,
|
2016-11-03 22:16:01 +00:00
|
|
|
Varchar: TEXT_TYPE,
|
|
|
|
NVarchar: TEXT_TYPE,
|
|
|
|
TinyText: TEXT_TYPE,
|
|
|
|
Text: TEXT_TYPE,
|
2018-07-20 02:10:17 +00:00
|
|
|
NText: TEXT_TYPE,
|
2016-11-03 22:16:01 +00:00
|
|
|
MediumText: TEXT_TYPE,
|
|
|
|
LongText: TEXT_TYPE,
|
|
|
|
Uuid: TEXT_TYPE,
|
|
|
|
Clob: TEXT_TYPE,
|
2018-07-20 02:10:17 +00:00
|
|
|
SysName: TEXT_TYPE,
|
2016-11-03 22:16:01 +00:00
|
|
|
|
2019-08-27 02:17:23 +00:00
|
|
|
Date: TIME_TYPE,
|
|
|
|
DateTime: TIME_TYPE,
|
|
|
|
Time: TIME_TYPE,
|
|
|
|
TimeStamp: TIME_TYPE,
|
|
|
|
TimeStampz: TIME_TYPE,
|
|
|
|
SmallDateTime: TIME_TYPE,
|
2019-09-29 12:52:39 +00:00
|
|
|
Year: TIME_TYPE,
|
2019-08-27 02:17:23 +00:00
|
|
|
|
|
|
|
Decimal: NUMERIC_TYPE,
|
|
|
|
Numeric: NUMERIC_TYPE,
|
|
|
|
Real: NUMERIC_TYPE,
|
|
|
|
Float: NUMERIC_TYPE,
|
|
|
|
Double: NUMERIC_TYPE,
|
|
|
|
Money: NUMERIC_TYPE,
|
2019-06-23 15:22:43 +00:00
|
|
|
SmallMoney: NUMERIC_TYPE,
|
2016-11-03 22:16:01 +00:00
|
|
|
|
|
|
|
Binary: BLOB_TYPE,
|
|
|
|
VarBinary: BLOB_TYPE,
|
|
|
|
|
2018-07-20 02:10:17 +00:00
|
|
|
TinyBlob: BLOB_TYPE,
|
|
|
|
Blob: BLOB_TYPE,
|
|
|
|
MediumBlob: BLOB_TYPE,
|
|
|
|
LongBlob: BLOB_TYPE,
|
|
|
|
Bytea: BLOB_TYPE,
|
|
|
|
UniqueIdentifier: BLOB_TYPE,
|
2016-11-03 22:16:01 +00:00
|
|
|
|
|
|
|
Bool: NUMERIC_TYPE,
|
|
|
|
|
|
|
|
Serial: NUMERIC_TYPE,
|
|
|
|
BigSerial: NUMERIC_TYPE,
|
2020-03-22 15:12:55 +00:00
|
|
|
|
|
|
|
Array: ARRAY_TYPE,
|
2016-11-03 22:16:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
intTypes = sort.StringSlice{"*int", "*int16", "*int32", "*int8"}
|
|
|
|
uintTypes = sort.StringSlice{"*uint", "*uint16", "*uint32", "*uint8"}
|
|
|
|
)
|
|
|
|
|
2017-09-13 05:18:22 +00:00
|
|
|
// !nashtsai! treat following var as interal const values, these are used for reflect.TypeOf comparison
|
2016-11-03 22:16:01 +00:00
|
|
|
var (
|
2021-05-14 19:17:06 +00:00
|
|
|
emptyString string
|
|
|
|
boolDefault bool
|
|
|
|
byteDefault byte
|
|
|
|
complex64Default complex64
|
|
|
|
complex128Default complex128
|
|
|
|
float32Default float32
|
|
|
|
float64Default float64
|
|
|
|
int64Default int64
|
|
|
|
uint64Default uint64
|
|
|
|
int32Default int32
|
|
|
|
uint32Default uint32
|
|
|
|
int16Default int16
|
|
|
|
uint16Default uint16
|
|
|
|
int8Default int8
|
|
|
|
uint8Default uint8
|
|
|
|
intDefault int
|
|
|
|
uintDefault uint
|
|
|
|
timeDefault time.Time
|
2016-11-03 22:16:01 +00:00
|
|
|
)
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// enumerates all types
|
2016-11-03 22:16:01 +00:00
|
|
|
var (
|
2021-05-14 19:17:06 +00:00
|
|
|
IntType = reflect.TypeOf(intDefault)
|
|
|
|
Int8Type = reflect.TypeOf(int8Default)
|
|
|
|
Int16Type = reflect.TypeOf(int16Default)
|
|
|
|
Int32Type = reflect.TypeOf(int32Default)
|
|
|
|
Int64Type = reflect.TypeOf(int64Default)
|
|
|
|
|
|
|
|
UintType = reflect.TypeOf(uintDefault)
|
|
|
|
Uint8Type = reflect.TypeOf(uint8Default)
|
|
|
|
Uint16Type = reflect.TypeOf(uint16Default)
|
|
|
|
Uint32Type = reflect.TypeOf(uint32Default)
|
|
|
|
Uint64Type = reflect.TypeOf(uint64Default)
|
|
|
|
|
|
|
|
Float32Type = reflect.TypeOf(float32Default)
|
|
|
|
Float64Type = reflect.TypeOf(float64Default)
|
|
|
|
|
|
|
|
Complex64Type = reflect.TypeOf(complex64Default)
|
|
|
|
Complex128Type = reflect.TypeOf(complex128Default)
|
|
|
|
|
|
|
|
StringType = reflect.TypeOf(emptyString)
|
|
|
|
BoolType = reflect.TypeOf(boolDefault)
|
|
|
|
ByteType = reflect.TypeOf(byteDefault)
|
2016-11-03 22:16:01 +00:00
|
|
|
BytesType = reflect.SliceOf(ByteType)
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
TimeType = reflect.TypeOf(timeDefault)
|
2016-11-03 22:16:01 +00:00
|
|
|
)
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// enumerates all types
|
2016-11-03 22:16:01 +00:00
|
|
|
var (
|
|
|
|
PtrIntType = reflect.PtrTo(IntType)
|
|
|
|
PtrInt8Type = reflect.PtrTo(Int8Type)
|
|
|
|
PtrInt16Type = reflect.PtrTo(Int16Type)
|
|
|
|
PtrInt32Type = reflect.PtrTo(Int32Type)
|
|
|
|
PtrInt64Type = reflect.PtrTo(Int64Type)
|
|
|
|
|
|
|
|
PtrUintType = reflect.PtrTo(UintType)
|
|
|
|
PtrUint8Type = reflect.PtrTo(Uint8Type)
|
|
|
|
PtrUint16Type = reflect.PtrTo(Uint16Type)
|
|
|
|
PtrUint32Type = reflect.PtrTo(Uint32Type)
|
|
|
|
PtrUint64Type = reflect.PtrTo(Uint64Type)
|
|
|
|
|
|
|
|
PtrFloat32Type = reflect.PtrTo(Float32Type)
|
|
|
|
PtrFloat64Type = reflect.PtrTo(Float64Type)
|
|
|
|
|
|
|
|
PtrComplex64Type = reflect.PtrTo(Complex64Type)
|
|
|
|
PtrComplex128Type = reflect.PtrTo(Complex128Type)
|
|
|
|
|
|
|
|
PtrStringType = reflect.PtrTo(StringType)
|
|
|
|
PtrBoolType = reflect.PtrTo(BoolType)
|
|
|
|
PtrByteType = reflect.PtrTo(ByteType)
|
|
|
|
|
|
|
|
PtrTimeType = reflect.PtrTo(TimeType)
|
|
|
|
)
|
|
|
|
|
|
|
|
// Type2SQLType generate SQLType acorrding Go's type
|
|
|
|
func Type2SQLType(t reflect.Type) (st SQLType) {
|
|
|
|
switch k := t.Kind(); k {
|
2021-05-14 19:17:06 +00:00
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
|
2016-11-03 22:16:01 +00:00
|
|
|
st = SQLType{Int, 0, 0}
|
2021-05-14 19:17:06 +00:00
|
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
|
|
|
|
st = SQLType{UnsignedInt, 0, 0}
|
|
|
|
case reflect.Int64:
|
2016-11-03 22:16:01 +00:00
|
|
|
st = SQLType{BigInt, 0, 0}
|
2021-05-14 19:17:06 +00:00
|
|
|
case reflect.Uint64:
|
|
|
|
st = SQLType{UnsignedBigInt, 0, 0}
|
2016-11-03 22:16:01 +00:00
|
|
|
case reflect.Float32:
|
|
|
|
st = SQLType{Float, 0, 0}
|
|
|
|
case reflect.Float64:
|
|
|
|
st = SQLType{Double, 0, 0}
|
|
|
|
case reflect.Complex64, reflect.Complex128:
|
|
|
|
st = SQLType{Varchar, 64, 0}
|
|
|
|
case reflect.Array, reflect.Slice, reflect.Map:
|
2021-05-14 19:17:06 +00:00
|
|
|
if t.Elem() == reflect.TypeOf(byteDefault) {
|
2016-11-03 22:16:01 +00:00
|
|
|
st = SQLType{Blob, 0, 0}
|
|
|
|
} else {
|
|
|
|
st = SQLType{Text, 0, 0}
|
|
|
|
}
|
|
|
|
case reflect.Bool:
|
|
|
|
st = SQLType{Bool, 0, 0}
|
|
|
|
case reflect.String:
|
|
|
|
st = SQLType{Varchar, 255, 0}
|
|
|
|
case reflect.Struct:
|
|
|
|
if t.ConvertibleTo(TimeType) {
|
|
|
|
st = SQLType{DateTime, 0, 0}
|
|
|
|
} else {
|
|
|
|
// TODO need to handle association struct
|
|
|
|
st = SQLType{Text, 0, 0}
|
|
|
|
}
|
|
|
|
case reflect.Ptr:
|
|
|
|
st = Type2SQLType(t.Elem())
|
|
|
|
default:
|
|
|
|
st = SQLType{Text, 0, 0}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-05-14 19:17:06 +00:00
|
|
|
// SQLType2Type convert default sql type change to go types
|
2016-11-03 22:16:01 +00:00
|
|
|
func SQLType2Type(st SQLType) reflect.Type {
|
|
|
|
name := strings.ToUpper(st.Name)
|
|
|
|
switch name {
|
|
|
|
case Bit, TinyInt, SmallInt, MediumInt, Int, Integer, Serial:
|
|
|
|
return reflect.TypeOf(1)
|
|
|
|
case BigInt, BigSerial:
|
|
|
|
return reflect.TypeOf(int64(1))
|
|
|
|
case Float, Real:
|
|
|
|
return reflect.TypeOf(float32(1))
|
|
|
|
case Double:
|
|
|
|
return reflect.TypeOf(float64(1))
|
2019-06-23 15:22:43 +00:00
|
|
|
case Char, NChar, Varchar, NVarchar, TinyText, Text, NText, MediumText, LongText, Enum, Set, Uuid, Clob, SysName:
|
2016-11-03 22:16:01 +00:00
|
|
|
return reflect.TypeOf("")
|
2018-07-20 02:10:17 +00:00
|
|
|
case TinyBlob, Blob, LongBlob, Bytea, Binary, MediumBlob, VarBinary, UniqueIdentifier:
|
2016-11-03 22:16:01 +00:00
|
|
|
return reflect.TypeOf([]byte{})
|
|
|
|
case Bool:
|
|
|
|
return reflect.TypeOf(true)
|
2019-09-29 12:52:39 +00:00
|
|
|
case DateTime, Date, Time, TimeStamp, TimeStampz, SmallDateTime, Year:
|
2021-05-14 19:17:06 +00:00
|
|
|
return reflect.TypeOf(timeDefault)
|
2019-06-23 15:22:43 +00:00
|
|
|
case Decimal, Numeric, Money, SmallMoney:
|
2016-11-03 22:16:01 +00:00
|
|
|
return reflect.TypeOf("")
|
|
|
|
default:
|
|
|
|
return reflect.TypeOf("")
|
|
|
|
}
|
|
|
|
}
|