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 (
|
2021-08-28 11:15:21 +00:00
|
|
|
"database/sql"
|
|
|
|
"math/big"
|
2016-11-03 22:16:01 +00:00
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2021-05-15 18:32:17 +00:00
|
|
|
// DBType represents a database type
|
2020-03-22 15:12:55 +00:00
|
|
|
type DBType string
|
|
|
|
|
2021-05-15 18:32:17 +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-15 18:32:17 +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
|
2021-08-28 11:15:21 +00:00
|
|
|
BOOL_TYPE
|
2016-11-03 22:16:01 +00:00
|
|
|
)
|
|
|
|
|
2021-05-15 18:32:17 +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-15 18:32:17 +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-15 18:32:17 +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-15 18:32:17 +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-08-28 11:15:21 +00:00
|
|
|
// IsBool returns true if column is a boolean type
|
|
|
|
func (s *SQLType) IsBool() bool {
|
|
|
|
return s.IsType(BOOL_TYPE)
|
|
|
|
}
|
|
|
|
|
2021-05-15 18:32:17 +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-15 18:32:17 +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-15 18:32:17 +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-15 18:32:17 +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-15 18:32:17 +00:00
|
|
|
// enumerates all the database column types
|
2016-11-03 22:16:01 +00:00
|
|
|
var (
|
2021-08-28 11:15:21 +00:00
|
|
|
Bit = "BIT"
|
|
|
|
UnsignedBit = "UNSIGNED BIT"
|
|
|
|
TinyInt = "TINYINT"
|
|
|
|
UnsignedTinyInt = "UNSIGNED TINYINT"
|
|
|
|
SmallInt = "SMALLINT"
|
|
|
|
UnsignedSmallInt = "UNSIGNED SMALLINT"
|
|
|
|
MediumInt = "MEDIUMINT"
|
|
|
|
UnsignedMediumInt = "UNSIGNED 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-08-28 11:15:21 +00:00
|
|
|
Bit: NUMERIC_TYPE,
|
|
|
|
UnsignedBit: NUMERIC_TYPE,
|
|
|
|
TinyInt: NUMERIC_TYPE,
|
|
|
|
UnsignedTinyInt: NUMERIC_TYPE,
|
|
|
|
SmallInt: NUMERIC_TYPE,
|
|
|
|
UnsignedSmallInt: NUMERIC_TYPE,
|
|
|
|
MediumInt: NUMERIC_TYPE,
|
|
|
|
UnsignedMediumInt: 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
|
|
|
|
2021-08-28 11:15:21 +00:00
|
|
|
Bool: BOOL_TYPE,
|
|
|
|
Boolean: BOOL_TYPE,
|
2016-11-03 22:16:01 +00:00
|
|
|
|
|
|
|
Serial: NUMERIC_TYPE,
|
|
|
|
BigSerial: NUMERIC_TYPE,
|
2020-03-22 15:12:55 +00:00
|
|
|
|
2021-08-28 11:15:21 +00:00
|
|
|
"INT8": NUMERIC_TYPE,
|
|
|
|
|
2020-03-22 15:12:55 +00:00
|
|
|
Array: ARRAY_TYPE,
|
2016-11-03 22:16:01 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2021-05-15 18:32:17 +00:00
|
|
|
// enumerates all types
|
2016-11-03 22:16:01 +00:00
|
|
|
var (
|
2021-08-28 11:15:21 +00:00
|
|
|
IntType = reflect.TypeOf((*int)(nil)).Elem()
|
|
|
|
Int8Type = reflect.TypeOf((*int8)(nil)).Elem()
|
|
|
|
Int16Type = reflect.TypeOf((*int16)(nil)).Elem()
|
|
|
|
Int32Type = reflect.TypeOf((*int32)(nil)).Elem()
|
|
|
|
Int64Type = reflect.TypeOf((*int64)(nil)).Elem()
|
|
|
|
|
|
|
|
UintType = reflect.TypeOf((*uint)(nil)).Elem()
|
|
|
|
Uint8Type = reflect.TypeOf((*uint8)(nil)).Elem()
|
|
|
|
Uint16Type = reflect.TypeOf((*uint16)(nil)).Elem()
|
|
|
|
Uint32Type = reflect.TypeOf((*uint32)(nil)).Elem()
|
|
|
|
Uint64Type = reflect.TypeOf((*uint64)(nil)).Elem()
|
|
|
|
|
|
|
|
Float32Type = reflect.TypeOf((*float32)(nil)).Elem()
|
|
|
|
Float64Type = reflect.TypeOf((*float64)(nil)).Elem()
|
|
|
|
|
|
|
|
Complex64Type = reflect.TypeOf((*complex64)(nil)).Elem()
|
|
|
|
Complex128Type = reflect.TypeOf((*complex128)(nil)).Elem()
|
|
|
|
|
|
|
|
StringType = reflect.TypeOf((*string)(nil)).Elem()
|
|
|
|
BoolType = reflect.TypeOf((*bool)(nil)).Elem()
|
|
|
|
ByteType = reflect.TypeOf((*byte)(nil)).Elem()
|
2016-11-03 22:16:01 +00:00
|
|
|
BytesType = reflect.SliceOf(ByteType)
|
|
|
|
|
2021-08-28 11:15:21 +00:00
|
|
|
TimeType = reflect.TypeOf((*time.Time)(nil)).Elem()
|
|
|
|
BigFloatType = reflect.TypeOf((*big.Float)(nil)).Elem()
|
|
|
|
NullFloat64Type = reflect.TypeOf((*sql.NullFloat64)(nil)).Elem()
|
|
|
|
NullStringType = reflect.TypeOf((*sql.NullString)(nil)).Elem()
|
|
|
|
NullInt32Type = reflect.TypeOf((*sql.NullInt32)(nil)).Elem()
|
|
|
|
NullInt64Type = reflect.TypeOf((*sql.NullInt64)(nil)).Elem()
|
|
|
|
NullBoolType = reflect.TypeOf((*sql.NullBool)(nil)).Elem()
|
2016-11-03 22:16:01 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Type2SQLType generate SQLType acorrding Go's type
|
|
|
|
func Type2SQLType(t reflect.Type) (st SQLType) {
|
|
|
|
switch k := t.Kind(); k {
|
2021-05-15 18:32:17 +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-15 18:32:17 +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-15 18:32:17 +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-08-28 11:15:21 +00:00
|
|
|
if t.Elem() == ByteType {
|
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}
|
2021-08-28 11:15:21 +00:00
|
|
|
} else if t.ConvertibleTo(NullFloat64Type) {
|
|
|
|
st = SQLType{Double, 0, 0}
|
|
|
|
} else if t.ConvertibleTo(NullStringType) {
|
|
|
|
st = SQLType{Varchar, 255, 0}
|
|
|
|
} else if t.ConvertibleTo(NullInt32Type) {
|
|
|
|
st = SQLType{Integer, 0, 0}
|
|
|
|
} else if t.ConvertibleTo(NullInt64Type) {
|
|
|
|
st = SQLType{BigInt, 0, 0}
|
|
|
|
} else if t.ConvertibleTo(NullBoolType) {
|
|
|
|
st = SQLType{Boolean, 0, 0}
|
2016-11-03 22:16:01 +00:00
|
|
|
} 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-15 18:32:17 +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:
|
2021-08-28 11:15:21 +00:00
|
|
|
return IntType
|
2016-11-03 22:16:01 +00:00
|
|
|
case BigInt, BigSerial:
|
2021-08-28 11:15:21 +00:00
|
|
|
return Int64Type
|
2016-11-03 22:16:01 +00:00
|
|
|
case Float, Real:
|
2021-08-28 11:15:21 +00:00
|
|
|
return Float32Type
|
2016-11-03 22:16:01 +00:00
|
|
|
case Double:
|
2021-08-28 11:15:21 +00:00
|
|
|
return Float64Type
|
2019-06-23 15:22:43 +00:00
|
|
|
case Char, NChar, Varchar, NVarchar, TinyText, Text, NText, MediumText, LongText, Enum, Set, Uuid, Clob, SysName:
|
2021-08-28 11:15:21 +00:00
|
|
|
return StringType
|
2018-07-20 02:10:17 +00:00
|
|
|
case TinyBlob, Blob, LongBlob, Bytea, Binary, MediumBlob, VarBinary, UniqueIdentifier:
|
2021-08-28 11:15:21 +00:00
|
|
|
return BytesType
|
2016-11-03 22:16:01 +00:00
|
|
|
case Bool:
|
2021-08-28 11:15:21 +00:00
|
|
|
return BoolType
|
2019-09-29 12:52:39 +00:00
|
|
|
case DateTime, Date, Time, TimeStamp, TimeStampz, SmallDateTime, Year:
|
2021-08-28 11:15:21 +00:00
|
|
|
return TimeType
|
2019-06-23 15:22:43 +00:00
|
|
|
case Decimal, Numeric, Money, SmallMoney:
|
2021-08-28 11:15:21 +00:00
|
|
|
return StringType
|
2016-11-03 22:16:01 +00:00
|
|
|
default:
|
2021-08-28 11:15:21 +00:00
|
|
|
return StringType
|
2016-11-03 22:16:01 +00:00
|
|
|
}
|
|
|
|
}
|
2021-08-28 11:15:21 +00:00
|
|
|
|
|
|
|
// SQLTypeName returns sql type name
|
|
|
|
func SQLTypeName(tp string) string {
|
|
|
|
fields := strings.Split(tp, "(")
|
|
|
|
return fields[0]
|
|
|
|
}
|