diff --git a/circle.yml b/circle.yml index 8faa627d..c281a6a2 100644 --- a/circle.yml +++ b/circle.yml @@ -3,6 +3,8 @@ dependencies: # './...' is a relative pattern which means all subdirectories - go get -t -d -v ./... - go get -t -d -v github.com/go-xorm/tests + - go get -u github.com/go-xorm/core + - go get -u github.com/go-xorm/builder - go build -v database: @@ -20,6 +22,8 @@ test: override: # './...' is a relative pattern which means all subdirectories - go test -v -race + - go test -v -race -db=mysql -conn_str="root:@/xorm_test" + - go test -v -race -db=postgres -conn_str="dbname=xorm_test sslmode=disable" - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./sqlite3.sh - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./mysql.sh - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./postgres.sh \ No newline at end of file diff --git a/dialect_mysql.go b/dialect_mysql.go index 55cfdd76..99100b23 100644 --- a/dialect_mysql.go +++ b/dialect_mysql.go @@ -299,7 +299,7 @@ func (db *mysql) TableCheckSql(tableName string) (string, []interface{}) { func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column, error) { args := []interface{}{db.DbName, tableName} s := "SELECT `COLUMN_NAME`, `IS_NULLABLE`, `COLUMN_DEFAULT`, `COLUMN_TYPE`," + - " `COLUMN_KEY`, `EXTRA` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?" + " `COLUMN_KEY`, `EXTRA`,`COLUMN_COMMENT` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?" db.LogSQL(s, args) rows, err := db.DB().Query(s, args...) @@ -314,13 +314,14 @@ func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column col := new(core.Column) col.Indexes = make(map[string]int) - var columnName, isNullable, colType, colKey, extra string + var columnName, isNullable, colType, colKey, extra, comment string var colDefault *string - err = rows.Scan(&columnName, &isNullable, &colDefault, &colType, &colKey, &extra) + err = rows.Scan(&columnName, &isNullable, &colDefault, &colType, &colKey, &extra, &comment) if err != nil { return nil, nil, err } col.Name = strings.Trim(columnName, "` ") + col.Comment = comment if "YES" == isNullable { col.Nullable = true } @@ -407,7 +408,7 @@ func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column func (db *mysql) GetTables() ([]*core.Table, error) { args := []interface{}{db.DbName} - s := "SELECT `TABLE_NAME`, `ENGINE`, `TABLE_ROWS`, `AUTO_INCREMENT` from " + + s := "SELECT `TABLE_NAME`, `ENGINE`, `TABLE_ROWS`, `AUTO_INCREMENT`, `TABLE_COMMENT` from " + "`INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? AND (`ENGINE`='MyISAM' OR `ENGINE` = 'InnoDB' OR `ENGINE` = 'TokuDB')" db.LogSQL(s, args) @@ -420,14 +421,15 @@ func (db *mysql) GetTables() ([]*core.Table, error) { tables := make([]*core.Table, 0) for rows.Next() { table := core.NewEmptyTable() - var name, engine, tableRows string + var name, engine, tableRows, comment string var autoIncr *string - err = rows.Scan(&name, &engine, &tableRows, &autoIncr) + err = rows.Scan(&name, &engine, &tableRows, &autoIncr, &comment) if err != nil { return nil, err } table.Name = name + table.Comment = comment table.StoreEngine = engine tables = append(tables, table) } diff --git a/engine.go b/engine.go index f25d7cb2..5e8d0af9 100644 --- a/engine.go +++ b/engine.go @@ -1007,6 +1007,10 @@ func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) { col = core.NewColumn(engine.ColumnMapper.Obj2Table(t.Field(i).Name), t.Field(i).Name, sqlType, sqlType.DefaultLength, sqlType.DefaultLength2, true) + + if fieldType.Kind() == reflect.Int64 && (strings.ToUpper(col.FieldName) == "ID" || strings.HasSuffix(strings.ToUpper(col.FieldName), ".ID")) { + idFieldColName = col.Name + } } if col.IsAutoIncrement { col.Nullable = false @@ -1014,9 +1018,6 @@ func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) { table.AddColumn(col) - if fieldType.Kind() == reflect.Int64 && (strings.ToUpper(col.FieldName) == "ID" || strings.HasSuffix(strings.ToUpper(col.FieldName), ".ID")) { - idFieldColName = col.Name - } } // end for if idFieldColName != "" && len(table.PrimaryKeys) == 0 { @@ -1291,18 +1292,6 @@ func (engine *Engine) Sync2(beans ...interface{}) error { return s.Sync2(beans...) } -func (engine *Engine) unMap(beans ...interface{}) (e error) { - engine.mutex.Lock() - defer engine.mutex.Unlock() - for _, bean := range beans { - t := rType(bean) - if _, ok := engine.Tables[t]; ok { - delete(engine.Tables, t) - } - } - return -} - // Drop all mapped table func (engine *Engine) dropAll() error { session := engine.NewSession() diff --git a/engine_test.go b/engine_test.go new file mode 100644 index 00000000..fcd3953c --- /dev/null +++ b/engine_test.go @@ -0,0 +1,59 @@ +// Copyright 2017 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. + +package xorm + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAutoIncrTag(t *testing.T) { + assert.NoError(t, prepareEngine()) + + type TestAutoIncr1 struct { + Id int64 + } + + tb := testEngine.TableInfo(new(TestAutoIncr1)) + cols := tb.Columns() + assert.EqualValues(t, 1, len(cols)) + assert.True(t, cols[0].IsAutoIncrement) + assert.True(t, cols[0].IsPrimaryKey) + assert.Equal(t, "id", cols[0].Name) + + type TestAutoIncr2 struct { + Id int64 `xorm:"id"` + } + + tb = testEngine.TableInfo(new(TestAutoIncr2)) + cols = tb.Columns() + assert.EqualValues(t, 1, len(cols)) + assert.False(t, cols[0].IsAutoIncrement) + assert.False(t, cols[0].IsPrimaryKey) + assert.Equal(t, "id", cols[0].Name) + + type TestAutoIncr3 struct { + Id int64 `xorm:"'ID'"` + } + + tb = testEngine.TableInfo(new(TestAutoIncr3)) + cols = tb.Columns() + assert.EqualValues(t, 1, len(cols)) + assert.False(t, cols[0].IsAutoIncrement) + assert.False(t, cols[0].IsPrimaryKey) + assert.Equal(t, "ID", cols[0].Name) + + type TestAutoIncr4 struct { + Id int64 `xorm:"pk"` + } + + tb = testEngine.TableInfo(new(TestAutoIncr4)) + cols = tb.Columns() + assert.EqualValues(t, 1, len(cols)) + assert.False(t, cols[0].IsAutoIncrement) + assert.True(t, cols[0].IsPrimaryKey) + assert.Equal(t, "id", cols[0].Name) +} diff --git a/helpers.go b/helpers.go index 324c5bea..bac1fd9c 100644 --- a/helpers.go +++ b/helpers.go @@ -12,7 +12,6 @@ import ( "strconv" "strings" "time" - "github.com/go-xorm/core" ) @@ -196,25 +195,43 @@ func isArrayValueZero(v reflect.Value) bool { func int64ToIntValue(id int64, tp reflect.Type) reflect.Value { var v interface{} - switch tp.Kind() { - case reflect.Int16: - v = int16(id) - case reflect.Int32: - v = int32(id) - case reflect.Int: - v = int(id) - case reflect.Int64: - v = id - case reflect.Uint16: - v = uint16(id) - case reflect.Uint32: - v = uint32(id) - case reflect.Uint64: - v = uint64(id) - case reflect.Uint: - v = uint(id) + kind := tp.Kind() + + if kind == reflect.Ptr { + kind = tp.Elem().Kind() } - return reflect.ValueOf(v).Convert(tp) + + switch kind { + case reflect.Int16: + temp := int16(id) + v = &temp + case reflect.Int32: + temp := int32(id) + v = &temp + case reflect.Int: + temp := int(id) + v = &temp + case reflect.Int64: + temp := id + v = &temp + case reflect.Uint16: + temp := uint16(id) + v = &temp + case reflect.Uint32: + temp := uint32(id) + v = &temp + case reflect.Uint64: + temp := uint64(id) + v = &temp + case reflect.Uint: + temp := uint(id) + v = &temp + } + + if tp.Kind() == reflect.Ptr { + return reflect.ValueOf(v).Convert(tp) + } + return reflect.ValueOf(v).Elem().Convert(tp) } func int64ToInt(id int64, tp reflect.Type) interface{} { @@ -537,6 +554,10 @@ func genCols(table *core.Table, session *Session, bean interface{}, useCol bool, if len(fieldValue.String()) == 0 { continue } + case reflect.Ptr: + if fieldValue.Pointer() == 0 { + continue + } } } diff --git a/session_insert_test.go b/session_insert_test.go index b58d9bdb..f0d26007 100644 --- a/session_insert_test.go +++ b/session_insert_test.go @@ -104,3 +104,35 @@ func callbackLooper(datas interface{}, step int, actionFunc func(interface{}) er } return } + +func TestInsertOneIfPkIsPoint(t *testing.T) { + assert.NoError(t, prepareEngine()) + + type TestPoint struct { + Id *int64 `xorm:"autoincr pk notnull 'id'"` + Msg *string `xorm:"varchar(255)"` + Created *time.Time `xorm:"created"` + } + + assert.NoError(t, testEngine.Sync2(new(TestPoint))) + msg := "hi" + data := TestPoint{Msg: &msg} + _, err := testEngine.InsertOne(&data) + assert.NoError(t, err) +} + +func TestInsertOneIfPkIsPointRename(t *testing.T) { + assert.NoError(t, prepareEngine()) + type ID *int64 + type TestPoint struct { + Id ID `xorm:"autoincr pk notnull 'id'"` + Msg *string `xorm:"varchar(255)"` + Created *time.Time `xorm:"created"` + } + + assert.NoError(t, testEngine.Sync2(new(TestPoint))) + msg := "hi" + data := TestPoint{Msg: &msg} + _, err := testEngine.InsertOne(&data) + assert.NoError(t, err) +} diff --git a/types_test.go b/types_test.go index f5a51679..900dac90 100644 --- a/types_test.go +++ b/types_test.go @@ -77,7 +77,7 @@ func TestGetBytes(t *testing.T) { assert.NoError(t, prepareEngine()) type Varbinary struct { - Data []byte `xorm:"VARBINARY"` + Data []byte `xorm:"VARBINARY(250)"` } err := testEngine.Sync2(new(Varbinary)) diff --git a/xorm.go b/xorm.go index c22c1b65..63cb15a6 100644 --- a/xorm.go +++ b/xorm.go @@ -17,7 +17,7 @@ import ( const ( // Version show the xorm's version - Version string = "0.6.2.0412" + Version string = "0.6.2.0517" ) func regDrvsNDialects() bool {