Fix DBMetas returned unsigned tinyint #2017

Merged
lunny merged 4 commits from lunny/fix_unsigned_tinyint into master 2021-07-29 03:04:43 +00:00
8 changed files with 96 additions and 26 deletions

View File

@ -318,7 +318,7 @@ func (db *mssql) SQLType(c *schemas.Column) string {
case schemas.TimeStampz: case schemas.TimeStampz:
res = "DATETIMEOFFSET" res = "DATETIMEOFFSET"
c.Length = 7 c.Length = 7
case schemas.MediumInt: case schemas.MediumInt, schemas.TinyInt, schemas.SmallInt, schemas.UnsignedMediumInt, schemas.UnsignedTinyInt, schemas.UnsignedSmallInt:
res = schemas.Int res = schemas.Int
case schemas.Text, schemas.MediumText, schemas.TinyText, schemas.LongText, schemas.Json: case schemas.Text, schemas.MediumText, schemas.TinyText, schemas.LongText, schemas.Json:
res = db.defaultVarchar + "(MAX)" res = db.defaultVarchar + "(MAX)"

View File

@ -263,6 +263,7 @@ func (db *mysql) SetParams(params map[string]string) {
func (db *mysql) SQLType(c *schemas.Column) string { func (db *mysql) SQLType(c *schemas.Column) string {
var res string var res string
var isUnsigned bool
switch t := c.SQLType.Name; t { switch t := c.SQLType.Name; t {
case schemas.Bool: case schemas.Bool:
res = schemas.TinyInt res = schemas.TinyInt
@ -309,8 +310,19 @@ func (db *mysql) SQLType(c *schemas.Column) string {
res = schemas.Text res = schemas.Text
case schemas.UnsignedInt: case schemas.UnsignedInt:
res = schemas.Int res = schemas.Int
isUnsigned = true
case schemas.UnsignedBigInt: case schemas.UnsignedBigInt:
res = schemas.BigInt res = schemas.BigInt
isUnsigned = true
case schemas.UnsignedMediumInt:
res = schemas.MediumInt
isUnsigned = true
case schemas.UnsignedSmallInt:
res = schemas.SmallInt
isUnsigned = true
case schemas.UnsignedTinyInt:
res = schemas.TinyInt
isUnsigned = true
default: default:
res = t res = t
} }
@ -329,7 +341,7 @@ func (db *mysql) SQLType(c *schemas.Column) string {
res += "(" + strconv.Itoa(c.Length) + ")" res += "(" + strconv.Itoa(c.Length) + ")"
} }
if c.SQLType.Name == schemas.UnsignedBigInt || c.SQLType.Name == schemas.UnsignedInt { if isUnsigned {
res += " UNSIGNED" res += " UNSIGNED"
} }

View File

@ -879,13 +879,13 @@ func (db *postgres) SetQuotePolicy(quotePolicy QuotePolicy) {
func (db *postgres) SQLType(c *schemas.Column) string { func (db *postgres) SQLType(c *schemas.Column) string {
var res string var res string
switch t := c.SQLType.Name; t { switch t := c.SQLType.Name; t {
case schemas.TinyInt: case schemas.TinyInt, schemas.UnsignedTinyInt:
res = schemas.SmallInt res = schemas.SmallInt
return res return res
case schemas.Bit: case schemas.Bit:
res = schemas.Boolean res = schemas.Boolean
return res return res
case schemas.MediumInt, schemas.Int, schemas.Integer: case schemas.MediumInt, schemas.Int, schemas.Integer, schemas.UnsignedMediumInt, schemas.UnsignedSmallInt:
if c.IsAutoIncrement { if c.IsAutoIncrement {
return schemas.Serial return schemas.Serial
} }

View File

@ -217,8 +217,9 @@ func (db *sqlite3) SQLType(c *schemas.Column) string {
case schemas.Char, schemas.Varchar, schemas.NVarchar, schemas.TinyText, case schemas.Char, schemas.Varchar, schemas.NVarchar, schemas.TinyText,
schemas.Text, schemas.MediumText, schemas.LongText, schemas.Json: schemas.Text, schemas.MediumText, schemas.LongText, schemas.Json:
return schemas.Text return schemas.Text
case schemas.Bit, schemas.TinyInt, schemas.SmallInt, schemas.MediumInt, schemas.Int, schemas.Integer, schemas.BigInt, case schemas.Bit, schemas.TinyInt, schemas.UnsignedTinyInt, schemas.SmallInt,
schemas.UnsignedBigInt, schemas.UnsignedInt: schemas.UnsignedSmallInt, schemas.MediumInt, schemas.Int, schemas.UnsignedInt,
schemas.BigInt, schemas.UnsignedBigInt, schemas.Integer:
return schemas.Integer return schemas.Integer
case schemas.Float, schemas.Double, schemas.Real: case schemas.Float, schemas.Double, schemas.Real:
return schemas.Real return schemas.Real

View File

@ -493,6 +493,45 @@ func TestUnsignedUint32(t *testing.T) {
assert.EqualValues(t, uint64(math.MaxUint32), v.Id) assert.EqualValues(t, uint64(math.MaxUint32), v.Id)
} }
func TestUnsignedTinyInt(t *testing.T) {
type MyUnsignedTinyIntStruct struct {
Id uint8 `xorm:"unsigned tinyint"`
}
assert.NoError(t, PrepareEngine())
assertSync(t, new(MyUnsignedTinyIntStruct))
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 TINYINT", tables[0].Columns()[0].SQLType.Name)
case schemas.POSTGRES:
assert.EqualValues(t, "SMALLINT", tables[0].Columns()[0].SQLType.Name)
case schemas.MSSQL:
assert.EqualValues(t, "INT", tables[0].Columns()[0].SQLType.Name)
default:
assert.False(t, true, "Unsigned is not implemented")
}
cnt, err := testEngine.Insert(&MyUnsignedTinyIntStruct{
Id: math.MaxUint8,
})
assert.NoError(t, err)
assert.EqualValues(t, 1, cnt)
var v MyUnsignedTinyIntStruct
has, err := testEngine.Get(&v)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, uint64(math.MaxUint32), v.Id)
}
type MyDecimal big.Int type MyDecimal big.Int
func (d *MyDecimal) FromDB(data []byte) error { func (d *MyDecimal) FromDB(data []byte) error {

View File

@ -92,16 +92,19 @@ func (s *SQLType) IsXML() bool {
// enumerates all the database column types // enumerates all the database column types
var ( var (
Bit = "BIT" Bit = "BIT"
UnsignedBit = "UNSIGNED BIT" UnsignedBit = "UNSIGNED BIT"
TinyInt = "TINYINT" TinyInt = "TINYINT"
SmallInt = "SMALLINT" UnsignedTinyInt = "UNSIGNED TINYINT"
MediumInt = "MEDIUMINT" SmallInt = "SMALLINT"
Int = "INT" UnsignedSmallInt = "UNSIGNED SMALLINT"
UnsignedInt = "UNSIGNED INT" MediumInt = "MEDIUMINT"
Integer = "INTEGER" UnsignedMediumInt = "UNSIGNED MEDIUMINT"
BigInt = "BIGINT" Int = "INT"
UnsignedBigInt = "UNSIGNED BIGINT" UnsignedInt = "UNSIGNED INT"
Integer = "INTEGER"
BigInt = "BIGINT"
UnsignedBigInt = "UNSIGNED BIGINT"
Enum = "ENUM" Enum = "ENUM"
Set = "SET" Set = "SET"
@ -158,16 +161,19 @@ var (
Array = "ARRAY" Array = "ARRAY"
SqlTypes = map[string]int{ SqlTypes = map[string]int{
Bit: NUMERIC_TYPE, Bit: NUMERIC_TYPE,
UnsignedBit: NUMERIC_TYPE, UnsignedBit: NUMERIC_TYPE,
TinyInt: NUMERIC_TYPE, TinyInt: NUMERIC_TYPE,
SmallInt: NUMERIC_TYPE, UnsignedTinyInt: NUMERIC_TYPE,
MediumInt: NUMERIC_TYPE, SmallInt: NUMERIC_TYPE,
Int: NUMERIC_TYPE, UnsignedSmallInt: NUMERIC_TYPE,
UnsignedInt: NUMERIC_TYPE, MediumInt: NUMERIC_TYPE,
Integer: NUMERIC_TYPE, UnsignedMediumInt: NUMERIC_TYPE,
BigInt: NUMERIC_TYPE, Int: NUMERIC_TYPE,
UnsignedBigInt: NUMERIC_TYPE, UnsignedInt: NUMERIC_TYPE,
Integer: NUMERIC_TYPE,
BigInt: NUMERIC_TYPE,
UnsignedBigInt: NUMERIC_TYPE,
Enum: TEXT_TYPE, Enum: TEXT_TYPE,
Set: TEXT_TYPE, Set: TEXT_TYPE,

View File

@ -217,6 +217,10 @@ func (parser *Parser) parseFieldWithTags(table *schemas.Table, fieldIndex int, f
if col.SQLType.Name == "" { if col.SQLType.Name == "" {
col.SQLType = schemas.Type2SQLType(field.Type) col.SQLType = schemas.Type2SQLType(field.Type)
} }
if ctx.isUnsigned && col.SQLType.IsNumeric() && !strings.HasPrefix(col.SQLType.Name, "UNSIGNED") {
col.SQLType.Name = "UNSIGNED " + col.SQLType.Name
}
parser.dialect.SQLType(col) parser.dialect.SQLType(col)
if col.Length == 0 { if col.Length == 0 {
col.Length = col.SQLType.DefaultLength col.Length = col.SQLType.DefaultLength

View File

@ -93,6 +93,7 @@ type Context struct {
hasCacheTag bool hasCacheTag bool
hasNoCacheTag bool hasNoCacheTag bool
ignoreNext bool ignoreNext bool
isUnsigned bool
} }
// Handler describes tag handler for XORM // Handler describes tag handler for XORM
@ -122,6 +123,7 @@ var (
"NOCACHE": NoCacheTagHandler, "NOCACHE": NoCacheTagHandler,
"COMMENT": CommentTagHandler, "COMMENT": CommentTagHandler,
"EXTENDS": ExtendsTagHandler, "EXTENDS": ExtendsTagHandler,
"UNSIGNED": UnsignedTagHandler,
} }
) )
@ -268,6 +270,12 @@ func UniqueTagHandler(ctx *Context) error {
return nil return nil
} }
// UnsignedTagHandler represents the column is unsigned
func UnsignedTagHandler(ctx *Context) error {
ctx.isUnsigned = true
return nil
}
// CommentTagHandler add comment to column // CommentTagHandler add comment to column
func CommentTagHandler(ctx *Context) error { func CommentTagHandler(ctx *Context) error {
if len(ctx.params) > 0 { if len(ctx.params) > 0 {