diff --git a/dialects/mssql.go b/dialects/mssql.go index 083fb65d..15d1cd06 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -284,7 +284,7 @@ func (db *mssql) SQLType(c *schemas.Column) string { case schemas.TimeStampz: res = "DATETIMEOFFSET" c.Length = 7 - case schemas.MediumInt: + case schemas.MediumInt, schemas.UnsignedInt: res = schemas.Int case schemas.Text, schemas.MediumText, schemas.TinyText, schemas.LongText, schemas.Json: res = db.defaultVarchar + "(MAX)" @@ -296,7 +296,7 @@ func (db *mssql) SQLType(c *schemas.Column) string { case schemas.TinyInt: res = schemas.TinyInt c.Length = 0 - case schemas.BigInt: + case schemas.BigInt, schemas.UnsignedBigInt: res = schemas.BigInt c.Length = 0 case schemas.NVarchar: diff --git a/dialects/mysql.go b/dialects/mysql.go index 769e30b1..2b530daf 100644 --- a/dialects/mysql.go +++ b/dialects/mysql.go @@ -254,6 +254,10 @@ func (db *mysql) SQLType(c *schemas.Column) string { c.Length = 40 case schemas.Json: res = schemas.Text + case schemas.UnsignedInt: + res = schemas.Int + case schemas.UnsignedBigInt: + res = schemas.BigInt default: res = t } @@ -271,6 +275,11 @@ func (db *mysql) SQLType(c *schemas.Column) string { } else if hasLen1 { res += "(" + strconv.Itoa(c.Length) + ")" } + + if c.SQLType.Name == schemas.UnsignedBigInt || c.SQLType.Name == schemas.UnsignedInt { + res += " UNSIGNED" + } + return res } @@ -331,16 +340,16 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName col := new(schemas.Column) col.Indexes = make(map[string]int) - var columnName, isNullable, colType, colKey, extra, comment string - var alreadyQuoted bool + var columnName, nullableStr, colType, colKey, extra, comment string + var alreadyQuoted, isUnsigned bool var colDefault *string - err = rows.Scan(&columnName, &isNullable, &colDefault, &colType, &colKey, &extra, &comment, &alreadyQuoted) + err = rows.Scan(&columnName, &nullableStr, &colDefault, &colType, &colKey, &extra, &comment, &alreadyQuoted) if err != nil { return nil, nil, err } col.Name = strings.Trim(columnName, "` ") col.Comment = comment - if "YES" == isNullable { + if nullableStr == "YES" { col.Nullable = true } @@ -351,6 +360,11 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName col.DefaultIsEmpty = true } + fields := strings.Fields(colType) + if len(fields) == 2 && fields[1] == "unsigned" { + isUnsigned = true + } + colType = fields[0] cts := strings.Split(colType, "(") colName := cts[0] // Remove the /* mariadb-5.3 */ suffix from coltypes @@ -389,11 +403,8 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName } } } - if colType == "FLOAT UNSIGNED" { - colType = "FLOAT" - } - if colType == "DOUBLE UNSIGNED" { - colType = "DOUBLE" + if isUnsigned { + colType = "UNSIGNED " + colType } col.Length = len1 col.Length2 = len2 diff --git a/dialects/postgres.go b/dialects/postgres.go index a2c0de74..2b234c66 100644 --- a/dialects/postgres.go +++ b/dialects/postgres.go @@ -833,12 +833,12 @@ func (db *postgres) SQLType(c *schemas.Column) string { case schemas.Bit: res = schemas.Boolean return res - case schemas.MediumInt, schemas.Int, schemas.Integer: + case schemas.MediumInt, schemas.Int, schemas.Integer, schemas.UnsignedInt: if c.IsAutoIncrement { return schemas.Serial } return schemas.Integer - case schemas.BigInt: + case schemas.BigInt, schemas.UnsignedBigInt: if c.IsAutoIncrement { return schemas.BigSerial } @@ -1052,6 +1052,10 @@ WHERE n.nspname= s.table_schema AND c.relkind = 'r'::char AND c.relname = $1%s A } } + if colDefault != nil && *colDefault == "unique_rowid()" { // ignore the system column added by cockroach + continue + } + col.Name = strings.Trim(colName, `" `) if colDefault != nil { diff --git a/dialects/sqlite3.go b/dialects/sqlite3.go index 62a38397..82683606 100644 --- a/dialects/sqlite3.go +++ b/dialects/sqlite3.go @@ -193,7 +193,8 @@ func (db *sqlite3) SQLType(c *schemas.Column) string { case schemas.Char, schemas.Varchar, schemas.NVarchar, schemas.TinyText, schemas.Text, schemas.MediumText, schemas.LongText, schemas.Json: return schemas.Text - case schemas.Bit, schemas.TinyInt, schemas.SmallInt, schemas.MediumInt, schemas.Int, schemas.Integer, schemas.BigInt: + case schemas.Bit, schemas.TinyInt, schemas.SmallInt, schemas.MediumInt, schemas.Int, schemas.Integer, schemas.BigInt, + schemas.UnsignedBigInt, schemas.UnsignedInt: return schemas.Integer case schemas.Float, schemas.Double, schemas.Real: return schemas.Real diff --git a/go.mod b/go.mod index b9eec3a0..5e073207 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ module xorm.io/xorm -go 1.11 +go 1.13 require ( - github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc + github.com/denisenkom/go-mssqldb v0.9.0 github.com/go-sql-driver/mysql v1.5.0 github.com/lib/pq v1.7.0 github.com/mattn/go-sqlite3 v1.14.6 diff --git a/go.sum b/go.sum index 7c72c699..230c16aa 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGq gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg= -github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk= +github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= diff --git a/integrations/types_test.go b/integrations/types_test.go index 112308f3..d0357d6b 100644 --- a/integrations/types_test.go +++ b/integrations/types_test.go @@ -375,3 +375,30 @@ func TestCustomType2(t *testing.T) { fmt.Println(users) } + +func TestUnsigned(t *testing.T) { + type MyUnsignedStruct struct { + Id uint64 + } + + assert.NoError(t, PrepareEngine()) + assertSync(t, new(MyUnsignedStruct)) + + tables, err := testEngine.DBMetas() + assert.NoError(t, err) + assert.EqualValues(t, 1, len(tables)) + assert.EqualValues(t, 1, len(tables[0].Columns())) + + switch testEngine.Dialect().URI().DBType { + case schemas.SQLITE: + assert.EqualValues(t, "INTEGER", tables[0].Columns()[0].SQLType.Name) + case schemas.MYSQL: + assert.EqualValues(t, "UNSIGNED BIGINT", tables[0].Columns()[0].SQLType.Name) + case schemas.POSTGRES: + assert.EqualValues(t, "BIGINT", tables[0].Columns()[0].SQLType.Name) + case schemas.MSSQL: + assert.EqualValues(t, "BIGINT", tables[0].Columns()[0].SQLType.Name) + default: + assert.False(t, true, "Unsigned is not implemented") + } +} diff --git a/schemas/type.go b/schemas/type.go index f0ede296..6b50d184 100644 --- a/schemas/type.go +++ b/schemas/type.go @@ -73,13 +73,16 @@ func (s *SQLType) IsXML() bool { } var ( - Bit = "BIT" - TinyInt = "TINYINT" - SmallInt = "SMALLINT" - MediumInt = "MEDIUMINT" - Int = "INT" - Integer = "INTEGER" - BigInt = "BIGINT" + Bit = "BIT" + UnsignedBit = "UNSIGNED BIT" + TinyInt = "TINYINT" + SmallInt = "SMALLINT" + MediumInt = "MEDIUMINT" + Int = "INT" + UnsignedInt = "UNSIGNED INT" + Integer = "INTEGER" + BigInt = "BIGINT" + UnsignedBigInt = "UNSIGNED BIGINT" Enum = "ENUM" Set = "SET" @@ -136,13 +139,16 @@ var ( Array = "ARRAY" SqlTypes = map[string]int{ - Bit: NUMERIC_TYPE, - TinyInt: NUMERIC_TYPE, - SmallInt: NUMERIC_TYPE, - MediumInt: NUMERIC_TYPE, - Int: NUMERIC_TYPE, - Integer: NUMERIC_TYPE, - BigInt: NUMERIC_TYPE, + 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, Enum: TEXT_TYPE, Set: TEXT_TYPE, @@ -280,10 +286,14 @@ var ( // Type2SQLType generate SQLType acorrding Go's type func Type2SQLType(t reflect.Type) (st SQLType) { switch k := t.Kind(); k { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32: + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: st = SQLType{Int, 0, 0} - case reflect.Int64, reflect.Uint64: + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32: + st = SQLType{UnsignedInt, 0, 0} + case reflect.Int64: st = SQLType{BigInt, 0, 0} + case reflect.Uint64: + st = SQLType{UnsignedBigInt, 0, 0} case reflect.Float32: st = SQLType{Float, 0, 0} case reflect.Float64: