From 3bb787a2f7de4aebc276545927eef53de042ffaf Mon Sep 17 00:00:00 2001 From: daxiong Date: Thu, 23 Apr 2020 12:57:44 +0000 Subject: [PATCH 01/61] fix GetColumns missing ordinal position (#1660) fix GetColumns missing ordinal position Co-authored-by: zhubo <816078@qq.com> Reviewed-on: https://gitea.com/xorm/xorm/pulls/1660 Reviewed-by: Lunny Xiao --- dialects/mysql.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dialects/mysql.go b/dialects/mysql.go index ac916c89..f9a2e943 100644 --- a/dialects/mysql.go +++ b/dialects/mysql.go @@ -308,7 +308,8 @@ func (db *mysql) AddColumnSQL(tableName string, col *schemas.Column) string { func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { args := []interface{}{db.uri.DBName, tableName} s := "SELECT `COLUMN_NAME`, `IS_NULLABLE`, `COLUMN_DEFAULT`, `COLUMN_TYPE`," + - " `COLUMN_KEY`, `EXTRA`,`COLUMN_COMMENT` 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` = ?" + + " ORDER BY `INFORMATION_SCHEMA`.`COLUMNS`.ORDINAL_POSITION" rows, err := queryer.QueryContext(ctx, s, args...) if err != nil { From 8ebcb8b55799f19d2d5b0968415bf1dcb87a1e96 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 26 Apr 2020 11:34:05 +0000 Subject: [PATCH 02/61] Fix find with another struct (#1666) Fix find with another struct Reviewed-on: https://gitea.com/xorm/xorm/pulls/1666 --- integrations/session_find_test.go | 7 +++++++ internal/statements/pk.go | 1 - session_find.go | 7 +++++-- tags/parser.go | 1 + 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/integrations/session_find_test.go b/integrations/session_find_test.go index 00477235..b9d722ba 100644 --- a/integrations/session_find_test.go +++ b/integrations/session_find_test.go @@ -708,6 +708,13 @@ func TestFindExtends(t *testing.T) { err = testEngine.Find(&results) assert.NoError(t, err) assert.EqualValues(t, 2, len(results)) + + results = make([]FindExtendsA, 0, 2) + err = testEngine.Find(&results, &FindExtendsB{ + ID: 1, + }) + assert.NoError(t, err) + assert.EqualValues(t, 1, len(results)) } func TestFindExtends3(t *testing.T) { diff --git a/internal/statements/pk.go b/internal/statements/pk.go index b6ae0f23..d0787719 100644 --- a/internal/statements/pk.go +++ b/internal/statements/pk.go @@ -64,7 +64,6 @@ func (statement *Statement) ProcessIDParam() error { } if len(statement.RefTable.PrimaryKeys) != len(statement.idParam) { - fmt.Println("=====", statement.RefTable.PrimaryKeys, statement.idParam) return fmt.Errorf("ID condition is error, expect %d primarykeys, there are %d", len(statement.RefTable.PrimaryKeys), len(statement.idParam), diff --git a/session_find.go b/session_find.go index 6fbca695..3bc6a642 100644 --- a/session_find.go +++ b/session_find.go @@ -108,8 +108,11 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) ) if tp == tpStruct { if !session.statement.NoAutoCondition && len(condiBean) > 0 { - var err error - autoCond, err = session.statement.BuildConds(table, condiBean[0], true, true, false, true, addedTableName) + condTable, err := session.engine.tagParser.Parse(reflect.ValueOf(condiBean[0])) + if err != nil { + return err + } + autoCond, err = session.statement.BuildConds(condTable, condiBean[0], true, true, false, true, addedTableName) if err != nil { return err } diff --git a/tags/parser.go b/tags/parser.go index 236d2d46..add30a13 100644 --- a/tags/parser.go +++ b/tags/parser.go @@ -115,6 +115,7 @@ func (parser *Parser) Parse(v reflect.Value) (*schemas.Table, error) { t := v.Type() if t.Kind() == reflect.Ptr { t = t.Elem() + v = v.Elem() } if t.Kind() != reflect.Struct { return nil, ErrUnsupportedType From 55594d1dbeabef08fb516fcec1fc95a72d624f69 Mon Sep 17 00:00:00 2001 From: tmalaher Date: Fri, 8 May 2020 12:13:13 +0000 Subject: [PATCH 03/61] Oracle uses double quotes for quoting table/column/etc. names (#1674) Oracle uses doulbe quotes for quoting table/column/etc. names Reviewed-on: https://gitea.com/xorm/xorm/pulls/1674 Reviewed-by: Lunny Xiao --- dialects/oracle.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dialects/oracle.go b/dialects/oracle.go index 2620b0bb..91eed251 100644 --- a/dialects/oracle.go +++ b/dialects/oracle.go @@ -500,8 +500,8 @@ var ( } oracleQuoter = schemas.Quoter{ - Prefix: '[', - Suffix: ']', + Prefix: '"', + Suffix: '"', IsReserved: schemas.AlwaysReserve, } ) From d485101331f5957067fb83e227e3d5aedcf24f2d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 22 May 2020 02:53:55 +0000 Subject: [PATCH 04/61] chore: improve snakeCasedName performance (#1688) chore: update chore: udpate chore: improve snakeCasedName performance Co-authored-by: Bo-Yi Wu Reviewed-on: https://gitea.com/xorm/xorm/pulls/1688 Reviewed-by: appleboy --- names/mapper.go | 20 +++++++++++++------- names/mapper_test.go | 11 +++++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/names/mapper.go b/names/mapper.go index 4aaf0844..80aa48d5 100644 --- a/names/mapper.go +++ b/names/mapper.go @@ -7,6 +7,7 @@ package names import ( "strings" "sync" + "unsafe" ) // Mapper represents a name convertation between struct's fields name and table's column name @@ -77,19 +78,24 @@ func (m SameMapper) Table2Obj(t string) string { type SnakeMapper struct { } +func b2s(b []byte) string { + return *(*string)(unsafe.Pointer(&b)) +} + func snakeCasedName(name string) string { - newstr := make([]rune, 0) - for idx, chr := range name { - if isUpper := 'A' <= chr && chr <= 'Z'; isUpper { - if idx > 0 { + newstr := make([]byte, 0, len(name)+1) + for i := 0; i < len(name); i++ { + c := name[i] + if isUpper := 'A' <= c && c <= 'Z'; isUpper { + if i > 0 { newstr = append(newstr, '_') } - chr -= ('A' - 'a') + c += 'a' - 'A' } - newstr = append(newstr, chr) + newstr = append(newstr, c) } - return string(newstr) + return b2s(newstr) } func (mapper SnakeMapper) Obj2Table(name string) string { diff --git a/names/mapper_test.go b/names/mapper_test.go index 0edfd2a8..5c6dc5d9 100644 --- a/names/mapper_test.go +++ b/names/mapper_test.go @@ -5,6 +5,7 @@ package names import ( + "strings" "testing" ) @@ -47,3 +48,13 @@ func TestGonicMapperToObj(t *testing.T) { } } } + +func BenchmarkSnakeCasedName(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + + s := strings.Repeat("FooBar", 32) + for i := 0; i < b.N; i++ { + _ = snakeCasedName(s) + } +} From f071e5eb9638d1ffaccf4abe8d49d2b95bcb7551 Mon Sep 17 00:00:00 2001 From: appleboy Date: Sat, 23 May 2020 02:22:08 +0000 Subject: [PATCH 05/61] chore: improve titleCasedName performance (#1691) udpate Signed-off-by: Bo-Yi Wu chore: improve titleCasedName performance Signed-off-by: Bo-Yi Wu Co-authored-by: Bo-Yi Wu Reviewed-on: https://gitea.com/xorm/xorm/pulls/1691 --- names/mapper.go | 15 ++++++++------- names/mapper_test.go | 10 ++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/names/mapper.go b/names/mapper.go index 80aa48d5..79add76e 100644 --- a/names/mapper.go +++ b/names/mapper.go @@ -103,27 +103,28 @@ func (mapper SnakeMapper) Obj2Table(name string) string { } func titleCasedName(name string) string { - newstr := make([]rune, 0) + newstr := make([]byte, 0, len(name)) upNextChar := true name = strings.ToLower(name) - for _, chr := range name { + for i := 0; i < len(name); i++ { + c := name[i] switch { case upNextChar: upNextChar = false - if 'a' <= chr && chr <= 'z' { - chr -= ('a' - 'A') + if 'a' <= c && c <= 'z' { + c -= 'a' - 'A' } - case chr == '_': + case c == '_': upNextChar = true continue } - newstr = append(newstr, chr) + newstr = append(newstr, c) } - return string(newstr) + return b2s(newstr) } func (mapper SnakeMapper) Table2Obj(name string) string { diff --git a/names/mapper_test.go b/names/mapper_test.go index 5c6dc5d9..a39cb569 100644 --- a/names/mapper_test.go +++ b/names/mapper_test.go @@ -58,3 +58,13 @@ func BenchmarkSnakeCasedName(b *testing.B) { _ = snakeCasedName(s) } } + +func BenchmarkTitleCasedName(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + + s := strings.Repeat("foo_bar", 32) + for i := 0; i < b.N; i++ { + _ = titleCasedName(s) + } +} From b08f962d7a7a785fb25108e4128aba6f6f23ec21 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 13 Jun 2020 01:20:25 +0000 Subject: [PATCH 06/61] Fix bug when ID used but no reference table given (#1709) Fix bug when ID used but no reference table given Reviewed-on: https://gitea.com/xorm/xorm/pulls/1709 --- integrations/session_update_test.go | 11 ++++++++++- internal/statements/pk.go | 22 +++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/integrations/session_update_test.go b/integrations/session_update_test.go index 8800246c..1bc1f32a 100644 --- a/integrations/session_update_test.go +++ b/integrations/session_update_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "xorm.io/xorm" + "xorm.io/xorm/internal/statements" "xorm.io/xorm/internal/utils" "xorm.io/xorm/names" ) @@ -39,6 +40,14 @@ func TestUpdateMap(t *testing.T) { }) assert.NoError(t, err) assert.EqualValues(t, 1, cnt) + + cnt, err = testEngine.Table("update_table").ID(tb.Id).Update(map[string]interface{}{ + "name": "test2", + "age": 36, + }) + assert.Error(t, err) + assert.True(t, statements.IsIDConditionWithNoTableErr(err)) + assert.EqualValues(t, 0, cnt) } func TestUpdateLimit(t *testing.T) { @@ -988,7 +997,7 @@ func TestUpdateMapContent(t *testing.T) { assert.EqualValues(t, false, c2.IsMan) assert.EqualValues(t, 2, c2.Gender) - cnt, err = testEngine.Table(testEngine.TableName(new(UpdateMapContent))).ID(c.Id).Update(map[string]interface{}{ + cnt, err = testEngine.Table(new(UpdateMapContent)).ID(c.Id).Update(map[string]interface{}{ "age": 15, "is_man": true, "gender": 1, diff --git a/internal/statements/pk.go b/internal/statements/pk.go index d0787719..59da89c0 100644 --- a/internal/statements/pk.go +++ b/internal/statements/pk.go @@ -20,6 +20,21 @@ var ( uintType = reflect.TypeOf(uint64(0)) ) +// ErrIDConditionWithNoTable represents an error there is no reference table with an ID condition +type ErrIDConditionWithNoTable struct { + ID schemas.PK +} + +func (err ErrIDConditionWithNoTable) Error() string { + return fmt.Sprintf("ID condition %#v need reference table", err.ID) +} + +// IsIDConditionWithNoTableErr return true if the err is ErrIDConditionWithNoTable +func IsIDConditionWithNoTableErr(err error) bool { + _, ok := err.(ErrIDConditionWithNoTable) + return ok +} + // ID generate "where id = ? " statement or for composite key "where key1 = ? and key2 = ?" func (statement *Statement) ID(id interface{}) *Statement { switch t := id.(type) { @@ -58,11 +73,16 @@ func (statement *Statement) ID(id interface{}) *Statement { return statement } +// ProcessIDParam handles the process of id condition func (statement *Statement) ProcessIDParam() error { - if statement.idParam == nil || statement.RefTable == nil { + if statement.idParam == nil { return nil } + if statement.RefTable == nil { + return ErrIDConditionWithNoTable{statement.idParam} + } + if len(statement.RefTable.PrimaryKeys) != len(statement.idParam) { return fmt.Errorf("ID condition is error, expect %d primarykeys, there are %d", len(statement.RefTable.PrimaryKeys), From 4dde8f14e667c49a1c49c41ab72fbbfcc853b758 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 13 Jun 2020 05:31:33 +0000 Subject: [PATCH 07/61] Fix find and count bug (#1651) Fix bug fix mssql findandcount Fix find and count bug Reviewed-on: https://gitea.com/xorm/xorm/pulls/1651 --- engine.go | 70 ------------------------------- integrations/session_find_test.go | 42 ++++++++++++++++++- schemas/column.go | 16 +++++++ schemas/table.go | 49 ++++++++++++++++++++++ session_find.go | 13 ++++-- 5 files changed, 114 insertions(+), 76 deletions(-) diff --git a/engine.go b/engine.go index 7399f41a..b5cb6558 100644 --- a/engine.go +++ b/engine.go @@ -816,81 +816,11 @@ func (engine *Engine) IsTableExist(beanOrTableName interface{}) (bool, error) { return session.IsTableExist(beanOrTableName) } -// IDOf get id from one struct -func (engine *Engine) IDOf(bean interface{}) (schemas.PK, error) { - return engine.IDOfV(reflect.ValueOf(bean)) -} - // TableName returns table name with schema prefix if has func (engine *Engine) TableName(bean interface{}, includeSchema ...bool) string { return dialects.FullTableName(engine.dialect, engine.GetTableMapper(), bean, includeSchema...) } -// IDOfV get id from one value of struct -func (engine *Engine) IDOfV(rv reflect.Value) (schemas.PK, error) { - return engine.idOfV(rv) -} - -func (engine *Engine) idOfV(rv reflect.Value) (schemas.PK, error) { - v := reflect.Indirect(rv) - table, err := engine.tagParser.ParseWithCache(v) - if err != nil { - return nil, err - } - - pk := make([]interface{}, len(table.PrimaryKeys)) - for i, col := range table.PKColumns() { - var err error - - fieldName := col.FieldName - for { - parts := strings.SplitN(fieldName, ".", 2) - if len(parts) == 1 { - break - } - - v = v.FieldByName(parts[0]) - if v.Kind() == reflect.Ptr { - v = v.Elem() - } - if v.Kind() != reflect.Struct { - return nil, ErrUnSupportedType - } - fieldName = parts[1] - } - - pkField := v.FieldByName(fieldName) - switch pkField.Kind() { - case reflect.String: - pk[i], err = engine.idTypeAssertion(col, pkField.String()) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - pk[i], err = engine.idTypeAssertion(col, strconv.FormatInt(pkField.Int(), 10)) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - // id of uint will be converted to int64 - pk[i], err = engine.idTypeAssertion(col, strconv.FormatUint(pkField.Uint(), 10)) - } - - if err != nil { - return nil, err - } - } - return schemas.PK(pk), nil -} - -func (engine *Engine) idTypeAssertion(col *schemas.Column, sid string) (interface{}, error) { - if col.SQLType.IsNumeric() { - n, err := strconv.ParseInt(sid, 10, 64) - if err != nil { - return nil, err - } - return n, nil - } else if col.SQLType.IsText() { - return sid, nil - } else { - return nil, errors.New("not supported") - } -} - // CreateIndexes create indexes func (engine *Engine) CreateIndexes(bean interface{}) error { session := engine.NewSession() diff --git a/integrations/session_find_test.go b/integrations/session_find_test.go index b9d722ba..95cf9384 100644 --- a/integrations/session_find_test.go +++ b/integrations/session_find_test.go @@ -502,10 +502,48 @@ func TestFindAndCountOneFunc(t *testing.T) { assert.EqualValues(t, 1, cnt) results = make([]FindAndCountStruct, 0, 1) - cnt, err = testEngine.Where("msg = ?", true).Limit(1).FindAndCount(&results) + cnt, err = testEngine.Where("1=1").Limit(1).FindAndCount(&results) assert.NoError(t, err) assert.EqualValues(t, 1, len(results)) - assert.EqualValues(t, 1, cnt) + assert.EqualValues(t, 2, cnt) + assert.EqualValues(t, FindAndCountStruct{ + Id: 1, + Content: "111", + Msg: false, + }, results[0]) + + results = make([]FindAndCountStruct, 0, 1) + cnt, err = testEngine.Where("1=1").Limit(1).FindAndCount(&results) + assert.NoError(t, err) + assert.EqualValues(t, 1, len(results)) + assert.EqualValues(t, 2, cnt) + assert.EqualValues(t, FindAndCountStruct{ + Id: 1, + Content: "111", + Msg: false, + }, results[0]) + + results = make([]FindAndCountStruct, 0, 1) + cnt, err = testEngine.Where("1=1").Limit(1, 1).FindAndCount(&results) + assert.NoError(t, err) + assert.EqualValues(t, 1, len(results)) + assert.EqualValues(t, 2, cnt) + assert.EqualValues(t, FindAndCountStruct{ + Id: 2, + Content: "222", + Msg: true, + }, results[0]) + + results = make([]FindAndCountStruct, 0, 1) + cnt, err = testEngine.Where("1=1").Limit(1, 1).FindAndCount(&results) + assert.NoError(t, err) + assert.EqualValues(t, 1, len(results)) + assert.EqualValues(t, 2, cnt) + assert.EqualValues(t, FindAndCountStruct{ + Id: 2, + Content: "222", + Msg: true, + }, results[0]) results = make([]FindAndCountStruct, 0, 1) cnt, err = testEngine.Where("msg = ?", true).Select("id, content, msg"). diff --git a/schemas/column.go b/schemas/column.go index 418629ac..db66a3a6 100644 --- a/schemas/column.go +++ b/schemas/column.go @@ -5,8 +5,10 @@ package schemas import ( + "errors" "fmt" "reflect" + "strconv" "strings" "time" ) @@ -115,3 +117,17 @@ func (col *Column) ValueOfV(dataStruct *reflect.Value) (*reflect.Value, error) { return &fieldValue, nil } + +// ConvertID converts id content to suitable type according column type +func (col *Column) ConvertID(sid string) (interface{}, error) { + if col.SQLType.IsNumeric() { + n, err := strconv.ParseInt(sid, 10, 64) + if err != nil { + return nil, err + } + return n, nil + } else if col.SQLType.IsText() { + return sid, nil + } + return nil, errors.New("not supported") +} diff --git a/schemas/table.go b/schemas/table.go index 38596991..6c57a7e3 100644 --- a/schemas/table.go +++ b/schemas/table.go @@ -5,7 +5,9 @@ package schemas import ( + "fmt" "reflect" + "strconv" "strings" ) @@ -28,6 +30,7 @@ type Table struct { Comment string } +// NewEmptyTable creates an empty table func NewEmptyTable() *Table { return NewTable("", nil) } @@ -44,10 +47,12 @@ func NewTable(name string, t reflect.Type) *Table { } } +// Columns returns table's columns func (table *Table) Columns() []*Column { return table.columns } +// ColumnsSeq returns table's column names according sequence func (table *Table) ColumnsSeq() []string { return table.columnsSeq } @@ -61,6 +66,7 @@ func (table *Table) columnsByName(name string) []*Column { return nil } +// GetColumn returns column according column name, if column not found, return nil func (table *Table) GetColumn(name string) *Column { cols := table.columnsByName(name) if cols != nil { @@ -70,6 +76,7 @@ func (table *Table) GetColumn(name string) *Column { return nil } +// GetColumnIdx returns column according name and idx func (table *Table) GetColumnIdx(name string, idx int) *Column { cols := table.columnsByName(name) if cols != nil && idx < len(cols) { @@ -144,3 +151,45 @@ func (table *Table) AddColumn(col *Column) { func (table *Table) AddIndex(index *Index) { table.Indexes[index.Name] = index } + +// IDOfV get id from one value of struct +func (table *Table) IDOfV(rv reflect.Value) (PK, error) { + v := reflect.Indirect(rv) + pk := make([]interface{}, len(table.PrimaryKeys)) + for i, col := range table.PKColumns() { + var err error + + fieldName := col.FieldName + for { + parts := strings.SplitN(fieldName, ".", 2) + if len(parts) == 1 { + break + } + + v = v.FieldByName(parts[0]) + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + if v.Kind() != reflect.Struct { + return nil, fmt.Errorf("Unsupported read value of column %s from field %s", col.Name, col.FieldName) + } + fieldName = parts[1] + } + + pkField := v.FieldByName(fieldName) + switch pkField.Kind() { + case reflect.String: + pk[i], err = col.ConvertID(pkField.String()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + pk[i], err = col.ConvertID(strconv.FormatInt(pkField.Int(), 10)) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + // id of uint will be converted to int64 + pk[i], err = col.ConvertID(strconv.FormatUint(pkField.Uint(), 10)) + } + + if err != nil { + return nil, err + } + } + return PK(pk), nil +} diff --git a/session_find.go b/session_find.go index 3bc6a642..642093f2 100644 --- a/session_find.go +++ b/session_find.go @@ -60,6 +60,12 @@ func (session *Session) FindAndCount(rowsSlicePtr interface{}, condiBean ...inte if session.statement.OrderStr != "" { session.statement.OrderStr = "" } + if session.statement.LimitN != nil { + session.statement.LimitN = nil + } + if session.statement.Start > 0 { + session.statement.Start = 0 + } // session has stored the conditions so we use `unscoped` to avoid duplicated condition. return session.Unscoped().Count(reflect.New(sliceElementType).Interface()) @@ -320,7 +326,7 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in } var pk schemas.PK = make([]interface{}, len(table.PrimaryKeys)) for i, col := range table.PKColumns() { - pk[i], err = session.engine.idTypeAssertion(col, res[i]) + pk[i], err = col.ConvertID(res[i]) if err != nil { return err } @@ -370,7 +376,7 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in } else { session.engine.logger.Debugf("[cache] cache hit bean: %v, %v, %v", tableName, id, bean) - pk, err := session.engine.IDOf(bean) + pk, err := table.IDOfV(reflect.ValueOf(bean)) if err != nil { return err } @@ -419,7 +425,6 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in if err != nil { return err } - session.statement = statement vs := reflect.Indirect(reflect.ValueOf(beans)) @@ -428,7 +433,7 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in if rv.Kind() != reflect.Ptr { rv = rv.Addr() } - id, err := session.engine.idOfV(rv) + id, err := table.IDOfV(rv) if err != nil { return err } From 08a18027a0caab739b853d3deadce464560c3672 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 13 Jun 2020 13:37:43 +0800 Subject: [PATCH 08/61] Update README badges --- README.md | 4 +--- README_CN.md | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a15be488..ed866224 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,7 @@ Xorm is a simple and powerful ORM for Go. -[![Build Status](https://drone.gitea.com/api/badges/xorm/xorm/status.svg)](https://drone.gitea.com/xorm/xorm) [![](http://gocover.io/_badge/xorm.io/xorm)](https://gocover.io/xorm.io/xorm) -[![](https://goreportcard.com/badge/xorm.io/xorm)](https://goreportcard.com/report/xorm.io/xorm) -[![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3) +[![Build Status](https://drone.gitea.com/api/badges/xorm/xorm/status.svg)](https://drone.gitea.com/xorm/xorm) [![](http://gocover.io/_badge/xorm.io/xorm)](https://gocover.io/xorm.io/xorm) [![](https://goreportcard.com/badge/xorm.io/xorm)](https://goreportcard.com/report/xorm.io/xorm) [![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3) ## Notice diff --git a/README_CN.md b/README_CN.md index f6f88310..80245dd3 100644 --- a/README_CN.md +++ b/README_CN.md @@ -4,9 +4,7 @@ xorm 是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。 -[![Build Status](https://drone.gitea.com/api/badges/xorm/xorm/status.svg)](https://drone.gitea.com/xorm/xorm) [![](http://gocover.io/_badge/xorm.io/xorm)](https://gocover.io/xorm.io/xorm) -[![](https://goreportcard.com/badge/xorm.io/xorm)](https://goreportcard.com/report/xorm.io/xorm) -[![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3) +[![Build Status](https://drone.gitea.com/api/badges/xorm/xorm/status.svg)](https://drone.gitea.com/xorm/xorm) [![](http://gocover.io/_badge/xorm.io/xorm)](https://gocover.io/xorm.io/xorm) [![](https://goreportcard.com/badge/xorm.io/xorm)](https://goreportcard.com/report/xorm.io/xorm) [![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3) ## Notice From b434b045ad863a3b250149ee543d2e600b284007 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 16 Jun 2020 02:09:37 +0000 Subject: [PATCH 09/61] Add missing changelog for 1.0.2 (#1712) Add missing changelog for 1.0.2 Reviewed-on: https://gitea.com/xorm/xorm/pulls/1712 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cd081e0..22f6157a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,20 @@ This changelog goes through all the changes that have been made in each release without substantial changes to our git log. +## [1.0.2](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1261) - 2020-06-16 + +* FEATURES + * Add Hook (#1644) +* BUGFIXES + * Fix bug when ID used but no reference table given (#1709) + * Fix find and count bug (#1651) +* ENHANCEMENTS + * chore: improve snakeCasedName performance (#1688) + * Fix find with another struct (#1666) + * fix GetColumns missing ordinal position (#1660) +* MISC + * chore: improve titleCasedName performance (#1691) + ## [1.0.1](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1253) - 2020-03-25 * BUGFIXES From cc7d219065268513354dca1f528cdebe2152ac32 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 18 Jun 2020 11:36:19 +0000 Subject: [PATCH 10/61] Upgrade some dependencies (#1718) Upgrade some dependencies Reviewed-on: https://gitea.com/xorm/xorm/pulls/1718 --- go.mod | 10 ++--- go.sum | 132 +++++++-------------------------------------------------- 2 files changed, 20 insertions(+), 122 deletions(-) diff --git a/go.mod b/go.mod index ff42c0f7..f6a98156 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,12 @@ module xorm.io/xorm go 1.11 require ( - github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4 - github.com/go-sql-driver/mysql v1.4.1 - github.com/kr/pretty v0.1.0 // indirect - github.com/lib/pq v1.0.0 - github.com/mattn/go-sqlite3 v1.10.0 + github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc + github.com/go-sql-driver/mysql v1.5.0 + github.com/lib/pq v1.7.0 + github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/stretchr/testify v1.4.0 github.com/syndtr/goleveldb v1.0.0 github.com/ziutek/mymysql v1.5.4 - google.golang.org/appengine v1.6.0 // indirect xorm.io/builder v0.3.7 ) diff --git a/go.sum b/go.sum index 84f9126e..2da01eeb 100644 --- a/go.sum +++ b/go.sum @@ -1,90 +1,33 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU= -cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4 h1:YcpmyvADGYw5LqMnHqSkyIELsHCGF6PkrmM31V8rF7o= -github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +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/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= -github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY= +github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= +github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= @@ -93,60 +36,20 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.0 h1:Tfd7cKwKbFRsI8RMAD3oqqw7JPFRrvFlOsfbgVkjOOw= -google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -154,8 +57,5 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI= xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= From 9b41b879a700c09250df797c12d3d046a1e09fbb Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jun 2020 13:06:46 +0000 Subject: [PATCH 11/61] return the result on transaction (#1725) return the result on transaction Reviewed-on: https://gitea.com/xorm/xorm/pulls/1725 --- engine.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine.go b/engine.go index b5cb6558..d5e599d6 100644 --- a/engine.go +++ b/engine.go @@ -1263,11 +1263,11 @@ func (engine *Engine) Transaction(f func(*Session) (interface{}, error)) (interf result, err := f(session) if err != nil { - return nil, err + return result, err } if err := session.Commit(); err != nil { - return nil, err + return result, err } return result, nil From 677c0d7411fe380dfcde87e887bfa80624f43954 Mon Sep 17 00:00:00 2001 From: getsu Date: Fri, 3 Jul 2020 08:10:09 +0000 Subject: [PATCH 12/61] fix invalid date when update for oracle (#1694) Merge branch 'master' into master Merge branch 'master' into master Merge branch 'master' into master fix invalid date when update for oracle Co-authored-by: Lunny Xiao Co-authored-by: chendy Reviewed-on: https://gitea.com/xorm/xorm/pulls/1694 --- session_update.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/session_update.go b/session_update.go index 62116c47..7df8c752 100644 --- a/session_update.go +++ b/session_update.go @@ -206,7 +206,11 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 colNames = append(colNames, session.engine.Quote(table.Updated)+" = ?") col := table.UpdatedColumn() val, t := session.engine.nowTime(col) - args = append(args, val) + if session.engine.dialect.URI().DBType == schemas.ORACLE { + args = append(args, t) + } else { + args = append(args, val) + } var colName = col.Name if isStruct { From 14a98ca9d20e4d5174ab5828e4d3214910c3c4c1 Mon Sep 17 00:00:00 2001 From: MURAOKA Taro Date: Sat, 4 Jul 2020 06:13:15 +0000 Subject: [PATCH 13/61] add hooks for Commit and Rollback (#1733) add hooks for Commit and Rollback Related issue: https://gitea.com/xorm/xorm/issues/1732 Co-authored-by: MURAOKA Taro Reviewed-on: https://gitea.com/xorm/xorm/pulls/1733 Reviewed-by: Lunny Xiao --- core/tx.go | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/core/tx.go b/core/tx.go index 9b2988af..a85a6874 100644 --- a/core/tx.go +++ b/core/tx.go @@ -18,7 +18,8 @@ var ( // Tx represents a transaction type Tx struct { *sql.Tx - db *DB + db *DB + ctx context.Context } func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) { @@ -32,13 +33,41 @@ func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) { if err := db.afterProcess(hookCtx); err != nil { return nil, err } - return &Tx{tx, db}, nil + return &Tx{tx, db, ctx}, nil } func (db *DB) Begin() (*Tx, error) { return db.BeginTx(context.Background(), nil) } +func (tx *Tx) Commit() error { + hookCtx := contexts.NewContextHook(tx.ctx, "COMMIT", nil) + ctx, err := tx.db.beforeProcess(hookCtx) + if err != nil { + return err + } + err = tx.Tx.Commit() + hookCtx.End(ctx, nil, err) + if err := tx.db.afterProcess(hookCtx); err != nil { + return err + } + return nil +} + +func (tx *Tx) Rollback() error { + hookCtx := contexts.NewContextHook(tx.ctx, "ROLLBACK", nil) + ctx, err := tx.db.beforeProcess(hookCtx) + if err != nil { + return err + } + err = tx.Tx.Rollback() + hookCtx.End(ctx, nil, err) + if err := tx.db.afterProcess(hookCtx); err != nil { + return err + } + return nil +} + func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) { names := make(map[string]int) var i int From 6becb291d3d6ca10f4dc331ad165613990e401bf Mon Sep 17 00:00:00 2001 From: Ky Date: Tue, 7 Jul 2020 14:49:58 +0000 Subject: [PATCH 14/61] update sqlite3 (#1730) update sqlite3 Reviewed-on: https://gitea.com/xorm/xorm/pulls/1730 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index f6a98156..e0d22a24 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc github.com/go-sql-driver/mysql v1.5.0 github.com/lib/pq v1.7.0 - github.com/mattn/go-sqlite3 v2.0.3+incompatible + github.com/mattn/go-sqlite3 v1.14.0 github.com/stretchr/testify v1.4.0 github.com/syndtr/goleveldb v1.0.0 github.com/ziutek/mymysql v1.5.4 From 1a396821804c5e8c388ba60c5082670c5197f254 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 9 Jul 2020 01:41:12 +0000 Subject: [PATCH 15/61] Fix dump of sqlite (#1639) Fix test fix test Fix sqlite dump Fix sqlite dump Reviewed-on: https://gitea.com/xorm/xorm/pulls/1639 --- dialects/mssql.go | 5 +- engine.go | 135 ++++++++++++++++++++++-------------- integrations/engine_test.go | 57 +++++++++++++-- 3 files changed, 137 insertions(+), 60 deletions(-) diff --git a/dialects/mssql.go b/dialects/mssql.go index 8ef924b8..f766950c 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -231,6 +231,7 @@ func (db *mssql) SQLType(c *schemas.Column) string { } else if strings.EqualFold(c.Default, "false") { c.Default = "0" } + return res case schemas.Serial: c.IsAutoIncrement = true c.IsPrimaryKey = true @@ -270,8 +271,8 @@ func (db *mssql) SQLType(c *schemas.Column) string { res = t } - if res == schemas.Int { - return schemas.Int + if res == schemas.Int || res == schemas.Bit || res == schemas.DateTime { + return res } hasLen1 := (c.Length > 0) diff --git a/engine.go b/engine.go index d5e599d6..8b137b27 100644 --- a/engine.go +++ b/engine.go @@ -412,6 +412,82 @@ func (engine *Engine) DumpTables(tables []*schemas.Table, w io.Writer, tp ...sch return engine.dumpTables(tables, w, tp...) } +func formatColumnValue(dstDialect dialects.Dialect, d interface{}, col *schemas.Column) string { + if d == nil { + return "NULL" + } + + if dq, ok := d.(bool); ok && (dstDialect.URI().DBType == schemas.SQLITE || + dstDialect.URI().DBType == schemas.MSSQL) { + if dq { + return "1" + } + return "0" + } + + if col.SQLType.IsText() { + var v = fmt.Sprintf("%s", d) + return "'" + strings.Replace(v, "'", "''", -1) + "'" + } else if col.SQLType.IsTime() { + var v = fmt.Sprintf("%s", d) + if strings.HasSuffix(v, " +0000 UTC") { + return fmt.Sprintf("'%s'", v[0:len(v)-len(" +0000 UTC")]) + } else if strings.HasSuffix(v, " +0000 +0000") { + return fmt.Sprintf("'%s'", v[0:len(v)-len(" +0000 +0000")]) + } + return "'" + strings.Replace(v, "'", "''", -1) + "'" + } else if col.SQLType.IsBlob() { + if reflect.TypeOf(d).Kind() == reflect.Slice { + return fmt.Sprintf("%s", dstDialect.FormatBytes(d.([]byte))) + } else if reflect.TypeOf(d).Kind() == reflect.String { + return fmt.Sprintf("'%s'", d.(string)) + } + } else if col.SQLType.IsNumeric() { + switch reflect.TypeOf(d).Kind() { + case reflect.Slice: + if col.SQLType.Name == schemas.Bool { + return fmt.Sprintf("%v", strconv.FormatBool(d.([]byte)[0] != byte('0'))) + } + return fmt.Sprintf("%s", string(d.([]byte))) + case reflect.Int16, reflect.Int8, reflect.Int32, reflect.Int64, reflect.Int: + if col.SQLType.Name == schemas.Bool { + v := reflect.ValueOf(d).Int() > 0 + if dstDialect.URI().DBType == schemas.SQLITE { + if v { + return "1" + } + return "0" + } + return fmt.Sprintf("%v", strconv.FormatBool(v)) + } + return fmt.Sprintf("%v", d) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if col.SQLType.Name == schemas.Bool { + v := reflect.ValueOf(d).Uint() > 0 + if dstDialect.URI().DBType == schemas.SQLITE { + if v { + return "1" + } + return "0" + } + return fmt.Sprintf("%v", strconv.FormatBool(v)) + } + return fmt.Sprintf("%v", d) + default: + return fmt.Sprintf("%v", d) + } + } + + s := fmt.Sprintf("%v", d) + if strings.Contains(s, ":") || strings.Contains(s, "-") { + if strings.HasSuffix(s, " +0000 UTC") { + return fmt.Sprintf("'%s'", s[0:len(s)-len(" +0000 UTC")]) + } + return fmt.Sprintf("'%s'", s) + } + return s +} + // dumpTables dump database all table structs and data to w with specify db type func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...schemas.DBType) error { var dstDialect dialects.Dialect @@ -424,7 +500,10 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch } uri := engine.dialect.URI() - destURI := *uri + destURI := dialects.URI{ + DBType: tp[0], + DBName: uri.DBName, + } dstDialect.Init(&destURI) } @@ -495,59 +574,9 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch if col == nil { return errors.New("unknow column error") } - - if d == nil { - temp += ", NULL" - } else if col.SQLType.IsText() || col.SQLType.IsTime() { - var v = fmt.Sprintf("%s", d) - if strings.HasSuffix(v, " +0000 UTC") { - temp += fmt.Sprintf(", '%s'", v[0:len(v)-len(" +0000 UTC")]) - } else { - temp += ", '" + strings.Replace(v, "'", "''", -1) + "'" - } - } else if col.SQLType.IsBlob() { - if reflect.TypeOf(d).Kind() == reflect.Slice { - temp += fmt.Sprintf(", %s", dstDialect.FormatBytes(d.([]byte))) - } else if reflect.TypeOf(d).Kind() == reflect.String { - temp += fmt.Sprintf(", '%s'", d.(string)) - } - } else if col.SQLType.IsNumeric() { - switch reflect.TypeOf(d).Kind() { - case reflect.Slice: - if col.SQLType.Name == schemas.Bool { - temp += fmt.Sprintf(", %v", strconv.FormatBool(d.([]byte)[0] != byte('0'))) - } else { - temp += fmt.Sprintf(", %s", string(d.([]byte))) - } - case reflect.Int16, reflect.Int8, reflect.Int32, reflect.Int64, reflect.Int: - if col.SQLType.Name == schemas.Bool { - temp += fmt.Sprintf(", %v", strconv.FormatBool(reflect.ValueOf(d).Int() > 0)) - } else { - temp += fmt.Sprintf(", %v", d) - } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - if col.SQLType.Name == schemas.Bool { - temp += fmt.Sprintf(", %v", strconv.FormatBool(reflect.ValueOf(d).Uint() > 0)) - } else { - temp += fmt.Sprintf(", %v", d) - } - default: - temp += fmt.Sprintf(", %v", d) - } - } else { - s := fmt.Sprintf("%v", d) - if strings.Contains(s, ":") || strings.Contains(s, "-") { - if strings.HasSuffix(s, " +0000 UTC") { - temp += fmt.Sprintf(", '%s'", s[0:len(s)-len(" +0000 UTC")]) - } else { - temp += fmt.Sprintf(", '%s'", s) - } - } else { - temp += fmt.Sprintf(", %s", s) - } - } + temp += "," + formatColumnValue(dstDialect, d, col) } - _, err = io.WriteString(w, temp[2:]+");\n") + _, err = io.WriteString(w, temp[1:]+");\n") if err != nil { return err } diff --git a/integrations/engine_test.go b/integrations/engine_test.go index 19c5285d..0e5d3424 100644 --- a/integrations/engine_test.go +++ b/integrations/engine_test.go @@ -93,19 +93,23 @@ func TestDump(t *testing.T) { assert.NoError(t, PrepareEngine()) type TestDumpStruct struct { - Id int64 - Name string + Id int64 + Name string + IsMan bool + Created time.Time `xorm:"created"` } assertSync(t, new(TestDumpStruct)) - testEngine.Insert([]TestDumpStruct{ - {Name: "1"}, + cnt, err := testEngine.Insert([]TestDumpStruct{ + {Name: "1", IsMan: true}, {Name: "2\n"}, {Name: "3;"}, {Name: "4\n;\n''"}, {Name: "5'\n"}, }) + assert.NoError(t, err) + assert.EqualValues(t, 5, cnt) fp := fmt.Sprintf("%v.sql", testEngine.Dialect().URI().DBType) os.Remove(fp) @@ -116,7 +120,7 @@ func TestDump(t *testing.T) { sess := testEngine.NewSession() defer sess.Close() assert.NoError(t, sess.Begin()) - _, err := sess.ImportFile(fp) + _, err = sess.ImportFile(fp) assert.NoError(t, err) assert.NoError(t, sess.Commit()) @@ -128,6 +132,49 @@ func TestDump(t *testing.T) { } } +func TestDumpTables(t *testing.T) { + assert.NoError(t, PrepareEngine()) + + type TestDumpTableStruct struct { + Id int64 + Name string + IsMan bool + Created time.Time `xorm:"created"` + } + + assertSync(t, new(TestDumpTableStruct)) + + testEngine.Insert([]TestDumpTableStruct{ + {Name: "1", IsMan: true}, + {Name: "2\n"}, + {Name: "3;"}, + {Name: "4\n;\n''"}, + {Name: "5'\n"}, + }) + + fp := fmt.Sprintf("%v-table.sql", testEngine.Dialect().URI().DBType) + os.Remove(fp) + tb, err := testEngine.TableInfo(new(TestDumpTableStruct)) + assert.NoError(t, err) + assert.NoError(t, testEngine.(*xorm.Engine).DumpTablesToFile([]*schemas.Table{tb}, fp)) + + assert.NoError(t, PrepareEngine()) + + sess := testEngine.NewSession() + defer sess.Close() + assert.NoError(t, sess.Begin()) + _, err = sess.ImportFile(fp) + assert.NoError(t, err) + assert.NoError(t, sess.Commit()) + + for _, tp := range []schemas.DBType{schemas.SQLITE, schemas.MYSQL, schemas.POSTGRES, schemas.MSSQL} { + name := fmt.Sprintf("dump_%v-table.sql", tp) + t.Run(name, func(t *testing.T) { + assert.NoError(t, testEngine.(*xorm.Engine).DumpTablesToFile([]*schemas.Table{tb}, name, tp)) + }) + } +} + func TestSetSchema(t *testing.T) { assert.NoError(t, PrepareEngine()) From 56881e64a9c77d19c862bf203ccf31a22368032d Mon Sep 17 00:00:00 2001 From: MURAOKA Taro Date: Thu, 9 Jul 2020 06:44:26 +0000 Subject: [PATCH 16/61] put ContextLogger in higher priority (#1656) Merge branch 'master' into logger-priority Merge branch 'master' into logger-priority Merge branch 'master' into logger-priority Merge branch 'master' into logger-priority put ContextLogger in higher priority SetLogger use `Logger` when give a interface which implements both ContextLogger and Logger. Because Go's type `switch` uses prior `case`. Co-authored-by: Lunny Xiao Co-authored-by: MURAOKA Taro Reviewed-on: https://gitea.com/xorm/xorm/pulls/1656 --- engine.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine.go b/engine.go index 8b137b27..4159a7b2 100644 --- a/engine.go +++ b/engine.go @@ -143,10 +143,10 @@ func (engine *Engine) Logger() log.ContextLogger { func (engine *Engine) SetLogger(logger interface{}) { var realLogger log.ContextLogger switch t := logger.(type) { - case log.Logger: - realLogger = log.NewLoggerAdapter(t) case log.ContextLogger: realLogger = t + case log.Logger: + realLogger = log.NewLoggerAdapter(t) } engine.logger = realLogger engine.DB().Logger = realLogger From be7800fc6365724c36ec756f76d40123ecac995b Mon Sep 17 00:00:00 2001 From: StdioA Date: Thu, 9 Jul 2020 08:26:18 +0000 Subject: [PATCH 17/61] Fix index name parsing in SQLite dialect (#1737) Fix index name parsing in SQLite dialect If index is created with statement like CREATE INDEX "IDX_tbl_field" ON "tbl" (field), the dialect will parse index name as "IDX_tbl_field" and recognize it as an irregular index. Co-authored-by: David Dai Reviewed-on: https://gitea.com/xorm/xorm/pulls/1737 --- dialects/sqlite3.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialects/sqlite3.go b/dialects/sqlite3.go index 0e910934..73f98beb 100644 --- a/dialects/sqlite3.go +++ b/dialects/sqlite3.go @@ -483,7 +483,7 @@ func (db *sqlite3) GetIndexes(queryer core.Queryer, ctx context.Context, tableNa continue } - indexName := strings.Trim(sql[nNStart+6:nNEnd], "` []") + indexName := strings.Trim(sql[nNStart+6:nNEnd], "` []'\"") var isRegular bool if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) { index.Name = indexName[5+len(tableName):] From 946fb57e1cf346a4d1df1cafad6f56d2fb24ed58 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 10 Jul 2020 20:57:00 +0800 Subject: [PATCH 18/61] Add 1.0.3 to changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22f6157a..fa0259bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,14 @@ This changelog goes through all the changes that have been made in each release without substantial changes to our git log. +## [1.0.3](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1281) - 2020-07-10 + +* BUGFIXES + * Fix dump of sqlite (#1639) +* ENHANCEMENTS + * Fix index name parsing in SQLite dialect (#1737) + * add hooks for Commit and Rollback (#1733) + ## [1.0.2](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1261) - 2020-06-16 * FEATURES From 0fae64bb3b4c280dc2f8ab6fe6d15e80068354bc Mon Sep 17 00:00:00 2001 From: Thomas_An Date: Mon, 13 Jul 2020 13:29:38 +0000 Subject: [PATCH 19/61] Support get dataSourceName on ContextHook for monitor which DB executed SQL (#1740) Merge branch 'log_context_add_db_info' add session to context Revert "accept lunny's suggestion" This reverts commit 57fd6699425bdb97baf6bbeddc3099ffcb4576d8. Merge branch 'master' of https://gitea.com/Thomas_An/thomasan_xorm accept lunny's suggestion Merge branch 'master' into master add test code session add Engine func Used to monitor which DB executed this SQL Co-authored-by: yong.an Reviewed-on: https://gitea.com/xorm/xorm/pulls/1740 Reviewed-by: Lunny Xiao --- integrations/session_test.go | 8 ++++++++ interface.go | 1 + log/logger_context.go | 1 + session.go | 12 ++++++++++-- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/integrations/session_test.go b/integrations/session_test.go index bdf3278d..af8b0375 100644 --- a/integrations/session_test.go +++ b/integrations/session_test.go @@ -54,3 +54,11 @@ func TestMustLogSQL(t *testing.T) { _, err := testEngine.Table("userinfo").MustLogSQL(true).Get(new(Userinfo)) assert.NoError(t, err) } + +func TestEnableSessionId(t *testing.T) { + assert.NoError(t, PrepareEngine()) + testEngine.EnableSessionID(true) + assertSync(t, new(Userinfo)) + _, err := testEngine.Table("userinfo").MustLogSQL(true).Get(new(Userinfo)) + assert.NoError(t, err) +} \ No newline at end of file diff --git a/interface.go b/interface.go index 6aac4ae8..0fe9cbe1 100644 --- a/interface.go +++ b/interface.go @@ -120,6 +120,7 @@ type EngineInterface interface { TableInfo(bean interface{}) (*schemas.Table, error) TableName(interface{}, ...bool) string UnMapType(reflect.Type) + EnableSessionID(bool) } var ( diff --git a/log/logger_context.go b/log/logger_context.go index 6b7252ef..46802576 100644 --- a/log/logger_context.go +++ b/log/logger_context.go @@ -42,6 +42,7 @@ var ( // enumerate all the context keys var ( SessionIDKey = "__xorm_session_id" + SessionKey = "__xorm_session_key" SessionShowSQLKey = "__xorm_show_sql" ) diff --git a/session.go b/session.go index 761b1415..48b3779e 100644 --- a/session.go +++ b/session.go @@ -102,12 +102,12 @@ func newSessionID() string { func newSession(engine *Engine) *Session { var ctx context.Context if engine.logSessionID { - ctx = context.WithValue(engine.defaultContext, log.SessionIDKey, newSessionID()) + ctx = context.WithValue(engine.defaultContext, log.SessionIDKey, newSessionID()) } else { ctx = engine.defaultContext } - return &Session{ + session := &Session{ ctx: ctx, engine: engine, tx: nil, @@ -136,6 +136,10 @@ func newSession(engine *Engine) *Session { sessionType: engineSession, } + if engine.logSessionID { + session.ctx = context.WithValue(session.ctx, log.SessionKey, session) + } + return session } // Close release the connection from pool @@ -165,6 +169,10 @@ func (session *Session) db() *core.DB { return session.engine.db } +func (session *Session) Engine() *Engine { + return session.engine +} + func (session *Session) getQueryer() core.Queryer { if session.tx != nil { return session.tx From 318102c9ff87134d86e1c173495afb77bb6b74e6 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 18 Jul 2020 08:01:27 +0000 Subject: [PATCH 20/61] Add params for mssql to allow redefine varchar as nvarchar or char as nchar (#1741) Update drone test for mssql nvarchar Add params for mssql to allow redefine varchar as nvarchar or char as nchar Reviewed-on: https://gitea.com/xorm/xorm/pulls/1741 --- .drone.yml | 1 + Makefile | 4 ++++ dialects/mssql.go | 34 ++++++++++++++++++++++++++++++++++ go.sum | 13 +++++++++++-- integrations/tests.go | 7 +++++++ 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/.drone.yml b/.drone.yml index 7a18e0d6..8cf43aa2 100644 --- a/.drone.yml +++ b/.drone.yml @@ -164,6 +164,7 @@ steps: - make test-mssql - TEST_CACHE_ENABLE=true make test-mssql - TEST_QUOTE_POLICY=reserved make test-mssql + - TEST_MSSQL_DEFAULT_VARCHAR=NVARCHAR TEST_MSSQL_DEFAULT_CHAR=NCHAR make test-mssql when: event: - push diff --git a/Makefile b/Makefile index 4cccacd8..ed873883 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,8 @@ TEST_MSSQL_HOST ?= mssql:1433 TEST_MSSQL_DBNAME ?= gitea TEST_MSSQL_USERNAME ?= sa TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1 +TEST_MSSQL_DEFAULT_VARCHAR ?= varchar +TEST_MSSQL_DEFAULT_CHAR ?= char TEST_MYSQL_HOST ?= mysql:3306 TEST_MYSQL_CHARSET ?= utf8 @@ -144,12 +146,14 @@ test-cockroach\#%: go-check test-mssql: go-check $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mssql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ -conn_str="server=$(TEST_MSSQL_HOST);user id=$(TEST_MSSQL_USERNAME);password=$(TEST_MSSQL_PASSWORD);database=$(TEST_MSSQL_DBNAME)" \ + -default_varchar=$(TEST_MSSQL_DEFAULT_VARCHAR) -default_char=$(TEST_MSSQL_DEFAULT_CHAR) \ -coverprofile=mssql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic .PNONY: test-mssql\#% test-mssql\#%: go-check $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=mssql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ -conn_str="server=$(TEST_MSSQL_HOST);user id=$(TEST_MSSQL_USERNAME);password=$(TEST_MSSQL_PASSWORD);database=$(TEST_MSSQL_DBNAME)" \ + -default_varchar=$(TEST_MSSQL_DEFAULT_VARCHAR) -default_char=$(TEST_MSSQL_DEFAULT_CHAR) \ -coverprofile=mssql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic .PNONY: test-mymysql diff --git a/dialects/mssql.go b/dialects/mssql.go index f766950c..d76a8c6c 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -214,6 +214,8 @@ var ( type mssql struct { Base + defaultVarchar string + defaultChar string } func (db *mssql) Init(uri *URI) error { @@ -221,6 +223,34 @@ func (db *mssql) Init(uri *URI) error { return db.Base.Init(db, uri) } +func (db *mssql) SetParams(params map[string]string) { + defaultVarchar, ok := params["DEFAULT_VARCHAR"] + if ok { + var t = strings.ToUpper(defaultVarchar) + switch t { + case "NVARCHAR", "VARCHAR": + db.defaultVarchar = defaultVarchar + default: + db.defaultVarchar = "VARCHAR" + } + } else { + db.defaultVarchar = "VARCHAR" + } + + defaultChar, ok := params["DEFAULT_CHAR"] + if ok { + var t = strings.ToUpper(defaultChar) + switch t { + case "NCHAR", "CHAR": + db.defaultChar = defaultChar + default: + db.defaultChar = "CHAR" + } + } else { + db.defaultChar = "CHAR" + } +} + func (db *mssql) SQLType(c *schemas.Column) string { var res string switch t := c.SQLType.Name; t { @@ -267,6 +297,10 @@ func (db *mssql) SQLType(c *schemas.Column) string { case schemas.BigInt: res = schemas.BigInt c.Length = 0 + case schemas.Varchar: + res = db.defaultVarchar + case schemas.Char: + res = db.defaultChar default: res = t } diff --git a/go.sum b/go.sum index 2da01eeb..844dd094 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= +github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= 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= @@ -18,8 +20,8 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY= github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= -github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= +github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -36,16 +38,23 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/integrations/tests.go b/integrations/tests.go index c8219935..b135bd90 100644 --- a/integrations/tests.go +++ b/integrations/tests.go @@ -36,6 +36,8 @@ var ( ignoreSelectUpdate = flag.Bool("ignore_select_update", false, "ignore select update if implementation difference, only for tidb") ingoreUpdateLimit = flag.Bool("ignore_update_limit", false, "ignore update limit if implementation difference, only for cockroach") quotePolicyStr = flag.String("quote", "always", "quote could be always, none, reversed") + defaultVarchar = flag.String("default_varchar", "varchar", "default varchar type, mssql only, could be varchar or nvarchar, default is varchar") + defaultChar = flag.String("default_char", "char", "default char type, mssql only, could be char or nchar, default is char") tableMapper names.Mapper colMapper names.Mapper ) @@ -137,6 +139,11 @@ func createEngine(dbType, connStr string) error { } else { testEngine.SetQuotePolicy(dialects.QuotePolicyAlways) } + + testEngine.Dialect().SetParams(map[string]string{ + "DEFAULT_VARCHAR": *defaultVarchar, + "DEFAULT_CHAR": *defaultChar, + }) } tableMapper = testEngine.GetTableMapper() From fe3bc3851e93af53a73152311421df1f85fb9495 Mon Sep 17 00:00:00 2001 From: appleboy Date: Tue, 21 Jul 2020 04:36:55 +0000 Subject: [PATCH 21/61] chore: enable fmt check (#1742) chore: enable fmt check Co-authored-by: Bo-Yi Wu Reviewed-on: https://gitea.com/xorm/xorm/pulls/1742 Reviewed-by: Lunny Xiao --- .drone.yml | 1 + integrations/session_test.go | 2 +- internal/utils/strings.go | 1 - session.go | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.drone.yml b/.drone.yml index 8cf43aa2..93fad07b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -10,6 +10,7 @@ steps: commands: - make vet - make test + - make fmt-check when: event: - push diff --git a/integrations/session_test.go b/integrations/session_test.go index af8b0375..c3ef0513 100644 --- a/integrations/session_test.go +++ b/integrations/session_test.go @@ -61,4 +61,4 @@ func TestEnableSessionId(t *testing.T) { assertSync(t, new(Userinfo)) _, err := testEngine.Table("userinfo").MustLogSQL(true).Get(new(Userinfo)) assert.NoError(t, err) -} \ No newline at end of file +} diff --git a/internal/utils/strings.go b/internal/utils/strings.go index b5dc37b7..72466705 100644 --- a/internal/utils/strings.go +++ b/internal/utils/strings.go @@ -27,4 +27,3 @@ func SplitNNoCase(s, sep string, n int) []string { } return strings.SplitN(s, s[idx:idx+len(sep)], n) } - diff --git a/session.go b/session.go index 48b3779e..b6ab3eb5 100644 --- a/session.go +++ b/session.go @@ -102,7 +102,7 @@ func newSessionID() string { func newSession(engine *Engine) *Session { var ctx context.Context if engine.logSessionID { - ctx = context.WithValue(engine.defaultContext, log.SessionIDKey, newSessionID()) + ctx = context.WithValue(engine.defaultContext, log.SessionIDKey, newSessionID()) } else { ctx = engine.defaultContext } From 4a6b8c29bf281da48b2a76a7f0d3d7129dd04d24 Mon Sep 17 00:00:00 2001 From: sylba2050 Date: Mon, 27 Jul 2020 09:29:33 +0000 Subject: [PATCH 22/61] Fix typo (#1748) Fix typo Co-authored-by: Masataka Hisasue Reviewed-on: https://gitea.com/xorm/xorm/pulls/1748 Reviewed-by: Lunny Xiao --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ed866224..67380839 100644 --- a/README.md +++ b/README.md @@ -313,7 +313,7 @@ err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e")) // SELECT id, name ... FROM user WHERE a NOT IN (?, ?) AND b IN (?, ?, ?) ``` -* Multiple operations in one go routine, no transation here but resue session memory +* Multiple operations in one go routine, no transaction here but resue session memory ```Go session := engine.NewSession() @@ -336,7 +336,7 @@ if _, err := session.Exec("delete from userinfo where username = ?", user2.Usern return nil ``` -* Transation should be on one go routine. There is transaction and resue session memory +* Transaction should be on one go routine. There is transaction and resue session memory ```Go session := engine.NewSession() From f39a4cb41c5ce30c219c3b465328e975d7eb51f1 Mon Sep 17 00:00:00 2001 From: w3xse7en Date: Thu, 30 Jul 2020 09:05:59 +0000 Subject: [PATCH 23/61] solve duplicate log in commit and rollback (#1750) solve duplicate log in commit and rollback Co-authored-by: Lyi Reviewed-on: https://gitea.com/xorm/xorm/pulls/1750 Reviewed-by: helong zhang --- session_tx.go | 45 ++------------------------------------------- 1 file changed, 2 insertions(+), 43 deletions(-) diff --git a/session_tx.go b/session_tx.go index cd23cf89..57791703 100644 --- a/session_tx.go +++ b/session_tx.go @@ -4,12 +4,6 @@ package xorm -import ( - "time" - - "xorm.io/xorm/log" -) - // Begin a transaction func (session *Session) Begin() error { if session.isAutoCommit { @@ -33,24 +27,7 @@ func (session *Session) Rollback() error { session.isCommitedOrRollbacked = true session.isAutoCommit = true - start := time.Now() - needSQL := session.DB().NeedLogSQL(session.ctx) - if needSQL { - session.engine.logger.BeforeSQL(log.LogContext{ - Ctx: session.ctx, - SQL: "ROLL BACK", - }) - } - err := session.tx.Rollback() - if needSQL { - session.engine.logger.AfterSQL(log.LogContext{ - Ctx: session.ctx, - SQL: "ROLL BACK", - ExecuteTime: time.Now().Sub(start), - Err: err, - }) - } - return err + return session.tx.Rollback() } return nil } @@ -62,25 +39,7 @@ func (session *Session) Commit() error { session.isCommitedOrRollbacked = true session.isAutoCommit = true - start := time.Now() - needSQL := session.DB().NeedLogSQL(session.ctx) - if needSQL { - session.engine.logger.BeforeSQL(log.LogContext{ - Ctx: session.ctx, - SQL: "COMMIT", - }) - } - err := session.tx.Commit() - if needSQL { - session.engine.logger.AfterSQL(log.LogContext{ - Ctx: session.ctx, - SQL: "COMMIT", - ExecuteTime: time.Now().Sub(start), - Err: err, - }) - } - - if err != nil { + if err := session.tx.Commit(); err != nil { return err } From 76d6b9fdf55b1cc4ed9a8bb8b1cdc0910cdff92e Mon Sep 17 00:00:00 2001 From: jdkendall Date: Mon, 31 Aug 2020 01:19:12 +0000 Subject: [PATCH 24/61] Fix mysql dialect error from invalid db identifier in orderby clause (#1743) (#1751) Fix mysql dialect error from invalid db identifier in orderby clause (#1743) Reviewed-on: https://gitea.com/xorm/xorm/pulls/1751 --- dialects/mysql.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialects/mysql.go b/dialects/mysql.go index f9a2e943..a39cd925 100644 --- a/dialects/mysql.go +++ b/dialects/mysql.go @@ -309,7 +309,7 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName args := []interface{}{db.uri.DBName, tableName} s := "SELECT `COLUMN_NAME`, `IS_NULLABLE`, `COLUMN_DEFAULT`, `COLUMN_TYPE`," + " `COLUMN_KEY`, `EXTRA`,`COLUMN_COMMENT` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?" + - " ORDER BY `INFORMATION_SCHEMA`.`COLUMNS`.ORDINAL_POSITION" + " ORDER BY `COLUMNS`.ORDINAL_POSITION" rows, err := queryer.QueryContext(ctx, s, args...) if err != nil { From f8c91ec4a3603ce640671278573d456a7522c91b Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Wed, 2 Sep 2020 12:37:16 +0000 Subject: [PATCH 25/61] Correct default detection in MariaDB >= 10.2.7 (#1778) try again ci Signed-off-by: Andrew Thornton try again ci Signed-off-by: Andrew Thornton tidy up appearance of the alreadyQuoted SQL string Signed-off-by: Andrew Thornton Merge remote-tracking branch 'origin/master' into fix-defaults-sync2-mysql Try MariaDB 10.4 Signed-off-by: Andrew Thornton fix drone Signed-off-by: Andrew Thornton Correct default detection in MariaDB >= 10.2.7 MariaDB in version 10.2.7 changed the reporting of COLUMN_DEFAULT in INFORMATION_SCHEMA.COLUMNS to quote string values. This PR adds a version detection test to the columns query. References: https://jira.mariadb.org/browse/MDEV-13132 References: https://jira.mariadb.org/browse/MDEV-15390 Signed-off-by: Andrew Thornton Reviewed-on: https://gitea.com/xorm/xorm/pulls/1778 Reviewed-by: Lunny Xiao --- .drone.yml | 31 +++++++++++++++++++++++++++++++ dialects/mysql.go | 19 ++++++++++++++----- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/.drone.yml b/.drone.yml index 93fad07b..300c7841 100644 --- a/.drone.yml +++ b/.drone.yml @@ -110,6 +110,25 @@ steps: - push - pull_request +- name: test-mariadb + image: golang:1.12 + environment: + GO111MODULE: "on" + GOPROXY: "https://goproxy.cn" + TEST_MYSQL_HOST: mariadb + TEST_MYSQL_CHARSET: utf8mb4 + TEST_MYSQL_DBNAME: xorm_test + TEST_MYSQL_USERNAME: root + TEST_MYSQL_PASSWORD: + commands: + - make test-mysql + - TEST_CACHE_ENABLE=true make test-mysql + - TEST_QUOTE_POLICY=reserved make test-mysql + when: + event: + - push + - pull_request + - name: test-postgres pull: default image: golang:1.12 @@ -259,6 +278,18 @@ services: - tag - pull_request +- name: mariadb + pull: default + image: mariadb:10.4 + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_DATABASE: xorm_test + when: + event: + - push + - tag + - pull_request + - name: pgsql pull: default image: postgres:9.5 diff --git a/dialects/mysql.go b/dialects/mysql.go index a39cd925..32e18a17 100644 --- a/dialects/mysql.go +++ b/dialects/mysql.go @@ -307,8 +307,16 @@ func (db *mysql) AddColumnSQL(tableName string, col *schemas.Column) string { func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { args := []interface{}{db.uri.DBName, tableName} + alreadyQuoted := "(INSTR(VERSION(), 'maria') > 0 && " + + "(SUBSTRING_INDEX(VERSION(), '.', 1) > 10 || " + + "(SUBSTRING_INDEX(VERSION(), '.', 1) = 10 && " + + "(SUBSTRING_INDEX(SUBSTRING(VERSION(), 4), '.', 1) > 2 || " + + "(SUBSTRING_INDEX(SUBSTRING(VERSION(), 4), '.', 1) = 2 && " + + "SUBSTRING_INDEX(SUBSTRING(VERSION(), 6), '-', 1) >= 7)))))" s := "SELECT `COLUMN_NAME`, `IS_NULLABLE`, `COLUMN_DEFAULT`, `COLUMN_TYPE`," + - " `COLUMN_KEY`, `EXTRA`,`COLUMN_COMMENT` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?" + + " `COLUMN_KEY`, `EXTRA`, `COLUMN_COMMENT`, " + + alreadyQuoted + " AS NEEDS_QUOTE " + + "FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?" + " ORDER BY `COLUMNS`.ORDINAL_POSITION" rows, err := queryer.QueryContext(ctx, s, args...) @@ -324,8 +332,9 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName col.Indexes = make(map[string]int) var columnName, isNullable, colType, colKey, extra, comment string + var alreadyQuoted bool var colDefault *string - err = rows.Scan(&columnName, &isNullable, &colDefault, &colType, &colKey, &extra, &comment) + err = rows.Scan(&columnName, &isNullable, &colDefault, &colType, &colKey, &extra, &comment, &alreadyQuoted) if err != nil { return nil, nil, err } @@ -335,7 +344,7 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName col.Nullable = true } - if colDefault != nil { + if colDefault != nil && (!alreadyQuoted || *colDefault != "NULL") { col.Default = *colDefault col.DefaultIsEmpty = false } else { @@ -404,9 +413,9 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName } if !col.DefaultIsEmpty { - if col.SQLType.IsText() { + if !alreadyQuoted && col.SQLType.IsText() { col.Default = "'" + col.Default + "'" - } else if col.SQLType.IsTime() && col.Default != "CURRENT_TIMESTAMP" { + } else if col.SQLType.IsTime() && !alreadyQuoted && col.Default != "CURRENT_TIMESTAMP" { col.Default = "'" + col.Default + "'" } } From b10919ec56a54173fb1b8e12cb5912110a44b216 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 2 Sep 2020 20:40:16 +0800 Subject: [PATCH 26/61] Add changelog for v1.0.4 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa0259bc..1a355d95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ This changelog goes through all the changes that have been made in each release without substantial changes to our git log. +## [1.0.4](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1286) - 2020-09-02 + +* FEATURES + * Add params for mssql to allow redefine varchar as nvarchar or char as nchar (#1741) +* BUGFIXES + * Fix mysql dialect error from invalid db identifier in orderby clause (#1743) (#1751) +* ENHANCEMENTS + * Support get dataSourceName on ContextHook for monitor which DB executed SQL (#1740) +* MISC + * Correct default detection in MariaDB >= 10.2.7 (#1778) + ## [1.0.3](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1281) - 2020-07-10 * BUGFIXES From 3e0179ff263b831a30bf1c563204355fd8f9a867 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 3 Sep 2020 13:10:27 +0000 Subject: [PATCH 27/61] Fix bug on get columns for postgres (#1779) Fix bug on get columns for postgres Reviewed-on: https://gitea.com/xorm/xorm/pulls/1779 --- dialects/postgres.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialects/postgres.go b/dialects/postgres.go index 1996c49d..3c1d53c0 100644 --- a/dialects/postgres.go +++ b/dialects/postgres.go @@ -1015,7 +1015,7 @@ WHERE n.nspname= s.table_schema AND c.relkind = 'r'::char AND c.relname = $1%s A schema := db.getSchema() if schema != "" { - s = fmt.Sprintf(s, "AND s.table_schema = $2") + s = fmt.Sprintf(s, " AND s.table_schema = $2") args = append(args, schema) } else { s = fmt.Sprintf(s, "") From 01e1e98dd5ebf06f8ebbedbc8d9e538f8609368a Mon Sep 17 00:00:00 2001 From: lafriks Date: Sun, 6 Sep 2020 08:22:34 +0000 Subject: [PATCH 28/61] Do not ever quote asterisk symbol. Fixes #1780 (#1781) Do not ever quote asterisk symbol. Fixes #1780 Co-authored-by: Lauris BH Reviewed-on: https://gitea.com/xorm/xorm/pulls/1781 Reviewed-by: Lunny Xiao --- schemas/quote.go | 8 +++----- schemas/quote_test.go | 9 +++++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/schemas/quote.go b/schemas/quote.go index c44abe25..a0070048 100644 --- a/schemas/quote.go +++ b/schemas/quote.go @@ -82,9 +82,7 @@ func (q Quoter) JoinWrite(b *strings.Builder, a []string, sep string) error { return err } } - if s != "*" { - q.QuoteTo(b, strings.TrimSpace(s)) - } + q.QuoteTo(b, strings.TrimSpace(s)) } return nil } @@ -143,7 +141,7 @@ func (q Quoter) quoteWordTo(buf *strings.Builder, word string) error { } isReserved := q.IsReserved(realWord) - if isReserved { + if isReserved && realWord != "*" { if err := buf.WriteByte(q.Prefix); err != nil { return err } @@ -151,7 +149,7 @@ func (q Quoter) quoteWordTo(buf *strings.Builder, word string) error { if _, err := buf.WriteString(realWord); err != nil { return err } - if isReserved { + if isReserved && realWord != "*" { return buf.WriteByte(q.Suffix) } diff --git a/schemas/quote_test.go b/schemas/quote_test.go index 708b450e..8e351dc0 100644 --- a/schemas/quote_test.go +++ b/schemas/quote_test.go @@ -22,6 +22,7 @@ func TestAlwaysQuoteTo(t *testing.T) { {"[mytable]", "`mytable`"}, {"[mytable]", `[mytable]`}, {`["mytable"]`, `"mytable"`}, + {`[mytable].*`, `[mytable].*`}, {"[myschema].[mytable]", "myschema.mytable"}, {"[myschema].[mytable]", "`myschema`.mytable"}, {"[myschema].[mytable]", "myschema.`mytable`"}, @@ -65,6 +66,7 @@ func TestReversedQuoteTo(t *testing.T) { {"[mytable]", "mytable"}, {"[mytable]", "`mytable`"}, {"[mytable]", `[mytable]`}, + {"[mytable].*", `[mytable].*`}, {`"mytable"`, `"mytable"`}, {"myschema.[mytable]", "myschema.mytable"}, {"myschema.[mytable]", "`myschema`.mytable"}, @@ -98,6 +100,7 @@ func TestNoQuoteTo(t *testing.T) { {"mytable", "mytable"}, {"mytable", "`mytable`"}, {"mytable", `[mytable]`}, + {"mytable.*", `[mytable].*`}, {`"mytable"`, `"mytable"`}, {"myschema.mytable", "myschema.mytable"}, {"myschema.mytable", "`myschema`.mytable"}, @@ -127,6 +130,8 @@ func TestJoin(t *testing.T) { assert.EqualValues(t, "[a],[b]", quoter.Join([]string{"a", " b"}, ",")) + assert.EqualValues(t, "[a].*,[b].[c]", quoter.Join([]string{"a.*", " b.c"}, ",")) + assert.EqualValues(t, "[f1], [f2], [f3]", quoter.Join(cols, ", ")) quoter.IsReserved = AlwaysNoReserve @@ -134,11 +139,11 @@ func TestJoin(t *testing.T) { } func TestStrings(t *testing.T) { - cols := []string{"f1", "f2", "t3.f3"} + cols := []string{"f1", "f2", "t3.f3", "t4.*"} quoter := Quoter{'[', ']', AlwaysReserve} quotedCols := quoter.Strings(cols) - assert.EqualValues(t, []string{"[f1]", "[f2]", "[t3].[f3]"}, quotedCols) + assert.EqualValues(t, []string{"[f1]", "[f2]", "[t3].[f3]", "[t4].*"}, quotedCols) } func TestTrim(t *testing.T) { From b4229306172900cc0bce6eab4e0036b3649e4432 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Tue, 8 Sep 2020 01:36:50 +0000 Subject: [PATCH 29/61] Fix warnings with schema Sync2 with default varchar as NVARCHAR (#1783) prod CI Merge branch 'fix-1782-MSSQL-nvarchar-fixes' of gitea.com:zeripath/xorm into fix-1782-MSSQL-nvarchar-fixes map "character" to Char for postgres Signed-off-by: Andrew Thornton Merge branch 'master' into fix-1782-MSSQL-nvarchar-fixes Postgres (and cockroachDB by inheritance) maps Char to Varchar Signed-off-by: Andrew Thornton fix test Add a few more column testcases in light of postgres weirdness prod CI prod CI prod CI Properly handle MAX Signed-off-by: Andrew Thornton Add tests for Test and Char columns Signed-off-by: Andrew Thornton prod CI fix test Signed-off-by: Andrew Thornton Remove the duplicate mssql drone test and add a specific sync test Signed-off-by: Andrew Thornton add depends_on (2) Signed-off-by: Andrew Thornton add depends_on Signed-off-by: Andrew Thornton add nvarchar as a testcase Signed-off-by: Andrew Thornton Set defaultVarchar to upper case Signed-off-by: Andrew Thornton Fix length issue Signed-off-by: Andrew Thornton schemas.Text should map to db.defaultVarchar Signed-off-by: Andrew Thornton Add failing test Signed-off-by: Andrew Thornton Reviewed-on: https://gitea.com/xorm/xorm/pulls/1783 Reviewed-by: Lunny Xiao --- Makefile | 3 ++ dialects/mssql.go | 32 ++++++++++++-- dialects/postgres.go | 6 ++- integrations/session_schema_test.go | 66 +++++++++++++++++++++++++++++ integrations/tests.go | 1 + 5 files changed, 104 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index ed873883..092f23b3 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ TEST_MSSQL_USERNAME ?= sa TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1 TEST_MSSQL_DEFAULT_VARCHAR ?= varchar TEST_MSSQL_DEFAULT_CHAR ?= char +TEST_MSSQL_DO_NVARCHAR_OVERRIDE_TEST ?= true TEST_MYSQL_HOST ?= mysql:3306 TEST_MYSQL_CHARSET ?= utf8 @@ -147,6 +148,7 @@ test-mssql: go-check $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mssql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ -conn_str="server=$(TEST_MSSQL_HOST);user id=$(TEST_MSSQL_USERNAME);password=$(TEST_MSSQL_PASSWORD);database=$(TEST_MSSQL_DBNAME)" \ -default_varchar=$(TEST_MSSQL_DEFAULT_VARCHAR) -default_char=$(TEST_MSSQL_DEFAULT_CHAR) \ + -do_nvarchar_override_test=$(TEST_MSSQL_DO_NVARCHAR_OVERRIDE_TEST) \ -coverprofile=mssql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic .PNONY: test-mssql\#% @@ -154,6 +156,7 @@ test-mssql\#%: go-check $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=mssql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ -conn_str="server=$(TEST_MSSQL_HOST);user id=$(TEST_MSSQL_USERNAME);password=$(TEST_MSSQL_PASSWORD);database=$(TEST_MSSQL_DBNAME)" \ -default_varchar=$(TEST_MSSQL_DEFAULT_VARCHAR) -default_char=$(TEST_MSSQL_DEFAULT_CHAR) \ + -do_nvarchar_override_test=$(TEST_MSSQL_DO_NVARCHAR_OVERRIDE_TEST) \ -coverprofile=mssql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic .PNONY: test-mymysql diff --git a/dialects/mssql.go b/dialects/mssql.go index d76a8c6c..8e76e538 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -229,7 +229,7 @@ func (db *mssql) SetParams(params map[string]string) { var t = strings.ToUpper(defaultVarchar) switch t { case "NVARCHAR", "VARCHAR": - db.defaultVarchar = defaultVarchar + db.defaultVarchar = t default: db.defaultVarchar = "VARCHAR" } @@ -242,7 +242,7 @@ func (db *mssql) SetParams(params map[string]string) { var t = strings.ToUpper(defaultChar) switch t { case "NCHAR", "CHAR": - db.defaultChar = defaultChar + db.defaultChar = t default: db.defaultChar = "CHAR" } @@ -285,7 +285,7 @@ func (db *mssql) SQLType(c *schemas.Column) string { case schemas.MediumInt: res = schemas.Int case schemas.Text, schemas.MediumText, schemas.TinyText, schemas.LongText, schemas.Json: - res = schemas.Varchar + "(MAX)" + res = db.defaultVarchar + "(MAX)" case schemas.Double: res = schemas.Real case schemas.Uuid: @@ -297,10 +297,26 @@ func (db *mssql) SQLType(c *schemas.Column) string { case schemas.BigInt: res = schemas.BigInt c.Length = 0 + case schemas.NVarchar: + res = t + if c.Length == -1 { + res += "(MAX)" + } case schemas.Varchar: res = db.defaultVarchar + if c.Length == -1 { + res += "(MAX)" + } case schemas.Char: res = db.defaultChar + if c.Length == -1 { + res += "(MAX)" + } + case schemas.NChar: + res = t + if c.Length == -1 { + res += "(MAX)" + } default: res = t } @@ -424,8 +440,18 @@ func (db *mssql) GetColumns(queryer core.Queryer, ctx context.Context, tableName col.SQLType = schemas.SQLType{Name: schemas.TimeStampz, DefaultLength: 0, DefaultLength2: 0} case "NVARCHAR": col.SQLType = schemas.SQLType{Name: schemas.NVarchar, DefaultLength: 0, DefaultLength2: 0} + if col.Length > 0 { + col.Length /= 2 + col.Length2 /= 2 + } case "IMAGE": col.SQLType = schemas.SQLType{Name: schemas.VarBinary, DefaultLength: 0, DefaultLength2: 0} + case "NCHAR": + if col.Length > 0 { + col.Length /= 2 + col.Length2 /= 2 + } + fallthrough default: if _, ok := schemas.SqlTypes[ct]; ok { col.SQLType = schemas.SQLType{Name: ct, DefaultLength: 0, DefaultLength2: 0} diff --git a/dialects/postgres.go b/dialects/postgres.go index 3c1d53c0..a2c0de74 100644 --- a/dialects/postgres.go +++ b/dialects/postgres.go @@ -857,6 +857,8 @@ func (db *postgres) SQLType(c *schemas.Column) string { res = schemas.Real case schemas.TinyText, schemas.MediumText, schemas.LongText: res = schemas.Text + case schemas.NChar: + res = schemas.Char case schemas.NVarchar: res = schemas.Varchar case schemas.Uuid: @@ -1086,8 +1088,10 @@ WHERE n.nspname= s.table_schema AND c.relkind = 'r'::char AND c.relname = $1%s A col.Nullable = (isNullable == "YES") switch strings.ToLower(dataType) { - case "character varying", "character", "string": + case "character varying", "string": col.SQLType = schemas.SQLType{Name: schemas.Varchar, DefaultLength: 0, DefaultLength2: 0} + case "character": + col.SQLType = schemas.SQLType{Name: schemas.Char, DefaultLength: 0, DefaultLength2: 0} case "timestamp without time zone": col.SQLType = schemas.SQLType{Name: schemas.DateTime, DefaultLength: 0, DefaultLength2: 0} case "timestamp with time zone": diff --git a/integrations/session_schema_test.go b/integrations/session_schema_test.go index 005b6619..3f8f810b 100644 --- a/integrations/session_schema_test.go +++ b/integrations/session_schema_test.go @@ -102,6 +102,9 @@ func TestSyncTable(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 1, len(tables)) assert.EqualValues(t, "sync_table1", tables[0].Name) + tableInfo, err := testEngine.TableInfo(new(SyncTable1)) + assert.NoError(t, err) + assert.EqualValues(t, testEngine.Dialect().SQLType(tables[0].GetColumn("name")), testEngine.Dialect().SQLType(tableInfo.GetColumn("name"))) assert.NoError(t, testEngine.Sync2(new(SyncTable2))) @@ -109,6 +112,9 @@ func TestSyncTable(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 1, len(tables)) assert.EqualValues(t, "sync_table1", tables[0].Name) + tableInfo, err = testEngine.TableInfo(new(SyncTable2)) + assert.NoError(t, err) + assert.EqualValues(t, testEngine.Dialect().SQLType(tables[0].GetColumn("name")), testEngine.Dialect().SQLType(tableInfo.GetColumn("name"))) assert.NoError(t, testEngine.Sync2(new(SyncTable3))) @@ -116,6 +122,9 @@ func TestSyncTable(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 1, len(tables)) assert.EqualValues(t, "sync_table1", tables[0].Name) + tableInfo, err = testEngine.TableInfo(new(SyncTable3)) + assert.NoError(t, err) + assert.EqualValues(t, testEngine.Dialect().SQLType(tables[0].GetColumn("name")), testEngine.Dialect().SQLType(tableInfo.GetColumn("name"))) } func TestSyncTable2(t *testing.T) { @@ -143,6 +152,63 @@ func TestSyncTable2(t *testing.T) { assert.EqualValues(t, colMapper.Obj2Table("NewCol"), tables[0].Columns()[3].Name) } +func TestSyncTable3(t *testing.T) { + type SyncTable5 struct { + Id int64 + Name string + Text string `xorm:"TEXT"` + Char byte `xorm:"CHAR(1)"` + TenChar [10]byte `xorm:"CHAR(10)"` + TenVarChar string `xorm:"VARCHAR(10)"` + } + + assert.NoError(t, PrepareEngine()) + + assert.NoError(t, testEngine.Sync2(new(SyncTable5))) + + tables, err := testEngine.DBMetas() + assert.NoError(t, err) + tableInfo, err := testEngine.TableInfo(new(SyncTable5)) + assert.NoError(t, err) + assert.EqualValues(t, testEngine.Dialect().SQLType(tableInfo.GetColumn("name")), testEngine.Dialect().SQLType(tables[0].GetColumn("name"))) + assert.EqualValues(t, testEngine.Dialect().SQLType(tableInfo.GetColumn("text")), testEngine.Dialect().SQLType(tables[0].GetColumn("text"))) + assert.EqualValues(t, testEngine.Dialect().SQLType(tableInfo.GetColumn("char")), testEngine.Dialect().SQLType(tables[0].GetColumn("char"))) + assert.EqualValues(t, testEngine.Dialect().SQLType(tableInfo.GetColumn("ten_char")), testEngine.Dialect().SQLType(tables[0].GetColumn("ten_char"))) + assert.EqualValues(t, testEngine.Dialect().SQLType(tableInfo.GetColumn("ten_var_char")), testEngine.Dialect().SQLType(tables[0].GetColumn("ten_var_char"))) + + if *doNVarcharTest { + var oldDefaultVarchar string + var oldDefaultChar string + oldDefaultVarchar, *defaultVarchar = *defaultVarchar, "nvarchar" + oldDefaultChar, *defaultChar = *defaultChar, "nchar" + testEngine.Dialect().SetParams(map[string]string{ + "DEFAULT_VARCHAR": *defaultVarchar, + "DEFAULT_CHAR": *defaultChar, + }) + defer func() { + *defaultVarchar = oldDefaultVarchar + *defaultChar = oldDefaultChar + testEngine.Dialect().SetParams(map[string]string{ + "DEFAULT_VARCHAR": *defaultVarchar, + "DEFAULT_CHAR": *defaultChar, + }) + }() + assert.NoError(t, PrepareEngine()) + + assert.NoError(t, testEngine.Sync2(new(SyncTable5))) + + tables, err := testEngine.DBMetas() + assert.NoError(t, err) + tableInfo, err := testEngine.TableInfo(new(SyncTable5)) + assert.NoError(t, err) + assert.EqualValues(t, testEngine.Dialect().SQLType(tableInfo.GetColumn("name")), testEngine.Dialect().SQLType(tables[0].GetColumn("name"))) + assert.EqualValues(t, testEngine.Dialect().SQLType(tableInfo.GetColumn("text")), testEngine.Dialect().SQLType(tables[0].GetColumn("text"))) + assert.EqualValues(t, testEngine.Dialect().SQLType(tableInfo.GetColumn("char")), testEngine.Dialect().SQLType(tables[0].GetColumn("char"))) + assert.EqualValues(t, testEngine.Dialect().SQLType(tableInfo.GetColumn("ten_char")), testEngine.Dialect().SQLType(tables[0].GetColumn("ten_char"))) + assert.EqualValues(t, testEngine.Dialect().SQLType(tableInfo.GetColumn("ten_var_char")), testEngine.Dialect().SQLType(tables[0].GetColumn("ten_var_char"))) + } +} + func TestIsTableExist(t *testing.T) { assert.NoError(t, PrepareEngine()) diff --git a/integrations/tests.go b/integrations/tests.go index b135bd90..31fa99bf 100644 --- a/integrations/tests.go +++ b/integrations/tests.go @@ -35,6 +35,7 @@ var ( schema = flag.String("schema", "", "specify the schema") ignoreSelectUpdate = flag.Bool("ignore_select_update", false, "ignore select update if implementation difference, only for tidb") ingoreUpdateLimit = flag.Bool("ignore_update_limit", false, "ignore update limit if implementation difference, only for cockroach") + doNVarcharTest = flag.Bool("do_nvarchar_override_test", false, "do nvarchar override test in sync table, only for mssql") quotePolicyStr = flag.String("quote", "always", "quote could be always, none, reversed") defaultVarchar = flag.String("default_varchar", "varchar", "default varchar type, mssql only, could be varchar or nvarchar, default is varchar") defaultChar = flag.String("default_char", "char", "default char type, mssql only, could be char or nchar, default is char") From 1b200bdcbabf02c141802336c583250e15ebd34e Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 8 Sep 2020 15:40:26 +0000 Subject: [PATCH 30/61] Fix bug of ToDB when update on a nil pointer (#1786) Fix test Fix bug Fix bug Add test for insert nil struct field Fix test Fix bug of ToDB when update on a nil pointer Reviewed-on: https://gitea.com/xorm/xorm/pulls/1786 --- integrations/session_update_test.go | 54 +++++++++++++++++++++++++++-- internal/statements/update.go | 2 +- internal/statements/values.go | 25 +++++++------ 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/integrations/session_update_test.go b/integrations/session_update_test.go index 1bc1f32a..07c722bd 100644 --- a/integrations/session_update_test.go +++ b/integrations/session_update_test.go @@ -188,6 +188,9 @@ func TestForUpdate(t *testing.T) { // lock is NOT used wg.Add(1) + + wg2 := &sync.WaitGroup{} + wg2.Add(1) go func() { f3 := new(ForUpdate) session3.Where("id = ?", 1) @@ -201,10 +204,10 @@ func TestForUpdate(t *testing.T) { t.Errorf("read lock failed") } wg.Done() + wg2.Done() }() - // wait for go rountines - time.Sleep(50 * time.Millisecond) + wg2.Wait() f := new(ForUpdate) f.Name = "updated by session1" @@ -1350,3 +1353,50 @@ func TestUpdateMultiplePK(t *testing.T) { _, err = testEngine.ID(&MySlice{test.Id, test.Name}).Update(test) assert.NoError(t, err) } + +type TestFieldType1 struct { + cb []byte +} + +func (a *TestFieldType1) FromDB(src []byte) error { + a.cb = src + return nil +} + +func (a TestFieldType1) ToDB() ([]byte, error) { + return a.cb, nil +} + +type TestTable1 struct { + Id int64 + Field1 *TestFieldType1 `xorm:"text"` + UpdateTime time.Time +} + +func TestNilFromDB(t *testing.T) { + assert.NoError(t, PrepareEngine()) + assertSync(t, new(TestTable1)) + + cnt, err := testEngine.Insert(&TestTable1{ + Field1: &TestFieldType1{ + cb: []byte("string"), + }, + UpdateTime: time.Now(), + }) + assert.NoError(t, err) + assert.EqualValues(t, 1, cnt) + + cnt, err = testEngine.Update(TestTable1{ + UpdateTime: time.Now().Add(time.Second), + }, TestTable1{ + Id: 1, + }) + assert.NoError(t, err) + assert.EqualValues(t, 1, cnt) + + cnt, err = testEngine.Insert(&TestTable1{ + UpdateTime: time.Now(), + }) + assert.NoError(t, err) + assert.EqualValues(t, 1, cnt) +} diff --git a/internal/statements/update.go b/internal/statements/update.go index b6ae118e..ff5f82b7 100644 --- a/internal/statements/update.go +++ b/internal/statements/update.go @@ -130,7 +130,7 @@ func (statement *Statement) BuildUpdates(tableValue reflect.Value, } } - if structConvert, ok := fieldValue.Interface().(convert.Conversion); ok { + if structConvert, ok := fieldValue.Interface().(convert.Conversion); ok && !fieldValue.IsNil() { data, err := structConvert.ToDB() if err != nil { return nil, nil, err diff --git a/internal/statements/values.go b/internal/statements/values.go index a1102c54..99eaa766 100644 --- a/internal/statements/values.go +++ b/internal/statements/values.go @@ -36,18 +36,21 @@ func (statement *Statement) Value2Interface(col *schemas.Column, fieldValue refl } } - if fieldConvert, ok := fieldValue.Interface().(convert.Conversion); ok { - data, err := fieldConvert.ToDB() - if err != nil { - return nil, err + isNil := fieldValue.Kind() == reflect.Ptr && fieldValue.IsNil() + if !isNil { + if fieldConvert, ok := fieldValue.Interface().(convert.Conversion); ok { + data, err := fieldConvert.ToDB() + if err != nil { + return nil, err + } + if col.SQLType.IsBlob() { + return data, nil + } + if nil == data { + return nil, nil + } + return string(data), nil } - if col.SQLType.IsBlob() { - return data, nil - } - if nil == data { - return nil, nil - } - return string(data), nil } fieldType := fieldValue.Type() From e35662b1ed25de7fc099b89be61115a42fbae816 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 8 Sep 2020 23:42:39 +0800 Subject: [PATCH 31/61] Change log for v1.0.5 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a355d95..3cead87d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,14 @@ This changelog goes through all the changes that have been made in each release without substantial changes to our git log. +## [1.0.5](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1299) - 2020-09-08 + +* BUGFIXES + * Fix bug of ToDB when update on a nil pointer (#1786) + * Fix warnings with schema Sync2 with default varchar as NVARCHAR (#1783) + * Do not ever quote asterisk symbol. Fixes #1780 (#1781) + * Fix bug on get columns for postgres (#1779) + ## [1.0.4](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1286) - 2020-09-02 * FEATURES From 0c1b815227daa28a3c55ae0319a2db3c1cf0cb51 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 9 Sep 2020 13:44:18 +0000 Subject: [PATCH 32/61] Performance improvement for columnsbyName (#1788) Performance improvement for columnsbyName Reviewed-on: https://gitea.com/xorm/xorm/pulls/1788 --- schemas/table.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/schemas/table.go b/schemas/table.go index 6c57a7e3..7ca9531f 100644 --- a/schemas/table.go +++ b/schemas/table.go @@ -58,12 +58,7 @@ func (table *Table) ColumnsSeq() []string { } func (table *Table) columnsByName(name string) []*Column { - for k, cols := range table.columnsMap { - if strings.EqualFold(k, name) { - return cols - } - } - return nil + return table.columnsMap[strings.ToLower(name)] } // GetColumn returns column according column name, if column not found, return nil From 17f28a1314376829df61d546b505cec6eae1bb53 Mon Sep 17 00:00:00 2001 From: jumpeiMano Date: Tue, 20 Oct 2020 11:11:04 +0800 Subject: [PATCH 33/61] feat: define xorm.FromDialectAndDB (#1812) refactor: rename the function name feat: define xorm.FromDialectAndDB Co-authored-by: jumpeiMano Reviewed-on: https://gitea.com/xorm/xorm/pulls/1812 Reviewed-by: Lunny Xiao Co-Authored-By: jumpeiMano Co-Committed-By: jumpeiMano --- engine.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/engine.go b/engine.go index 4159a7b2..6c894e74 100644 --- a/engine.go +++ b/engine.go @@ -61,6 +61,10 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) { return nil, err } + return newEngine(driverName, dataSourceName, dialect, db) +} + +func newEngine(driverName, dataSourceName string, dialect dialects.Dialect, db *core.DB) (*Engine, error) { cacherMgr := caches.NewManager() mapper := names.NewCacheMapper(new(names.SnakeMapper)) tagParser := tags.NewParser("xorm", dialect, mapper, mapper, cacherMgr) @@ -88,7 +92,7 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) { engine.SetLogger(log.NewLoggerAdapter(logger)) runtime.SetFinalizer(engine, func(engine *Engine) { - engine.Close() + _ = engine.Close() }) return engine, nil @@ -101,6 +105,14 @@ func NewEngineWithParams(driverName string, dataSourceName string, params map[st return engine, err } +// NewEngineWithDialectAndDB new a db manager according to the parameter. +// If you do not want to use your own dialect or db, please use NewEngine. +// For creating dialect, you can call dialects.OpenDialect. And, for creating db, +// you can call core.Open or core.FromDB. +func NewEngineWithDialectAndDB(driverName, dataSourceName string, dialect dialects.Dialect, db *core.DB) (*Engine, error) { + return newEngine(driverName, dataSourceName, dialect, db) +} + // EnableSessionID if enable session id func (engine *Engine) EnableSessionID(enable bool) { engine.logSessionID = enable From beac298c02bfe40f54e7b82bbfdf2b090fb4f06a Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 3 Nov 2020 17:10:35 +0800 Subject: [PATCH 34/61] Fix json tag with other type (#1822) Fix json tag with other type Reviewed-on: https://gitea.com/xorm/xorm/pulls/1822 Co-Authored-By: Lunny Xiao Co-Committed-By: Lunny Xiao --- integrations/session_get_test.go | 54 ++++++++++++++++++++++++++++++++ internal/statements/statement.go | 4 +-- internal/statements/update.go | 2 +- internal/statements/values.go | 2 +- schemas/column.go | 1 + session.go | 4 +-- tags/tag.go | 3 ++ 7 files changed, 64 insertions(+), 6 deletions(-) diff --git a/integrations/session_get_test.go b/integrations/session_get_test.go index 4e50f9ab..e4d9f82e 100644 --- a/integrations/session_get_test.go +++ b/integrations/session_get_test.go @@ -394,6 +394,60 @@ func TestJSONString(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 1, len(jss)) assert.True(t, `["1","2"]` == jss[0].Content || `["1", "2"]` == jss[0].Content) + + type JsonAnonymousStruct struct { + Id int64 + JsonString `xorm:"'json_string' JSON LONGTEXT"` + } + + assertSync(t, new(JsonAnonymousStruct)) + + _, err = testEngine.Insert(&JsonAnonymousStruct{ + JsonString: JsonString{ + Content: "1", + }, + }) + assert.NoError(t, err) + + var jas JsonAnonymousStruct + has, err = testEngine.Get(&jas) + assert.NoError(t, err) + assert.True(t, has) + assert.EqualValues(t, 1, jas.Id) + assert.EqualValues(t, "1", jas.Content) + + var jass []JsonAnonymousStruct + err = testEngine.Find(&jass) + assert.NoError(t, err) + assert.EqualValues(t, 1, len(jass)) + assert.EqualValues(t, "1", jass[0].Content) + + type JsonStruct struct { + Id int64 + JSON JsonString `xorm:"'json_string' JSON LONGTEXT"` + } + + assertSync(t, new(JsonStruct)) + + _, err = testEngine.Insert(&JsonStruct{ + JSON: JsonString{ + Content: "2", + }, + }) + assert.NoError(t, err) + + var jst JsonStruct + has, err = testEngine.Get(&jst) + assert.NoError(t, err) + assert.True(t, has) + assert.EqualValues(t, 1, jst.Id) + assert.EqualValues(t, "2", jst.JSON.Content) + + var jsts []JsonStruct + err = testEngine.Find(&jsts) + assert.NoError(t, err) + assert.EqualValues(t, 1, len(jsts)) + assert.EqualValues(t, "2", jsts[0].JSON.Content) } func TestGetActionMapping(t *testing.T) { diff --git a/internal/statements/statement.go b/internal/statements/statement.go index ed7bdaeb..a4294bec 100644 --- a/internal/statements/statement.go +++ b/internal/statements/statement.go @@ -704,7 +704,7 @@ func (statement *Statement) buildConds2(table *schemas.Table, bean interface{}, col.SQLType.IsBlob() || col.SQLType.Name == schemas.TimeStampz) { continue } - if col.SQLType.IsJson() { + if col.IsJSON { continue } @@ -813,7 +813,7 @@ func (statement *Statement) buildConds2(table *schemas.Table, bean interface{}, continue } } else { - if col.SQLType.IsJson() { + if col.IsJSON { if col.SQLType.IsText() { bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface()) if err != nil { diff --git a/internal/statements/update.go b/internal/statements/update.go index ff5f82b7..251880b2 100644 --- a/internal/statements/update.go +++ b/internal/statements/update.go @@ -204,7 +204,7 @@ func (statement *Statement) BuildUpdates(tableValue reflect.Value, continue } } else { - if !col.SQLType.IsJson() { + if !col.IsJSON { table, err := statement.tagParser.ParseWithCache(fieldValue) if err != nil { val = fieldValue.Interface() diff --git a/internal/statements/values.go b/internal/statements/values.go index 99eaa766..71327c55 100644 --- a/internal/statements/values.go +++ b/internal/statements/values.go @@ -86,7 +86,7 @@ func (statement *Statement) Value2Interface(col *schemas.Column, fieldValue refl return t.Float64, nil } - if !col.SQLType.IsJson() { + if !col.IsJSON { // !! 增加支持driver.Valuer接口的结构,如sql.NullString if v, ok := fieldValue.Interface().(driver.Valuer); ok { return v.Value() diff --git a/schemas/column.go b/schemas/column.go index db66a3a6..4f32afab 100644 --- a/schemas/column.go +++ b/schemas/column.go @@ -51,6 +51,7 @@ type Column struct { func NewColumn(name, fieldName string, sqlType SQLType, len1, len2 int, nullable bool) *Column { return &Column{ Name: name, + IsJSON: sqlType.IsJson(), TableName: "", FieldName: fieldName, SQLType: sqlType, diff --git a/session.go b/session.go index b6ab3eb5..17abd453 100644 --- a/session.go +++ b/session.go @@ -503,7 +503,7 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, b fieldType := fieldValue.Type() hasAssigned := false - if col.SQLType.IsJson() { + if col.IsJSON { var bs []byte if rawValueType.Kind() == reflect.String { bs = []byte(vv.String()) @@ -683,7 +683,7 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, b session.engine.logger.Errorf("sql.Sanner error: %v", err) hasAssigned = false } - } else if col.SQLType.IsJson() { + } else if col.IsJSON { if rawValueType.Kind() == reflect.String { hasAssigned = true x := reflect.New(fieldType) diff --git a/tags/tag.go b/tags/tag.go index ee3f1e82..bb5b5838 100644 --- a/tags/tag.go +++ b/tags/tag.go @@ -226,6 +226,9 @@ func CommentTagHandler(ctx *Context) error { // SQLTypeTagHandler describes SQL Type tag handler func SQLTypeTagHandler(ctx *Context) error { ctx.col.SQLType = schemas.SQLType{Name: ctx.tagName} + if strings.EqualFold(ctx.tagName, "JSON") { + ctx.col.IsJSON = true + } if len(ctx.params) > 0 { if ctx.tagName == schemas.Enum { ctx.col.EnumOptions = make(map[string]int) From acb337ba1f6ef41a74054380537e28ed4bd735ee Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 9 Nov 2020 12:23:14 +0800 Subject: [PATCH 35/61] Fix find and count bug with cols (#1826) Fix find and count bug with cols Reviewed-on: https://gitea.com/xorm/xorm/pulls/1826 Co-Authored-By: Lunny Xiao Co-Committed-By: Lunny Xiao --- integrations/session_find_test.go | 7 +++++++ session_find.go | 3 +++ 2 files changed, 10 insertions(+) diff --git a/integrations/session_find_test.go b/integrations/session_find_test.go index 95cf9384..c3e99183 100644 --- a/integrations/session_find_test.go +++ b/integrations/session_find_test.go @@ -552,6 +552,13 @@ func TestFindAndCountOneFunc(t *testing.T) { assert.EqualValues(t, 1, len(results)) assert.EqualValues(t, 1, cnt) + results = make([]FindAndCountStruct, 0, 1) + cnt, err = testEngine.Where("msg = ?", true).Cols("id", "content", "msg"). + Limit(1).FindAndCount(&results) + assert.NoError(t, err) + assert.EqualValues(t, 1, len(results)) + assert.EqualValues(t, 1, cnt) + results = make([]FindAndCountStruct, 0, 1) cnt, err = testEngine.Where("msg = ?", true).Desc("id"). Limit(1).Cols("content").FindAndCount(&results) diff --git a/session_find.go b/session_find.go index 642093f2..0daea005 100644 --- a/session_find.go +++ b/session_find.go @@ -57,6 +57,9 @@ func (session *Session) FindAndCount(rowsSlicePtr interface{}, condiBean ...inte if session.statement.SelectStr != "" { session.statement.SelectStr = "" } + if len(session.statement.ColumnMap) > 0 { + session.statement.ColumnMap = []string{} + } if session.statement.OrderStr != "" { session.statement.OrderStr = "" } From 3472d80a6dd1ad3b510558712b449a7b0cff2e9d Mon Sep 17 00:00:00 2001 From: finelog Date: Wed, 2 Dec 2020 22:07:35 +0800 Subject: [PATCH 36/61] prevent panic when struct with unexport field (#1839) prevent panic when struct with unexport field add test for prevent panic when vanial struct with unexport field panic minor code fix minor fix part II Co-authored-by: finelog Reviewed-on: https://gitea.com/xorm/xorm/pulls/1839 Reviewed-by: Lunny Xiao Co-Authored-By: finelog Co-Committed-By: finelog --- tags/parser.go | 4 +++- tags/parser_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/tags/parser.go b/tags/parser.go index add30a13..a301d124 100644 --- a/tags/parser.go +++ b/tags/parser.go @@ -253,7 +253,7 @@ func (parser *Parser) Parse(v reflect.Value) (*schemas.Table, error) { addIndex(indexName, table, col, indexType) } } - } else { + } else if fieldValue.CanSet() { var sqlType schemas.SQLType if fieldValue.CanAddr() { if _, ok := fieldValue.Addr().Interface().(convert.Conversion); ok { @@ -272,6 +272,8 @@ func (parser *Parser) Parse(v reflect.Value) (*schemas.Table, error) { if fieldType.Kind() == reflect.Int64 && (strings.ToUpper(col.FieldName) == "ID" || strings.HasSuffix(strings.ToUpper(col.FieldName), ".ID")) { idFieldColName = col.Name } + } else { + continue } if col.IsAutoIncrement { col.Nullable = false diff --git a/tags/parser_test.go b/tags/parser_test.go index 6065bf2e..ff304a5b 100644 --- a/tags/parser_test.go +++ b/tags/parser_test.go @@ -42,3 +42,41 @@ func TestParseTableName(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, "p_parseTableName", table.Name) } + +func TestUnexportField(t *testing.T) { + parser := NewParser( + "xorm", + dialects.QueryDialect("mysql"), + names.SnakeMapper{}, + names.SnakeMapper{}, + caches.NewManager(), + ) + + type VanilaStruct struct { + private int + Public int + } + table, err := parser.Parse(reflect.ValueOf(new(VanilaStruct))) + assert.NoError(t, err) + assert.EqualValues(t, "vanila_struct", table.Name) + assert.EqualValues(t, 1, len(table.Columns())) + + for _, col := range table.Columns() { + assert.EqualValues(t, "public", col.Name) + assert.NotEqual(t, "private", col.Name) + } + + type TaggedStruct struct { + private int `xorm:"private"` + Public int `xorm:"-"` + } + table, err = parser.Parse(reflect.ValueOf(new(TaggedStruct))) + assert.NoError(t, err) + assert.EqualValues(t, "tagged_struct", table.Name) + assert.EqualValues(t, 1, len(table.Columns())) + + for _, col := range table.Columns() { + assert.EqualValues(t, "private", col.Name) + assert.NotEqual(t, "public", col.Name) + } +} From 7c8d3f1ad95dd560468df06f2622af8de6bbda38 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 5 Jan 2021 10:37:41 +0800 Subject: [PATCH 37/61] Fix bug when modify column on mssql (#1849) Reviewed-on: https://gitea.com/xorm/xorm/pulls/1849 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- dialects/dialect.go | 2 +- dialects/mssql.go | 5 +++++ integrations/session_schema_test.go | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/dialects/dialect.go b/dialects/dialect.go index dc96f73a..18b781a1 100644 --- a/dialects/dialect.go +++ b/dialects/dialect.go @@ -163,7 +163,7 @@ func (db *Base) DropIndexSQL(tableName string, index *schemas.Index) string { func (db *Base) ModifyColumnSQL(tableName string, col *schemas.Column) string { s, _ := ColumnString(db.dialect, col, false) - return fmt.Sprintf("alter table %s MODIFY COLUMN %s", tableName, s) + return fmt.Sprintf("ALTER TABLE %s MODIFY COLUMN %s", tableName, s) } func (b *Base) ForUpdateSQL(query string) string { diff --git a/dialects/mssql.go b/dialects/mssql.go index 8e76e538..5340455d 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -368,6 +368,11 @@ func (db *mssql) DropTableSQL(tableName string) (string, bool) { "DROP TABLE \"%s\"", tableName, tableName), true } +func (db *mssql) ModifyColumnSQL(tableName string, col *schemas.Column) string { + s, _ := ColumnString(db.dialect, col, false) + return fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s", tableName, s) +} + func (db *mssql) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { args := []interface{}{idxName} sql := "select name from sysindexes where id=object_id('" + tableName + "') and name=?" diff --git a/integrations/session_schema_test.go b/integrations/session_schema_test.go index 3f8f810b..72779e11 100644 --- a/integrations/session_schema_test.go +++ b/integrations/session_schema_test.go @@ -10,6 +10,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "xorm.io/xorm/schemas" ) func TestStoreEngine(t *testing.T) { @@ -396,3 +397,26 @@ func TestSync2_Default(t *testing.T) { assertSync(t, new(TestSync2Default)) assert.NoError(t, testEngine.Sync2(new(TestSync2Default))) } + +func TestModifyColum(t *testing.T) { + type TestModifyColumn struct { + Id int64 + UserId int64 `xorm:"default(1)"` + IsMember bool `xorm:"default(true)"` + Name string `xorm:"char(10)"` + } + + assert.NoError(t, PrepareEngine()) + assertSync(t, new(TestModifyColumn)) + + alterSQL := testEngine.Dialect().ModifyColumnSQL("test_modify_column", &schemas.Column{ + Name: "name", + SQLType: schemas.SQLType{ + Name: "VARCHAR", + }, + Length: 16, + Nullable: false, + }) + _, err := testEngine.Exec(alterSQL) + assert.NoError(t, err) +} From b65276da851d1773281b7129049495e28e070608 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 5 Jan 2021 10:42:14 +0800 Subject: [PATCH 38/61] Fix index (#1841) Reviewed-on: https://gitea.com/xorm/xorm/pulls/1841 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- dialects/sqlite3.go | 2 +- engine.go | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/dialects/sqlite3.go b/dialects/sqlite3.go index 73f98beb..62a38397 100644 --- a/dialects/sqlite3.go +++ b/dialects/sqlite3.go @@ -483,7 +483,7 @@ func (db *sqlite3) GetIndexes(queryer core.Queryer, ctx context.Context, tableNa continue } - indexName := strings.Trim(sql[nNStart+6:nNEnd], "` []'\"") + indexName := strings.Trim(strings.TrimSpace(sql[nNStart+6:nNEnd]), "`[]'\"") var isRegular bool if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) { index.Name = indexName[5+len(tableName):] diff --git a/engine.go b/engine.go index 6c894e74..873fcdc1 100644 --- a/engine.go +++ b/engine.go @@ -359,13 +359,16 @@ func (engine *Engine) loadTableInfo(table *schemas.Table) error { var seq int for _, index := range indexes { for _, name := range index.Cols { - parts := strings.Split(name, " ") + parts := strings.Split(strings.TrimSpace(name), " ") if len(parts) > 1 { if parts[1] == "DESC" { seq = 1 + } else if parts[1] == "ASC" { + seq = 0 } } - if col := table.GetColumn(parts[0]); col != nil { + var colName = strings.Trim(parts[0], `"`) + if col := table.GetColumn(colName); col != nil { col.Indexes[index.Name] = index.Type } else { return fmt.Errorf("Unknown col %s seq %d, in index %v of table %v, columns %v", name, seq, index.Name, table.Name, table.ColumnsSeq()) From 26b248c5691f19a62ed607dfaaca81fd15671f1b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 5 Jan 2021 10:55:36 +0800 Subject: [PATCH 39/61] Fix update bug (#1823) Fix #1821 Reviewed-on: https://gitea.com/xorm/xorm/pulls/1823 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- integrations/session_schema_test.go | 4 ++++ integrations/session_update_test.go | 14 ++++++++++++++ session_update.go | 9 ++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/integrations/session_schema_test.go b/integrations/session_schema_test.go index 72779e11..1ef653ef 100644 --- a/integrations/session_schema_test.go +++ b/integrations/session_schema_test.go @@ -399,6 +399,10 @@ func TestSync2_Default(t *testing.T) { } func TestModifyColum(t *testing.T) { + // Since SQLITE don't support modify column SQL, currrently just ignore + if testEngine.Dialect().URI().DBType == schemas.SQLITE { + return + } type TestModifyColumn struct { Id int64 UserId int64 `xorm:"default(1)"` diff --git a/integrations/session_update_test.go b/integrations/session_update_test.go index 07c722bd..f2105e2b 100644 --- a/integrations/session_update_test.go +++ b/integrations/session_update_test.go @@ -15,6 +15,7 @@ import ( "xorm.io/xorm/internal/statements" "xorm.io/xorm/internal/utils" "xorm.io/xorm/names" + "xorm.io/xorm/schemas" ) func TestUpdateMap(t *testing.T) { @@ -48,6 +49,19 @@ func TestUpdateMap(t *testing.T) { assert.Error(t, err) assert.True(t, statements.IsIDConditionWithNoTableErr(err)) assert.EqualValues(t, 0, cnt) + + cnt, err = testEngine.Table("update_table").Update(map[string]interface{}{ + "name": "test2", + "age": 36, + }, &UpdateTable{ + Id: tb.Id, + }) + assert.NoError(t, err) + if testEngine.Dialect().URI().DBType == schemas.SQLITE { + assert.EqualValues(t, 1, cnt) + } else { + assert.EqualValues(t, 0, cnt) + } } func TestUpdateLimit(t *testing.T) { diff --git a/session_update.go b/session_update.go index 7df8c752..0adac25e 100644 --- a/session_update.go +++ b/session_update.go @@ -273,8 +273,15 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 k = ct.Elem().Kind() } if k == reflect.Struct { + var refTable = session.statement.RefTable + if refTable == nil { + refTable, err = session.engine.TableInfo(condiBean[0]) + if err != nil { + return 0, err + } + } var err error - autoCond, err = session.statement.BuildConds(session.statement.RefTable, condiBean[0], true, true, false, true, false) + autoCond, err = session.statement.BuildConds(refTable, condiBean[0], true, true, false, true, false) if err != nil { return 0, err } From 8284e5defa48331f157bff08b1b3c6f53104291d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 5 Jan 2021 11:04:22 +0800 Subject: [PATCH 40/61] Automatically convert datetime to int64 (#1715) Fix #1714 Reviewed-on: https://gitea.com/xorm/xorm/pulls/1715 Reviewed-by: Jerry Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- integrations/session_find_test.go | 23 +++++++++++++++++++++++ session_convert.go | 24 +++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/integrations/session_find_test.go b/integrations/session_find_test.go index c3e99183..0c25a1e9 100644 --- a/integrations/session_find_test.go +++ b/integrations/session_find_test.go @@ -962,3 +962,26 @@ func TestDistinctAndCols(t *testing.T) { assert.EqualValues(t, 1, len(names)) assert.EqualValues(t, "test", names[0]) } + +func TestDateTimeInt64(t *testing.T) { + type DateTimeInt64 struct { + Id int64 + TimeStamp int64 `xorm:"datetime"` + } + + assert.NoError(t, PrepareEngine()) + assertSync(t, new(DateTimeInt64)) + + ts := time.Now().Unix() + cnt, err := testEngine.Insert(&DateTimeInt64{ + TimeStamp: ts, + }) + assert.NoError(t, err) + assert.EqualValues(t, 1, cnt) + + var dts []DateTimeInt64 + err = testEngine.Find(&dts) + assert.NoError(t, err) + assert.EqualValues(t, 1, len(dts)) + assert.EqualValues(t, ts, dts[0].TimeStamp) +} diff --git a/session_convert.go b/session_convert.go index a6839947..4a4dd8be 100644 --- a/session_convert.go +++ b/session_convert.go @@ -168,7 +168,29 @@ func (session *Session) bytes2Value(col *schemas.Column, fieldValue *reflect.Val } else if strings.EqualFold(sdata, "false") { x = 0 } else { - x, err = strconv.ParseInt(sdata, 10, 64) + if col.SQLType.Name == schemas.DateTime { + if len(sdata) == 20 { + t, err := time.Parse("2006-01-02T15:04:05Z", sdata) + if err != nil { + return fmt.Errorf("arg %v as int: %s", key, err.Error()) + } + x = t.Unix() + } else if len(sdata) == 19 { + var parseFormat = "2006-01-02 15:04:05" + if sdata[10] == 'T' { + parseFormat = "2006-01-02T15:04:05" + } + t, err := time.Parse(parseFormat, sdata) + if err != nil { + return fmt.Errorf("arg %v as int: %s", key, err.Error()) + } + x = t.Unix() + } else { + x, err = strconv.ParseInt(sdata, 10, 64) + } + } else { + x, err = strconv.ParseInt(sdata, 10, 64) + } } if err != nil { return fmt.Errorf("arg %v as int: %s", key, err.Error()) From 91e0b9aa6ec4d5fbb181904539135f23d2f791a1 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 5 Jan 2021 11:06:15 +0800 Subject: [PATCH 41/61] Add changelog --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cead87d..32403a1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,20 @@ This changelog goes through all the changes that have been made in each release without substantial changes to our git log. +## [1.0.6](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1308) - 2021-01-05 + +* BUGFIXES + * Fix bug when modify column on mssql (#1849) + * Fix find and count bug with cols (#1826) + * Fix update bug (#1823) + * Fix json tag with other type (#1822) +* ENHANCEMENTS + * prevent panic when struct with unexport field (#1839) + * Automatically convert datetime to int64 (#1715) +* MISC + * Fix index (#1841) + * Performance improvement for columnsbyName (#1788) + ## [1.0.5](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1299) - 2020-09-08 * BUGFIXES From c442c5a9a8f0f81b1a3ef2f23e23e249c99e0c22 Mon Sep 17 00:00:00 2001 From: L-Angel Date: Tue, 19 Jan 2021 13:41:14 +0800 Subject: [PATCH 42/61] fix_bugs_for_mssql (#1852) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. add: support xml column type for mssql. 2. fix: array index overflow when getindexs caused by unregular indexname(eg.idx_(tablename)) Co-authored-by: Rick Reviewed-on: https://gitea.com/xorm/xorm/pulls/1852 Reviewed-by: Lunny Xiao Co-authored-by: L-Angel Co-committed-by: L-Angel --- dialects/mssql.go | 2 +- schemas/type.go | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/dialects/mssql.go b/dialects/mssql.go index 5340455d..4504eb55 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -538,7 +538,7 @@ WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =? colName = strings.Trim(colName, "` ") var isRegular bool - if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) { + if (strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName)) && len(indexName) > (5+len(tableName)) { indexName = indexName[5+len(tableName):] isRegular = true } diff --git a/schemas/type.go b/schemas/type.go index 89459a4d..f0ede296 100644 --- a/schemas/type.go +++ b/schemas/type.go @@ -68,6 +68,10 @@ func (s *SQLType) IsJson() bool { return s.Name == Json || s.Name == Jsonb } +func (s *SQLType) IsXML() bool { + return s.Name == XML +} + var ( Bit = "BIT" TinyInt = "TINYINT" @@ -128,6 +132,7 @@ var ( Json = "JSON" Jsonb = "JSONB" + XML = "XML" Array = "ARRAY" SqlTypes = map[string]int{ @@ -144,6 +149,8 @@ var ( Json: TEXT_TYPE, Jsonb: TEXT_TYPE, + XML: TEXT_TYPE, + Char: TEXT_TYPE, NChar: TEXT_TYPE, Varchar: TEXT_TYPE, From 6f4b2fd80e8bd1f9c796cfcfaffcb128202eb3f8 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 21 Jan 2021 15:08:48 +0800 Subject: [PATCH 43/61] Fix bug for mssql (#1854) Reviewed-on: https://gitea.com/xorm/xorm/pulls/1854 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- dialects/mssql.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dialects/mssql.go b/dialects/mssql.go index 4504eb55..083fb65d 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -220,6 +220,8 @@ type mssql struct { func (db *mssql) Init(uri *URI) error { db.quoter = mssqlQuoter + db.defaultChar = "CHAR" + db.defaultVarchar = "VARCHAR" return db.Base.Init(db, uri) } From 34f68a05eb77fd719aac7bc12fa82256f9abcf0e Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 21 Jan 2021 15:10:21 +0800 Subject: [PATCH 44/61] Release v1.0.7 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32403a1a..3ac229c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ This changelog goes through all the changes that have been made in each release without substantial changes to our git log. +## [1.0.7](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1336) - 2021-01-21 + +* BUGFIXES + * Fix bug for mssql (#1854) +* MISC + * fix_bugs_for_mssql (#1852) + ## [1.0.6](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1308) - 2021-01-05 * BUGFIXES From 7cd51d58fa4edbcc22720396d5f6f85c70338178 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 28 Jan 2021 10:56:03 +0800 Subject: [PATCH 45/61] Upgrade builder to v0.3.8 (#1855) Reviewed-on: https://gitea.com/xorm/xorm/pulls/1855 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e0d22a24..0fcdb2b8 100644 --- a/go.mod +++ b/go.mod @@ -10,5 +10,5 @@ require ( github.com/stretchr/testify v1.4.0 github.com/syndtr/goleveldb v1.0.0 github.com/ziutek/mymysql v1.5.4 - xorm.io/builder v0.3.7 + xorm.io/builder v0.3.8 ) diff --git a/go.sum b/go.sum index 844dd094..833498ca 100644 --- a/go.sum +++ b/go.sum @@ -66,5 +66,5 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI= -xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= +xorm.io/builder v0.3.8 h1:P/wPgRqa9kX5uE0aA1/ukJ23u9KH0aSRpHLwDKXigSE= +xorm.io/builder v0.3.8/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= From 7c61c09af7cb34bdebf611eae8c80368ab360eaa Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 28 Jan 2021 11:03:43 +0800 Subject: [PATCH 46/61] Revert "Automatically convert datetime to int64 (#1715)" This reverts commit 8284e5defa48331f157bff08b1b3c6f53104291d. --- integrations/session_find_test.go | 23 ----------------------- session_convert.go | 24 +----------------------- 2 files changed, 1 insertion(+), 46 deletions(-) diff --git a/integrations/session_find_test.go b/integrations/session_find_test.go index 0c25a1e9..c3e99183 100644 --- a/integrations/session_find_test.go +++ b/integrations/session_find_test.go @@ -962,26 +962,3 @@ func TestDistinctAndCols(t *testing.T) { assert.EqualValues(t, 1, len(names)) assert.EqualValues(t, "test", names[0]) } - -func TestDateTimeInt64(t *testing.T) { - type DateTimeInt64 struct { - Id int64 - TimeStamp int64 `xorm:"datetime"` - } - - assert.NoError(t, PrepareEngine()) - assertSync(t, new(DateTimeInt64)) - - ts := time.Now().Unix() - cnt, err := testEngine.Insert(&DateTimeInt64{ - TimeStamp: ts, - }) - assert.NoError(t, err) - assert.EqualValues(t, 1, cnt) - - var dts []DateTimeInt64 - err = testEngine.Find(&dts) - assert.NoError(t, err) - assert.EqualValues(t, 1, len(dts)) - assert.EqualValues(t, ts, dts[0].TimeStamp) -} diff --git a/session_convert.go b/session_convert.go index 4a4dd8be..a6839947 100644 --- a/session_convert.go +++ b/session_convert.go @@ -168,29 +168,7 @@ func (session *Session) bytes2Value(col *schemas.Column, fieldValue *reflect.Val } else if strings.EqualFold(sdata, "false") { x = 0 } else { - if col.SQLType.Name == schemas.DateTime { - if len(sdata) == 20 { - t, err := time.Parse("2006-01-02T15:04:05Z", sdata) - if err != nil { - return fmt.Errorf("arg %v as int: %s", key, err.Error()) - } - x = t.Unix() - } else if len(sdata) == 19 { - var parseFormat = "2006-01-02 15:04:05" - if sdata[10] == 'T' { - parseFormat = "2006-01-02T15:04:05" - } - t, err := time.Parse(parseFormat, sdata) - if err != nil { - return fmt.Errorf("arg %v as int: %s", key, err.Error()) - } - x = t.Unix() - } else { - x, err = strconv.ParseInt(sdata, 10, 64) - } - } else { - x, err = strconv.ParseInt(sdata, 10, 64) - } + x, err = strconv.ParseInt(sdata, 10, 64) } if err != nil { return fmt.Errorf("arg %v as int: %s", key, err.Error()) From d41a13b56254b44f60b69dfd75174affc54f1dbb Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 28 Jan 2021 11:17:33 +0800 Subject: [PATCH 47/61] Fix tests --- integrations/session_update_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integrations/session_update_test.go b/integrations/session_update_test.go index f2105e2b..df0631c4 100644 --- a/integrations/session_update_test.go +++ b/integrations/session_update_test.go @@ -57,10 +57,10 @@ func TestUpdateMap(t *testing.T) { Id: tb.Id, }) assert.NoError(t, err) - if testEngine.Dialect().URI().DBType == schemas.SQLITE { - assert.EqualValues(t, 1, cnt) - } else { + if testEngine.Dialect().URI().DBType == schemas.MYSQL { assert.EqualValues(t, 0, cnt) + } else { + assert.EqualValues(t, 1, cnt) } } From 4629bb17176a8e0fb14d31c376e22847cf4e50f3 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 2 Feb 2021 14:15:10 +0800 Subject: [PATCH 48/61] Add NewEngineWithDB (#1860) Reviewed-on: https://gitea.com/xorm/xorm/pulls/1860 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- engine.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/engine.go b/engine.go index 873fcdc1..f52148aa 100644 --- a/engine.go +++ b/engine.go @@ -105,6 +105,15 @@ func NewEngineWithParams(driverName string, dataSourceName string, params map[st return engine, err } +// NewEngineWithDB new a db manager with db. The params will be passed to db. +func NewEngineWithDB(driverName string, dataSourceName string, db *core.DB) (*Engine, error) { + dialect, err := dialects.OpenDialect(driverName, dataSourceName) + if err != nil { + return nil, err + } + return newEngine(driverName, dataSourceName, dialect, db) +} + // NewEngineWithDialectAndDB new a db manager according to the parameter. // If you do not want to use your own dialect or db, please use NewEngine. // For creating dialect, you can call dialects.OpenDialect. And, for creating db, From ffac8e3577712515307b832fab8f251b57603468 Mon Sep 17 00:00:00 2001 From: whybangbang Date: Wed, 3 Feb 2021 23:27:07 +0800 Subject: [PATCH 49/61] session add method IsInTx (#1863) Co-authored-by: whybangbang <525484036@qq.com> Reviewed-on: https://gitea.com/xorm/xorm/pulls/1863 Reviewed-by: Lunny Xiao Co-authored-by: whybangbang Co-committed-by: whybangbang --- session_tx.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/session_tx.go b/session_tx.go index 57791703..f50bbf1f 100644 --- a/session_tx.go +++ b/session_tx.go @@ -84,3 +84,8 @@ func (session *Session) Commit() error { } return nil } + +// if current session is in a transaction +func (session *Session) IsInTx() bool { + return !session.isAutoCommit +} \ No newline at end of file From 407da9ddd84acac1554161a4eb83a17663ccb357 Mon Sep 17 00:00:00 2001 From: clannadxr Date: Tue, 9 Feb 2021 15:20:54 +0800 Subject: [PATCH 50/61] export tag identifier (#1865) #1864 Export tag identifier so we can change that form `xorm` to others This will be useful when in some migration scenarios such as migrate `sqlx` to `xorm`, the former uses `db` as the identifier and has a very simple rule which can be covered by xorm parser rules Co-authored-by: clannadxr Reviewed-on: https://gitea.com/xorm/xorm/pulls/1865 Reviewed-by: Lunny Xiao Co-authored-by: clannadxr Co-committed-by: clannadxr --- engine.go | 5 +++++ engine_group.go | 8 ++++++++ interface.go | 1 + tags/parser.go | 5 +++++ tags/parser_test.go | 23 +++++++++++++++++++++++ 5 files changed, 42 insertions(+) diff --git a/engine.go b/engine.go index f52148aa..f5710801 100644 --- a/engine.go +++ b/engine.go @@ -209,6 +209,11 @@ func (engine *Engine) SetColumnMapper(mapper names.Mapper) { engine.tagParser.SetColumnMapper(mapper) } +// SetTagIdentifier set the tag identifier +func (engine *Engine) SetTagIdentifier(tagIdentifier string) { + engine.tagParser.SetIdentifier(tagIdentifier) +} + // Quote Use QuoteStr quote the string sql func (engine *Engine) Quote(value string) string { value = strings.TrimSpace(value) diff --git a/engine_group.go b/engine_group.go index cdd9dd44..3e91cbd6 100644 --- a/engine_group.go +++ b/engine_group.go @@ -167,6 +167,14 @@ func (eg *EngineGroup) SetMapper(mapper names.Mapper) { } } +// SetTagIdentifier set the tag identifier +func (eg *EngineGroup) SetTagIdentifier(tagIdentifier string) { + eg.Engine.SetTagIdentifier(tagIdentifier) + for i := 0; i < len(eg.slaves); i++ { + eg.slaves[i].SetTagIdentifier(tagIdentifier) + } +} + // SetMaxIdleConns set the max idle connections on pool, default is 2 func (eg *EngineGroup) SetMaxIdleConns(conns int) { eg.Engine.DB().SetMaxIdleConns(conns) diff --git a/interface.go b/interface.go index 0fe9cbe1..55162c8c 100644 --- a/interface.go +++ b/interface.go @@ -101,6 +101,7 @@ type EngineInterface interface { SetCacher(string, caches.Cacher) SetConnMaxLifetime(time.Duration) SetColumnMapper(names.Mapper) + SetTagIdentifier(string) SetDefaultCacher(caches.Cacher) SetLogger(logger interface{}) SetLogLevel(log.LogLevel) diff --git a/tags/parser.go b/tags/parser.go index a301d124..45dd6d9d 100644 --- a/tags/parser.go +++ b/tags/parser.go @@ -63,6 +63,11 @@ func (parser *Parser) SetColumnMapper(mapper names.Mapper) { parser.columnMapper = mapper } +func (parser *Parser) SetIdentifier(identifier string) { + parser.ClearCaches() + parser.identifier = identifier +} + func (parser *Parser) ParseWithCache(v reflect.Value) (*schemas.Table, error) { t := v.Type() tableI, ok := parser.tableCache.Load(t) diff --git a/tags/parser_test.go b/tags/parser_test.go index ff304a5b..c3bf8051 100644 --- a/tags/parser_test.go +++ b/tags/parser_test.go @@ -80,3 +80,26 @@ func TestUnexportField(t *testing.T) { assert.NotEqual(t, "public", col.Name) } } + +func TestParseWithOtherIdentifier(t *testing.T) { + parser := NewParser( + "xorm", + dialects.QueryDialect("mysql"), + names.GonicMapper{}, + names.SnakeMapper{}, + caches.NewManager(), + ) + + type StructWithDBTag struct { + FieldFoo string `db:"foo"` + } + parser.SetIdentifier("db") + table, err := parser.Parse(reflect.ValueOf(new(StructWithDBTag))) + assert.NoError(t, err) + assert.EqualValues(t, "struct_with_db_tag", table.Name) + assert.EqualValues(t, 1, len(table.Columns())) + + for _, col := range table.Columns() { + assert.EqualValues(t, "foo", col.Name) + } +} From eed7e65bd9fa4614fa0196466f307151ae1b9c86 Mon Sep 17 00:00:00 2001 From: clannadxr Date: Thu, 18 Feb 2021 17:14:13 +0800 Subject: [PATCH 51/61] Panic when setting wrong logger (#1868) Co-authored-by: clannadxr Reviewed-on: https://gitea.com/xorm/xorm/pulls/1868 Reviewed-by: Lunny Xiao Co-authored-by: clannadxr Co-committed-by: clannadxr --- engine.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/engine.go b/engine.go index f5710801..ee98ed05 100644 --- a/engine.go +++ b/engine.go @@ -168,6 +168,8 @@ func (engine *Engine) SetLogger(logger interface{}) { realLogger = t case log.Logger: realLogger = log.NewLoggerAdapter(t) + default: + panic("logger should implement either log.ContextLogger or log.Logger") } engine.logger = realLogger engine.DB().Logger = realLogger From a7a51533d1dc520b256ec98949ffaf2fe098baeb Mon Sep 17 00:00:00 2001 From: 4color <4color@noreply.gitea.io> Date: Thu, 4 Mar 2021 23:40:35 +0800 Subject: [PATCH 52/61] fix oracle insert datetime (#1873) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit oracle下的日期插入问题。 Reviewed-on: https://gitea.com/xorm/xorm/pulls/1873 Reviewed-by: Lunny Xiao Co-authored-by: 4color <4color@noreply.gitea.io> Co-committed-by: 4color <4color@noreply.gitea.io> --- dialects/time.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dialects/time.go b/dialects/time.go index b0394745..9a3c82a4 100644 --- a/dialects/time.go +++ b/dialects/time.go @@ -19,7 +19,11 @@ func FormatTime(dialect Dialect, sqlTypeName string, t time.Time) (v interface{} case schemas.Date: v = t.Format("2006-01-02") case schemas.DateTime, schemas.TimeStamp, schemas.Varchar: // !DarthPestilane! format time when sqlTypeName is schemas.Varchar. - v = t.Format("2006-01-02 15:04:05") + if dialect.URI().DBType == schemas.ORACLE { + v = t + } else { + v = t.Format("2006-01-02 15:04:05") + } case schemas.TimeStampz: if dialect.URI().DBType == schemas.MSSQL { v = t.Format("2006-01-02T15:04:05.9999999Z07:00") From e660414278d25b2fa607b2b9429719626a6e70e1 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 15 Mar 2021 23:34:33 +0800 Subject: [PATCH 53/61] Support modernc.org/sqlite (#1850) Reviewed-on: https://gitea.com/xorm/xorm/pulls/1850 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- .gitignore | 1 + Makefile | 25 +++++++++-- core/db_test.go | 8 +++- dialects/dialect.go | 1 + go.mod | 3 +- go.sum | 86 +++++++++++++++++++++++++++++-------- integrations/engine_test.go | 1 + integrations/tests.go | 8 +++- 8 files changed, 108 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 617d5da7..a3fbadd4 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ test.db.sql *coverage.out test.db integrations/*.sql +integrations/test_sqlite* \ No newline at end of file diff --git a/Makefile b/Makefile index 092f23b3..0f0ddb6c 100644 --- a/Makefile +++ b/Makefile @@ -99,7 +99,8 @@ help: @echo " - test-mysql run integration tests for mysql" @echo " - test-mssql run integration tests for mssql" @echo " - test-postgres run integration tests for postgres" - @echo " - test-sqlite run integration tests for sqlite" + @echo " - test-sqlite3 run integration tests for sqlite" + @echo " - test-sqlite run integration tests for pure go sqlite" @echo " - test-tidb run integration tests for tidb" @echo " - vet examines Go source code and reports suspicious constructs" @@ -195,21 +196,37 @@ test-postgres\#%: go-check -conn_str="postgres://$(TEST_PGSQL_USERNAME):$(TEST_PGSQL_PASSWORD)@$(TEST_PGSQL_HOST)/$(TEST_PGSQL_DBNAME)?sslmode=disable" \ -quote=$(TEST_QUOTE_POLICY) -coverprofile=postgres.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic +.PHONY: test-sqlite3 +test-sqlite3: go-check + $(GO) test $(INTEGRATION_PACKAGES) -v -race -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ + -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic + +.PHONY: test-sqlite3-schema +test-sqlite3-schema: go-check + $(GO) test $(INTEGRATION_PACKAGES) -v -race -schema=xorm -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ + -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic + +.PHONY: test-sqlite3\#% +test-sqlite3\#%: go-check + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ + -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic + .PHONY: test-sqlite test-sqlite: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -cache=$(TEST_CACHE_ENABLE) -db=sqlite -conn_str="./test.db?cache=shared&mode=rwc" \ -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic .PHONY: test-sqlite-schema test-sqlite-schema: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -schema=xorm -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -schema=xorm -cache=$(TEST_CACHE_ENABLE) -db=sqlite -conn_str="./test.db?cache=shared&mode=rwc" \ -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic .PHONY: test-sqlite\#% test-sqlite\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -cache=$(TEST_CACHE_ENABLE) -db=sqlite -conn_str="./test.db?cache=shared&mode=rwc" \ -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic + .PNONY: test-tidb test-tidb: go-check $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mysql -cache=$(TEST_CACHE_ENABLE) -ignore_select_update=true \ diff --git a/core/db_test.go b/core/db_test.go index 777ab0ad..104c5b95 100644 --- a/core/db_test.go +++ b/core/db_test.go @@ -15,6 +15,7 @@ import ( _ "github.com/go-sql-driver/mysql" _ "github.com/mattn/go-sqlite3" + _ "modernc.org/sqlite" ) var ( @@ -27,7 +28,7 @@ func TestMain(m *testing.M) { flag.Parse() switch *dbtype { - case "sqlite3": + case "sqlite3", "sqlite": createTableSql = "CREATE TABLE IF NOT EXISTS `user` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NULL, " + "`title` TEXT NULL, `age` FLOAT NULL, `alias` TEXT NULL, `nick_name` TEXT NULL, `created` datetime);" case "mysql": @@ -45,8 +46,11 @@ func TestMain(m *testing.M) { func testOpen() (*DB, error) { switch *dbtype { case "sqlite3": - os.Remove("./test.db") + os.Remove("./test_sqlite3.db") return Open("sqlite3", "./test.db") + case "sqlite": + os.Remove("./test_sqlite.db") + return Open("sqlite", "./test.db") case "mysql": return Open("mysql", *dbConn) default: diff --git a/dialects/dialect.go b/dialects/dialect.go index 18b781a1..d9a640a4 100644 --- a/dialects/dialect.go +++ b/dialects/dialect.go @@ -206,6 +206,7 @@ func regDrvsNDialects() bool { "postgres": {"postgres", func() Driver { return &pqDriver{} }, func() Dialect { return &postgres{} }}, "pgx": {"postgres", func() Driver { return &pqDriverPgx{} }, func() Dialect { return &postgres{} }}, "sqlite3": {"sqlite3", func() Driver { return &sqlite3Driver{} }, func() Dialect { return &sqlite3{} }}, + "sqlite": {"sqlite3", func() Driver { return &sqlite3Driver{} }, func() Dialect { return &sqlite3{} }}, "oci8": {"oracle", func() Driver { return &oci8Driver{} }, func() Dialect { return &oracle{} }}, "goracle": {"oracle", func() Driver { return &goracleDriver{} }, func() Dialect { return &oracle{} }}, } diff --git a/go.mod b/go.mod index 0fcdb2b8..b9eec3a0 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,10 @@ require ( github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc github.com/go-sql-driver/mysql v1.5.0 github.com/lib/pq v1.7.0 - github.com/mattn/go-sqlite3 v1.14.0 + github.com/mattn/go-sqlite3 v1.14.6 github.com/stretchr/testify v1.4.0 github.com/syndtr/goleveldb v1.0.0 github.com/ziutek/mymysql v1.5.4 + modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84 xorm.io/builder v0.3.8 ) diff --git a/go.sum b/go.sum index 833498ca..7c72c699 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,11 @@ gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= -github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= -github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= 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/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= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= @@ -16,12 +16,18 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY= github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= -github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -29,34 +35,53 @@ github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= @@ -66,5 +91,32 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +modernc.org/cc/v3 v3.31.5-0.20210308123301-7a3e9dab9009 h1:u0oCo5b9wyLr++HF3AN9JicGhkUxJhMz51+8TIZH9N0= +modernc.org/cc/v3 v3.31.5-0.20210308123301-7a3e9dab9009/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878= +modernc.org/ccgo/v3 v3.9.0 h1:JbcEIqjw4Agf+0g3Tc85YvfYqkkFOv6xBwS4zkfqSoA= +modernc.org/ccgo/v3 v3.9.0/go.mod h1:nQbgkn8mwzPdp4mm6BT6+p85ugQ7FrGgIcYaE7nSrpY= +modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= +modernc.org/libc v1.8.0 h1:Pp4uv9g0csgBMpGPABKtkieF6O5MGhfGo6ZiOdlYfR8= +modernc.org/libc v1.8.0/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= +modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.2.2 h1:+yFk8hBprV+4c0U9GjFtL+dV3N8hOJ8JCituQcMShFY= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM= +modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= +modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84 h1:rgEUzE849tFlHSoeCrKyS9cZAljC+DY7MdMHKq6R6sY= +modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84/go.mod h1:PGzq6qlhyYjL6uVbSgS6WoF7ZopTW/sI7+7p+mb4ZVU= +modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc= +modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/tcl v1.5.0 h1:euZSUNfE0Fd4W8VqXI1Ly1v7fqDJoBuAV88Ea+SnaSs= +modernc.org/tcl v1.5.0/go.mod h1:gb57hj4pO8fRrK54zveIfFXBaMHK3SKJNWcmRw1cRzc= +modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= +modernc.org/z v1.0.1 h1:WyIDpEpAIx4Hel6q/Pcgj/VhaQV5XPJ2I6ryIYbjnpc= +modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= xorm.io/builder v0.3.8 h1:P/wPgRqa9kX5uE0aA1/ukJ23u9KH0aSRpHLwDKXigSE= xorm.io/builder v0.3.8/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= diff --git a/integrations/engine_test.go b/integrations/engine_test.go index 0e5d3424..7f77c21f 100644 --- a/integrations/engine_test.go +++ b/integrations/engine_test.go @@ -20,6 +20,7 @@ import ( _ "github.com/mattn/go-sqlite3" "github.com/stretchr/testify/assert" _ "github.com/ziutek/mymysql/godrv" + _ "modernc.org/sqlite" ) func TestPing(t *testing.T) { diff --git a/integrations/tests.go b/integrations/tests.go index 31fa99bf..840b1020 100644 --- a/integrations/tests.go +++ b/integrations/tests.go @@ -174,7 +174,13 @@ func MainTest(m *testing.M) { dbType = *db if *db == "sqlite3" { if ptrConnStr == nil { - connString = "./test.db?cache=shared&mode=rwc" + connString = "./test_sqlite3.db?cache=shared&mode=rwc" + } else { + connString = *ptrConnStr + } + } else if *db == "sqlite" { + if ptrConnStr == nil { + connString = "./test_sqlite.db?cache=shared&mode=rwc" } else { connString = *ptrConnStr } From 9286f29576542e721d3f7064ec6b943bae995c4d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 23 Mar 2021 21:34:42 +0800 Subject: [PATCH 54/61] Fix bug on import when split SQLs (#1878) Fix #1876 Reviewed-on: https://gitea.com/xorm/xorm/pulls/1878 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- integrations/engine_test.go | 9 + integrations/testdata/import1.sql | 279 ++++++++++++++++++++++++++++++ session_schema.go | 36 ++-- 3 files changed, 314 insertions(+), 10 deletions(-) create mode 100644 integrations/testdata/import1.sql diff --git a/integrations/engine_test.go b/integrations/engine_test.go index 7f77c21f..0dfc3de1 100644 --- a/integrations/engine_test.go +++ b/integrations/engine_test.go @@ -187,3 +187,12 @@ func TestSetSchema(t *testing.T) { assert.EqualValues(t, oldSchema, testEngine.Dialect().URI().Schema) } } + +func TestImport(t *testing.T) { + sess := testEngine.NewSession() + defer sess.Close() + assert.NoError(t, sess.Begin()) + _, err := sess.ImportFile("./testdata/import1.sql") + assert.NoError(t, err) + assert.NoError(t, sess.Commit()) +} diff --git a/integrations/testdata/import1.sql b/integrations/testdata/import1.sql new file mode 100644 index 00000000..e004f41c --- /dev/null +++ b/integrations/testdata/import1.sql @@ -0,0 +1,279 @@ +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+00:00"; + +-- 基本用户信息表 +CREATE TABLE IF NOT EXISTS `user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`), + KEY `uid` (`id`), + `user_name` varchar(128) CHARACTER SET utf8mb4 NOT NULL, + KEY `user_name` (`user_name`), + `email` varchar(32) NOT NULL, + KEY `email` (`email`), + `pass` varchar(256) NOT NULL, + `passwd` varchar(16) NOT NULL, + `uuid` TEXT NULL DEFAULT NULL COMMENT 'uuid', + `t` int(11) NOT NULL DEFAULT '0', + `u` bigint(20) NOT NULL, + `d` bigint(20) NOT NULL, + `plan` varchar(2) CHARACTER SET utf8mb4 NOT NULL DEFAULT 'A', + `node_group` INT NOT NULL DEFAULT '0', + `auto_reset_day` INT NOT NULL DEFAULT '0', + `auto_reset_bandwidth` DECIMAL(12,2) NOT NULL DEFAULT '0.00', + `transfer_enable` BIGINT(20) NOT NULL, + `port` int(11) NOT NULL, + `protocol_param` VARCHAR(128) NULL DEFAULT NULL, + `obfs_param` VARCHAR(128) NULL DEFAULT NULL, + `switch` tinyint(4) NOT NULL DEFAULT '1', + `enable` tinyint(4) NOT NULL DEFAULT '1', + `type` tinyint(4) NOT NULL DEFAULT '1', + `last_get_gift_time` int(11) NOT NULL DEFAULT '0', + `last_check_in_time` int(11) NOT NULL DEFAULT '0', + `last_rest_pass_time` int(11) NOT NULL DEFAULT '0', + `reg_date` datetime NOT NULL, + `invite_num` int(8) NOT NULL, + `money` decimal(12,2) NOT NULL, + `ref_by` int(11) NOT NULL DEFAULT '0', + `expire_time` int(11) NOT NULL DEFAULT '0', + `is_email_verify` tinyint(4) NOT NULL DEFAULT '0', + `reg_ip` varchar(128) NOT NULL DEFAULT '127.0.0.1', + `node_speedlimit` DECIMAL(12,2) NOT NULL DEFAULT '0.00', + `node_connector` int(11) NOT NULL DEFAULT '0', + `forbidden_ip` LONGTEXT NULL DEFAULT '', + `forbidden_port` LONGTEXT NULL DEFAULT '', + `disconnect_ip` LONGTEXT NULL DEFAULT '', + `is_hide` INT NOT NULL DEFAULT '0', + `last_detect_ban_time` datetime DEFAULT '1989-06-04 00:05:00', + `all_detect_number` int(11) NOT NULL DEFAULT '0', + `is_multi_user` INT NOT NULL DEFAULT '0', + `telegram_id` BIGINT NULL, + `is_admin` int(2) NOT NULL DEFAULT '0', + `im_type` int(11) DEFAULT '1', + `im_value` text, + `last_day_t` bigint(20) NOT NULL DEFAULT '0', + `mail_notified` int(11) NOT NULL DEFAULT '0', + `class` int(11) NOT NULL DEFAULT '0', + `class_expire` datetime NOT NULL DEFAULT '1989-06-04 00:05:00', + `expire_in` datetime NOT NULL DEFAULT '2099-06-04 00:05:00', + `theme` text NOT NULL, + `ga_token` text NOT NULL, + `ga_enable` int(11) NOT NULL DEFAULT '0', + `pac` LONGTEXT, + `remark` text +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 用户流量信息表 +-- TODO: 重写流量信息提取逻辑 +CREATE TABLE IF NOT EXISTS `user_traffic_log` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`), + `user_id` int(11) NOT NULL, + `u` BIGINT(20) NOT NULL, + `d` BIGINT(20) NOT NULL, + `node_id` int(11) NOT NULL, + `rate` float NOT NULL, + `traffic` varchar(32) NOT NULL, + `log_time` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 用户订阅 TOKEN 信息表 +CREATE TABLE IF NOT EXISTS `user_token` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`), + `token` varchar(256) NOT NULL, + `user_id` int(11) NOT NULL, + `create_time` int(11) NOT NULL, + `expire_time` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 充值码使用信息表 +CREATE TABLE IF NOT EXISTS `charge_code` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`), + `code` text NOT NULL, + `type` int(11) NOT NULL, + `number` DECIMAL(11,2) NOT NULL, + `isused` int(11) NOT NULL DEFAULT '0', + `userid` bigint(20) NOT NULL, + `usedatetime` datetime NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 邀请码使用信息表 +CREATE TABLE IF NOT EXISTS `invite_code` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`), + `code` varchar(128) NOT NULL, + KEY `user_id` (`user_id`), + `user_id` int(11) NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `updated_at` timestamp NOT NULL DEFAULT '2016-06-01 00:00:00' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 公告信息表 +CREATE TABLE IF NOT EXISTS `announcement` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`), + `date` datetime NOT NULL, + `content` LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + `markdown` LONGTEXT NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 节点信息表 +CREATE TABLE IF NOT EXISTS `node` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`), + `name` varchar(128) NOT NULL, + `type` int(3) NOT NULL, + `online_user` int(11) NOT NULL, + `mu_only` INT NULL DEFAULT '0', + `online` BOOLEAN NOT NULL DEFAULT TRUE, + `server` varchar(128) NOT NULL, + `method` varchar(64) NOT NULL, + `info` varchar(128) NOT NULL, + `status` varchar(128) NOT NULL, + `node_group` INT NOT NULL DEFAULT '0', + `sort` int(3) NOT NULL, + `custom_method` tinyint(1) NOT NULL DEFAULT '0', + `traffic_rate` float NOT NULL DEFAULT '1', + `node_class` int(11) NOT NULL DEFAULT '0', + `node_speedlimit` DECIMAL(12,2) NOT NULL DEFAULT '0.00', + `node_connector` int(11) NOT NULL DEFAULT '0', + `node_bandwidth` bigint(20) NOT NULL DEFAULT '0', + `node_bandwidth_limit` bigint(20) NOT NULL DEFAULT '0', + `bandwidthlimit_resetday` int(11) NOT NULL DEFAULT '0', + `node_heartbeat` bigint(20) NOT NULL DEFAULT '0', + `node_ip` text +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +-- TODO: 修改 VPN 节点的结算说明 + +-- 商店数据表 +CREATE TABLE `shop` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `name` TEXT NOT NULL, + `price` DECIMAL(12,2) NOT NULL, + `content` TEXT NOT NULL, + `auto_renew` INT NOT NULL, + `status` INT NOT NULL DEFAULT '1', + `auto_reset_bandwidth` INT NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 优惠券数据表 +CREATE TABLE `coupon` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `code` TEXT NOT NULL, + `onetime` INT NOT NULL, + `expire` BIGINT NOT NULL, + `shop` TEXT NOT NULL, + `credit` INT NOT NULL, + PRIMARY KEY (`id`) +) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 购买记录数据表 +CREATE TABLE `bought` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `userid` BIGINT NOT NULL, + `shopid` BIGINT NOT NULL, + `coupon` TEXT NOT NULL, + `datetime` BIGINT NOT NULL, + `renew` BIGINT(11) NOT NULL, + `price` DECIMAL(12,2) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 工单数据表 +CREATE TABLE `ticket` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `title` LONGTEXT NOT NULL, + `status` INT NOT NULL DEFAULT '1', + `content` LONGTEXT NOT NULL, + `rootid` BIGINT NOT NULL,`userid` BIGINT NOT NULL, + `datetime` BIGINT NOT NULL, + PRIMARY KEY (`id`) +) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 返利记录数据表 +CREATE TABLE `payback` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `total` DECIMAL(12,2) NOT NULL, + `userid` BIGINT NOT NULL, + `ref_by` BIGINT NOT NULL, + `ref_get` DECIMAL(12,2) NOT NULL, + `datetime` BIGINT NOT NULL, + PRIMARY KEY (`id`) +) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 审计规则数据表 +CREATE TABLE `detect_list` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `name` LONGTEXT NOT NULL, + `type` INT NOT NULL, + `text` LONGTEXT NOT NULL, + `regex` LONGTEXT NOT NULL, + PRIMARY KEY (`id`) +) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 审计记录数据表 +CREATE TABLE `detect_log` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `user_id` BIGINT NOT NULL, + `node_id` INT NOT NULL, + `list_id` BIGINT NOT NULL, + `datetime` BIGINT NOT NULL, + PRIMARY KEY (`id`) +) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 中转规则数据表 +CREATE TABLE IF NOT EXISTS `relay` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`), + `user_id` bigint(20) NOT NULL, + `source_node_id` bigint(20) NOT NULL, + `dist_node_id` bigint(20) NOT NULL, + `dist_ip` text NOT NULL, + `port` int(11) NOT NULL, + `priority` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 用户订阅日志 +CREATE TABLE IF NOT EXISTS `user_subscribe_log` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `user_name` varchar(128) NOT NULL COMMENT '用户名', + `user_id` int(11) NOT NULL COMMENT '用户 ID', + `email` varchar(32) NOT NULL COMMENT '用户邮箱', + `subscribe_type` varchar(20) NOT NULL COMMENT '获取的订阅类型', + `request_ip` varchar(128) NOT NULL COMMENT '请求 IP', + `request_time` datetime NOT NULL COMMENT '请求时间', + `request_user_agent` text COMMENT '请求 UA 信息', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户订阅日志'; + +-- 审计封禁日志 +CREATE TABLE IF NOT EXISTS `detect_ban_log` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `user_name` varchar(128) NOT NULL COMMENT '用户名', + `user_id` int(11) NOT NULL COMMENT '用户 ID', + `email` varchar(32) NOT NULL COMMENT '用户邮箱', + `detect_number` int(11) NOT NULL COMMENT '本次违规次数', + `ban_time` int(11) NOT NULL COMMENT '本次封禁时长', + `start_time` bigint(20) NOT NULL COMMENT '统计开始时间', + `end_time` bigint(20) NOT NULL COMMENT '统计结束时间', + `all_detect_number` int(11) NOT NULL COMMENT '累计违规次数', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='审计封禁日志'; + +-- 管理员操作记录 +CREATE TABLE IF NOT EXISTS `gconfig` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `key` varchar(128) NOT NULL COMMENT '配置键名', + `type` varchar(32) NOT NULL COMMENT '值类型', + `value` text NOT NULL COMMENT '配置值', + `oldvalue` text NOT NULL COMMENT '之前的配置值', + `name` varchar(128) NOT NULL COMMENT '配置名称', + `comment` text NOT NULL COMMENT '配置描述', + `operator_id` int(11) NOT NULL COMMENT '操作员 ID', + `operator_name` varchar(128) NOT NULL COMMENT '操作员名称', + `operator_email` varchar(32) NOT NULL COMMENT '操作员邮箱', + `last_update` bigint(20) NOT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='网站配置'; \ No newline at end of file diff --git a/session_schema.go b/session_schema.go index 9ccf8abe..7d36ae7f 100644 --- a/session_schema.go +++ b/session_schema.go @@ -448,27 +448,43 @@ func (session *Session) ImportFile(ddlPath string) ([]sql.Result, error) { // Import SQL DDL from io.Reader func (session *Session) Import(r io.Reader) ([]sql.Result, error) { - var results []sql.Result - var lastError error - scanner := bufio.NewScanner(r) + var ( + results []sql.Result + lastError error + inSingleQuote bool + startComment bool + ) - var inSingleQuote bool + scanner := bufio.NewScanner(r) semiColSpliter := func(data []byte, atEOF bool) (advance int, token []byte, err error) { if atEOF && len(data) == 0 { return 0, nil, nil } + var oriInSingleQuote = inSingleQuote for i, b := range data { - if b == '\'' { - inSingleQuote = !inSingleQuote - } - if !inSingleQuote && b == ';' { - return i + 1, data[0:i], nil + if startComment { + if b == '\n' { + startComment = false + } + } else { + if i > 0 && data[i-1] == '-' && data[i] == '-' { + startComment = true + continue + } + + if b == '\'' { + inSingleQuote = !inSingleQuote + } + if !inSingleQuote && b == ';' { + return i + 1, data[0:i], nil + } } } // If we're at EOF, we have a final, non-terminated line. Return it. if atEOF { return len(data), data, nil } + inSingleQuote = oriInSingleQuote // Request more data. return 0, nil, nil } @@ -479,10 +495,10 @@ func (session *Session) Import(r io.Reader) ([]sql.Result, error) { query := strings.Trim(scanner.Text(), " \t\n\r") if len(query) > 0 { result, err := session.Exec(query) - results = append(results, result) if err != nil { return nil, err } + results = append(results, result) } } From 40ee326cac59ffba1234d48dfbb62ea633c4d3c6 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 23 Mar 2021 21:48:58 +0800 Subject: [PATCH 55/61] More clear for Get with nil (#1879) Resolve #1844 Reviewed-on: https://gitea.com/xorm/xorm/pulls/1879 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- integrations/session_get_test.go | 16 ++++++++++++++++ session_get.go | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/integrations/session_get_test.go b/integrations/session_get_test.go index e4d9f82e..99db98fc 100644 --- a/integrations/session_get_test.go +++ b/integrations/session_get_test.go @@ -6,11 +6,13 @@ package integrations import ( "database/sql" + "errors" "fmt" "strconv" "testing" "time" + "xorm.io/xorm" "xorm.io/xorm/contexts" "xorm.io/xorm/schemas" @@ -750,3 +752,17 @@ func TestGetViaMapCond(t *testing.T) { assert.NoError(t, err) assert.False(t, has) } + +func TestGetNil(t *testing.T) { + type GetNil struct { + Id int64 + } + + assert.NoError(t, PrepareEngine()) + assertSync(t, new(GetNil)) + + var gn *GetNil + has, err := testEngine.Get(gn) + assert.True(t, errors.Is(err, xorm.ErrObjectIsNil)) + assert.False(t, has) +} diff --git a/session_get.go b/session_get.go index afedcd1f..6e65ea2f 100644 --- a/session_get.go +++ b/session_get.go @@ -16,6 +16,10 @@ import ( "xorm.io/xorm/schemas" ) +var ( + ErrObjectIsNil = errors.New("object should not be nil") +) + // Get retrieve one record from database, bean's non-empty fields // will be as conditions func (session *Session) Get(bean interface{}) (bool, error) { @@ -37,6 +41,8 @@ func (session *Session) get(bean interface{}) (bool, error) { return false, errors.New("needs a pointer to a value") } else if beanValue.Elem().Kind() == reflect.Ptr { return false, errors.New("a pointer to a pointer is not allowed") + } else if beanValue.IsNil() { + return false, ErrObjectIsNil } if beanValue.Elem().Kind() == reflect.Struct { From 21881d8b84ba38e22f26dc82a60360d444df29da Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Thu, 8 Apr 2021 14:12:40 +0800 Subject: [PATCH 56/61] MariaDB 10.5 adds a suffix on old datatypes (#1885) MariaDB when encountering an old datetime type will add a suffix of /* mariadb-5.3 */ on its schema information page. Xorm does not understand this and then its mappings fail. The simplest solution is just to remove any fixed suffix and that is what this PR does - a clever solution would look for and remove any comments or match them. See https://mariadb.com/kb/en/time/ for more details about the comment. Related: https://github.com/go-gitea/gitea/issues/15277 Signed-off-by: Andrew Thornton Reviewed-on: https://gitea.com/xorm/xorm/pulls/1885 Reviewed-by: Lunny Xiao Co-authored-by: Andrew Thornton Co-committed-by: Andrew Thornton --- dialects/mysql.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dialects/mysql.go b/dialects/mysql.go index 32e18a17..769e30b1 100644 --- a/dialects/mysql.go +++ b/dialects/mysql.go @@ -353,6 +353,8 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName cts := strings.Split(colType, "(") colName := cts[0] + // Remove the /* mariadb-5.3 */ suffix from coltypes + colName = strings.TrimSuffix(colName, "/* mariadb-5.3 */") colType = strings.ToUpper(colName) var len1, len2 int if len(cts) == 2 { From 2142e31d95557ca9db2201e440938f8f4538224d Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Thu, 8 Apr 2021 20:51:48 +0800 Subject: [PATCH 57/61] Fix formatting (#1886) Fix newline formatting Signed-off-by: Andrew Thornton Reviewed-on: https://gitea.com/xorm/xorm/pulls/1886 Co-authored-by: Andrew Thornton Co-committed-by: Andrew Thornton --- session_tx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session_tx.go b/session_tx.go index f50bbf1f..33ef72c6 100644 --- a/session_tx.go +++ b/session_tx.go @@ -88,4 +88,4 @@ func (session *Session) Commit() error { // if current session is in a transaction func (session *Session) IsInTx() bool { return !session.isAutoCommit -} \ No newline at end of file +} From ee78664413c09868df2867d8b0f60cdb4ec60658 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 8 Apr 2021 21:26:21 +0800 Subject: [PATCH 58/61] Fix sqlite test (#1887) Fix bug Reviewed-on: https://gitea.com/xorm/xorm/pulls/1887 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- integrations/engine_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/integrations/engine_test.go b/integrations/engine_test.go index 0dfc3de1..1e2e9f4a 100644 --- a/integrations/engine_test.go +++ b/integrations/engine_test.go @@ -189,6 +189,10 @@ func TestSetSchema(t *testing.T) { } func TestImport(t *testing.T) { + if testEngine.Dialect().URI().DBType != schemas.MYSQL { + t.SkipNow() + return + } sess := testEngine.NewSession() defer sess.Close() assert.NoError(t, sess.Begin()) From b92d951eac56ed56db9991dac819960f51221561 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 10 Apr 2021 09:45:18 +0800 Subject: [PATCH 59/61] Fix drone (#1842) Reviewed-on: https://gitea.com/xorm/xorm/pulls/1842 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- .drone.yml | 790 ++++++++++++++++++++++++++++++++++++++++------------- Makefile | 4 +- 2 files changed, 599 insertions(+), 195 deletions(-) diff --git a/.drone.yml b/.drone.yml index 300c7841..05f06e99 100644 --- a/.drone.yml +++ b/.drone.yml @@ -2,58 +2,288 @@ kind: pipeline name: testing steps: +- name: restore-cache + image: meltwater/drone-cache + pull: always + settings: + backend: "filesystem" + restore: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go + - name: test-vet - image: golang:1.11 # The lowest golang requirement + image: golang:1.15 environment: GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' commands: - make vet - - make test - make fmt-check + volumes: + - name: cache + path: /go when: event: - push - pull_request -- name: test-sqlite - image: golang:1.12 +- name: rebuild-cache + image: meltwater/drone-cache + pull: true + settings: + backend: "filesystem" + rebuild: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go + +volumes: + - name: cache + temp: {} + +--- +kind: pipeline +name: test-sqlite +depends_on: + - testing +steps: +- name: restore-cache + image: meltwater/drone-cache:dev + pull: always + settings: + backend: "filesystem" + restore: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go + +- name: test-sqlite3 + image: golang:1.15 environment: GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' + commands: + - make test-sqlite3 + - TEST_CACHE_ENABLE=true make test-sqlite3 + - TEST_QUOTE_POLICY=reserved make test-sqlite3 + volumes: + - name: cache + path: /go + +- name: test-sqlite + image: golang:1.15 + environment: + GO111MODULE: "on" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' commands: - make test-sqlite - TEST_CACHE_ENABLE=true make test-sqlite - TEST_QUOTE_POLICY=reserved make test-sqlite - when: - event: - - push - - pull_request + volumes: + - name: cache + path: /go + +- name: rebuild-cache + image: meltwater/drone-cache:dev + pull: true + settings: + backend: "filesystem" + rebuild: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go + +volumes: + - name: cache + temp: {} + +--- +kind: pipeline +name: test-mysql +depends_on: + - testing +steps: +- name: restore-cache + image: meltwater/drone-cache + pull: always + settings: + backend: "filesystem" + restore: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go - name: test-mysql - image: golang:1.12 + image: golang:1.15 environment: GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' TEST_MYSQL_HOST: mysql TEST_MYSQL_CHARSET: utf8 TEST_MYSQL_DBNAME: xorm_test TEST_MYSQL_USERNAME: root TEST_MYSQL_PASSWORD: commands: + - make test + - make test-mysql + - TEST_CACHE_ENABLE=true make test-mysql + - TEST_QUOTE_POLICY=reserved make test-mysql + volumes: + - name: cache + path: /go + +- name: test-mysql-utf8mb4 + image: golang:1.15 + depends_on: + - test-mysql + environment: + GO111MODULE: "on" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' + TEST_MYSQL_HOST: mysql + TEST_MYSQL_CHARSET: utf8mb4 + TEST_MYSQL_DBNAME: xorm_test + TEST_MYSQL_USERNAME: root + TEST_MYSQL_PASSWORD: + commands: - make test-mysql - TEST_CACHE_ENABLE=true make test-mysql - TEST_QUOTE_POLICY=reserved make test-mysql - when: - event: - - push - - pull_request + volumes: + - name: cache + path: /go -- name: test-mysql8 - image: golang:1.12 +- name: test-mymysql + pull: default + image: golang:1.15 + depends_on: + - test-mysql-utf8mb4 environment: GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' + TEST_MYSQL_HOST: mysql:3306 + TEST_MYSQL_DBNAME: xorm_test + TEST_MYSQL_USERNAME: root + TEST_MYSQL_PASSWORD: + commands: + - make test-mymysql + - TEST_CACHE_ENABLE=true make test-mymysql + - TEST_QUOTE_POLICY=reserved make test-mymysql + volumes: + - name: cache + path: /go + +- name: rebuild-cache + image: meltwater/drone-cache + depends_on: + - test-mysql + - test-mysql-utf8mb4 + - test-mymysql + pull: true + settings: + backend: "filesystem" + rebuild: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go + +volumes: + - name: cache + temp: {} + +services: +- name: mysql + pull: default + image: mysql:5.7 + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_DATABASE: xorm_test + +--- +kind: pipeline +name: test-mysql8 +depends_on: + - test-mysql + - test-sqlite +steps: +- name: restore-cache + image: meltwater/drone-cache + pull: always + settings: + backend: "filesystem" + restore: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go + +- name: test-mysql8 + image: golang:1.15 + environment: + GO111MODULE: "on" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' TEST_MYSQL_HOST: mysql8 TEST_MYSQL_CHARSET: utf8mb4 TEST_MYSQL_DBNAME: xorm_test @@ -63,58 +293,70 @@ steps: - make test-mysql - TEST_CACHE_ENABLE=true make test-mysql - TEST_QUOTE_POLICY=reserved make test-mysql - when: - event: - - push - - pull_request + volumes: + - name: cache + path: /go -- name: test-mysql-utf8mb4 - image: golang:1.12 +- name: rebuild-cache + image: meltwater/drone-cache:dev + pull: true depends_on: - - test-mysql - environment: - GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" - TEST_MYSQL_HOST: mysql - TEST_MYSQL_CHARSET: utf8mb4 - TEST_MYSQL_DBNAME: xorm_test - TEST_MYSQL_USERNAME: root - TEST_MYSQL_PASSWORD: - commands: - - make test-mysql - - TEST_CACHE_ENABLE=true make test-mysql - - TEST_QUOTE_POLICY=reserved make test-mysql - when: - event: - - push - - pull_request + - test-mysql8 + settings: + backend: "filesystem" + rebuild: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go -- name: test-mymysql +volumes: + - name: cache + temp: {} + +services: +- name: mysql8 pull: default - image: golang:1.12 - depends_on: - - test-mysql-utf8mb4 + image: mysql:8.0 environment: - GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" - TEST_MYSQL_HOST: mysql:3306 - TEST_MYSQL_DBNAME: xorm_test - TEST_MYSQL_USERNAME: root - TEST_MYSQL_PASSWORD: - commands: - - make test-mymysql - - TEST_CACHE_ENABLE=true make test-mymysql - - TEST_QUOTE_POLICY=reserved make test-mymysql - when: - event: - - push - - pull_request + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_DATABASE: xorm_test + +--- +kind: pipeline +name: test-mariadb +depends_on: + - test-mysql8 +steps: +- name: restore-cache + image: meltwater/drone-cache + pull: always + settings: + backend: "filesystem" + restore: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go - name: test-mariadb - image: golang:1.12 + image: golang:1.15 environment: GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' TEST_MYSQL_HOST: mariadb TEST_MYSQL_CHARSET: utf8mb4 TEST_MYSQL_DBNAME: xorm_test @@ -124,17 +366,71 @@ steps: - make test-mysql - TEST_CACHE_ENABLE=true make test-mysql - TEST_QUOTE_POLICY=reserved make test-mysql - when: - event: - - push - - pull_request + volumes: + - name: cache + path: /go + +- name: rebuild-cache + image: meltwater/drone-cache:dev + depends_on: + - test-mariadb + pull: true + settings: + backend: "filesystem" + rebuild: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go + +volumes: + - name: cache + temp: {} + +services: +- name: mariadb + pull: default + image: mariadb:10.4 + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_DATABASE: xorm_test + +--- +kind: pipeline +name: test-postgres +depends_on: + - test-mariadb +steps: +- name: restore-cache + image: meltwater/drone-cache + pull: always + settings: + backend: "filesystem" + restore: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go - name: test-postgres pull: default - image: golang:1.12 + image: golang:1.15 environment: GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' TEST_PGSQL_HOST: pgsql TEST_PGSQL_DBNAME: xorm_test TEST_PGSQL_USERNAME: postgres @@ -143,19 +439,21 @@ steps: - make test-postgres - TEST_CACHE_ENABLE=true make test-postgres - TEST_QUOTE_POLICY=reserved make test-postgres - when: - event: - - push - - pull_request + volumes: + - name: cache + path: /go - name: test-postgres-schema pull: default - image: golang:1.12 + image: golang:1.15 depends_on: - test-postgres environment: GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' TEST_PGSQL_HOST: pgsql TEST_PGSQL_SCHEMA: xorm TEST_PGSQL_DBNAME: xorm_test @@ -165,17 +463,72 @@ steps: - make test-postgres - TEST_CACHE_ENABLE=true make test-postgres - TEST_QUOTE_POLICY=reserved make test-postgres - when: - event: - - push - - pull_request + volumes: + - name: cache + path: /go + +- name: rebuild-cache + image: meltwater/drone-cache:dev + pull: true + depends_on: + - test-postgres-schema + settings: + backend: "filesystem" + rebuild: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go + +volumes: + - name: cache + temp: {} + +services: +- name: pgsql + pull: default + image: postgres:9.5 + environment: + POSTGRES_DB: xorm_test + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + +--- +kind: pipeline +name: test-mssql +depends_on: + - test-postgres +steps: +- name: restore-cache + image: meltwater/drone-cache + pull: always + settings: + backend: "filesystem" + restore: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go - name: test-mssql pull: default - image: golang:1.12 + image: golang:1.15 environment: GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' TEST_MSSQL_HOST: mssql TEST_MSSQL_DBNAME: xorm_test TEST_MSSQL_USERNAME: sa @@ -185,17 +538,70 @@ steps: - TEST_CACHE_ENABLE=true make test-mssql - TEST_QUOTE_POLICY=reserved make test-mssql - TEST_MSSQL_DEFAULT_VARCHAR=NVARCHAR TEST_MSSQL_DEFAULT_CHAR=NCHAR make test-mssql - when: - event: - - push - - pull_request + volumes: + - name: cache + path: /go + +- name: rebuild-cache + image: meltwater/drone-cache:dev + pull: true + settings: + backend: "filesystem" + rebuild: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go + +volumes: + - name: cache + temp: {} + +services: +- name: mssql + pull: default + image: microsoft/mssql-server-linux:latest + environment: + ACCEPT_EULA: Y + SA_PASSWORD: yourStrong(!)Password + MSSQL_PID: Developer + +--- +kind: pipeline +name: test-tidb +depends_on: + - test-mssql +steps: +- name: restore-cache + image: meltwater/drone-cache + pull: always + settings: + backend: "filesystem" + restore: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go - name: test-tidb pull: default - image: golang:1.12 + image: golang:1.15 environment: GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' TEST_TIDB_HOST: "tidb:4000" TEST_TIDB_DBNAME: xorm_test TEST_TIDB_USERNAME: root @@ -204,17 +610,66 @@ steps: - make test-tidb - TEST_CACHE_ENABLE=true make test-tidb - TEST_QUOTE_POLICY=reserved make test-tidb - when: - event: - - push - - pull_request + volumes: + - name: cache + path: /go + +- name: rebuild-cache + image: meltwater/drone-cache:dev + pull: true + settings: + backend: "filesystem" + rebuild: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go + +volumes: + - name: cache + temp: {} + +services: +- name: tidb + pull: default + image: pingcap/tidb:v3.0.3 + +--- +kind: pipeline +name: test-cockroach +depends_on: + - test-tidb +steps: +- name: restore-cache + image: meltwater/drone-cache + pull: always + settings: + backend: "filesystem" + restore: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go - name: test-cockroach pull: default - image: golang:1.13 + image: golang:1.15 environment: GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" + GOPROXY: "https://goproxy.io" + CGO_ENABLED: 1 + GOMODCACHE: '/drone/src/pkg.mod' + GOCACHE: '/drone/src/pkg.build' TEST_COCKROACH_HOST: "cockroach:26257" TEST_COCKROACH_DBNAME: xorm_test TEST_COCKROACH_USERNAME: root @@ -223,115 +678,62 @@ steps: - sleep 10 - make test-cockroach - TEST_CACHE_ENABLE=true make test-cockroach - when: - event: - - push - - pull_request + volumes: + - name: cache + path: /go -- name: merge_coverage - pull: default - image: golang:1.12 - environment: - GO111MODULE: "on" - GOPROXY: "https://goproxy.cn" - depends_on: - - test-vet - - test-sqlite - - test-mysql - - test-mysql8 - - test-mymysql - - test-postgres - - test-postgres-schema - - test-mssql - - test-tidb - - test-cockroach - commands: - - make coverage - when: - event: - - push - - pull_request +- name: rebuild-cache + image: meltwater/drone-cache:dev + pull: true + settings: + backend: "filesystem" + rebuild: true + cache_key: '{{ .Repo.Name }}_{{ checksum "go.mod" }}_{{ checksum "go.sum" }}_{{ arch }}_{{ os }}' + archive_format: "gzip" + filesystem_cache_root: "/go" + mount: + - pkg.mod + - pkg.build + volumes: + - name: cache + path: /go + +volumes: + - name: cache + temp: {} services: - -- name: mysql - pull: default - image: mysql:5.7 - environment: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - MYSQL_DATABASE: xorm_test - when: - event: - - push - - tag - - pull_request - -- name: mysql8 - pull: default - image: mysql:8.0 - environment: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - MYSQL_DATABASE: xorm_test - when: - event: - - push - - tag - - pull_request - -- name: mariadb - pull: default - image: mariadb:10.4 - environment: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - MYSQL_DATABASE: xorm_test - when: - event: - - push - - tag - - pull_request - -- name: pgsql - pull: default - image: postgres:9.5 - environment: - POSTGRES_DB: xorm_test - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - when: - event: - - push - - tag - - pull_request - -- name: mssql - pull: default - image: microsoft/mssql-server-linux:latest - environment: - ACCEPT_EULA: Y - SA_PASSWORD: yourStrong(!)Password - MSSQL_PID: Developer - when: - event: - - push - - tag - - pull_request - -- name: tidb - pull: default - image: pingcap/tidb:v3.0.3 - when: - event: - - push - - tag - - pull_request - - name: cockroach pull: default image: cockroachdb/cockroach:v19.2.4 commands: - /cockroach/cockroach start --insecure + +--- +kind: pipeline +name: merge_coverage +depends_on: + - testing + - test-sqlite + - test-mysql + - test-mysql8 + - test-mariadb + - test-postgres + - test-mssql + - test-tidb + - test-cockroach +steps: +- name: merge_coverage + pull: default + image: golang:1.15 + environment: + GO111MODULE: "on" + GOPROXY: "https://goproxy.io" + commands: + - make coverage when: + branch: + - master event: - - push - - tag - - pull_request + - push + - pull_request diff --git a/Makefile b/Makefile index 0f0ddb6c..7305baa7 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,9 @@ GOFMT ?= gofmt -s TAGS ?= SED_INPLACE := sed -i -GOFILES := $(shell find . -name "*.go" -type f) +GO_DIRS := caches contexts integrations convert core dialects internal log migrate names schemas tags +GOFILES := $(wildcard *.go) +GOFILES += $(shell find $(GO_DIRS) -name "*.go" -type f) INTEGRATION_PACKAGES := xorm.io/xorm/integrations PACKAGES ?= $(filter-out $(INTEGRATION_PACKAGES),$(shell $(GO) list ./...)) From 4bfe6853f595740a9bdeb7053c87079495ce96b8 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 10 Apr 2021 10:57:36 +0800 Subject: [PATCH 60/61] Fix some comments lint and bug (#1888) Reviewed-on: https://gitea.com/xorm/xorm/pulls/1888 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- caches/leveldb.go | 5 +++++ caches/manager.go | 4 ++++ contexts/hook.go | 6 ++++++ dialects/dialect.go | 35 ++++++++++++++++++++------------ engine.go | 3 ++- engine_group.go | 3 ++- integrations/engine_test.go | 2 +- integrations/tests.go | 10 ++++++++++ internal/json/json.go | 6 +++--- internal/utils/name.go | 1 + internal/utils/reflect.go | 1 + internal/utils/sql.go | 1 + internal/utils/strings.go | 3 +++ internal/utils/zero.go | 40 +++++++++++++++++++++---------------- migrate/migrate.go | 5 +---- migrate/migrate_test.go | 5 +---- session.go | 3 ++- session_get.go | 1 + session_tx.go | 2 +- 19 files changed, 90 insertions(+), 46 deletions(-) diff --git a/caches/leveldb.go b/caches/leveldb.go index d1a177ad..f2f71d84 100644 --- a/caches/leveldb.go +++ b/caches/leveldb.go @@ -19,6 +19,7 @@ type LevelDBStore struct { var _ CacheStore = &LevelDBStore{} +// NewLevelDBStore creates a leveldb store func NewLevelDBStore(dbfile string) (*LevelDBStore, error) { db := &LevelDBStore{} h, err := leveldb.OpenFile(dbfile, nil) @@ -29,6 +30,7 @@ func NewLevelDBStore(dbfile string) (*LevelDBStore, error) { return db, nil } +// Put implements CacheStore func (s *LevelDBStore) Put(key string, value interface{}) error { val, err := Encode(value) if err != nil { @@ -50,6 +52,7 @@ func (s *LevelDBStore) Put(key string, value interface{}) error { return err } +// Get implements CacheStore func (s *LevelDBStore) Get(key string) (interface{}, error) { data, err := s.store.Get([]byte(key), nil) if err != nil { @@ -75,6 +78,7 @@ func (s *LevelDBStore) Get(key string) (interface{}, error) { return s.v, err } +// Del implements CacheStore func (s *LevelDBStore) Del(key string) error { err := s.store.Delete([]byte(key), nil) if err != nil { @@ -89,6 +93,7 @@ func (s *LevelDBStore) Del(key string) error { return err } +// Close implements CacheStore func (s *LevelDBStore) Close() { s.store.Close() } diff --git a/caches/manager.go b/caches/manager.go index 05045210..89a14106 100644 --- a/caches/manager.go +++ b/caches/manager.go @@ -6,6 +6,7 @@ package caches import "sync" +// Manager represents a cache manager type Manager struct { cacher Cacher disableGlobalCache bool @@ -14,6 +15,7 @@ type Manager struct { cacherLock sync.RWMutex } +// NewManager creates a cache manager func NewManager() *Manager { return &Manager{ cachers: make(map[string]Cacher), @@ -27,12 +29,14 @@ func (mgr *Manager) SetDisableGlobalCache(disable bool) { } } +// SetCacher set cacher of table func (mgr *Manager) SetCacher(tableName string, cacher Cacher) { mgr.cacherLock.Lock() mgr.cachers[tableName] = cacher mgr.cacherLock.Unlock() } +// GetCacher returns a cache of a table func (mgr *Manager) GetCacher(tableName string) Cacher { var cacher Cacher var ok bool diff --git a/contexts/hook.go b/contexts/hook.go index 71ad8e87..70f114dd 100644 --- a/contexts/hook.go +++ b/contexts/hook.go @@ -31,6 +31,7 @@ func NewContextHook(ctx context.Context, sql string, args []interface{}) *Contex } } +// End finish the hook invokation func (c *ContextHook) End(ctx context.Context, result sql.Result, err error) { c.Ctx = ctx c.Result = result @@ -38,19 +39,23 @@ func (c *ContextHook) End(ctx context.Context, result sql.Result, err error) { c.ExecuteTime = time.Now().Sub(c.start) } +// Hook represents a hook behaviour type Hook interface { BeforeProcess(c *ContextHook) (context.Context, error) AfterProcess(c *ContextHook) error } +// Hooks implements Hook interface but contains multiple Hook type Hooks struct { hooks []Hook } +// AddHook adds a Hook func (h *Hooks) AddHook(hooks ...Hook) { h.hooks = append(h.hooks, hooks...) } +// BeforeProcess invoked before execute the process func (h *Hooks) BeforeProcess(c *ContextHook) (context.Context, error) { ctx := c.Ctx for _, h := range h.hooks { @@ -63,6 +68,7 @@ func (h *Hooks) BeforeProcess(c *ContextHook) (context.Context, error) { return ctx, nil } +// AfterProcess invoked after exetue the process func (h *Hooks) AfterProcess(c *ContextHook) error { firstErr := c.Err for _, h := range h.hooks { diff --git a/dialects/dialect.go b/dialects/dialect.go index d9a640a4..b02ec4ae 100644 --- a/dialects/dialect.go +++ b/dialects/dialect.go @@ -79,32 +79,34 @@ type Base struct { quoter schemas.Quoter } -func (b *Base) Quoter() schemas.Quoter { - return b.quoter +// Quoter returns the current database Quoter +func (db *Base) Quoter() schemas.Quoter { + return db.quoter } -func (b *Base) Init(dialect Dialect, uri *URI) error { - b.dialect, b.uri = dialect, uri +// Init initialize the dialect +func (db *Base) Init(dialect Dialect, uri *URI) error { + db.dialect, db.uri = dialect, uri return nil } -func (b *Base) URI() *URI { - return b.uri +// URI returns the uri of database +func (db *Base) URI() *URI { + return db.uri } -func (b *Base) DBType() schemas.DBType { - return b.uri.DBType -} - -func (b *Base) FormatBytes(bs []byte) string { +// FormatBytes formats bytes +func (db *Base) FormatBytes(bs []byte) string { return fmt.Sprintf("0x%x", bs) } +// DropTableSQL returns drop table SQL func (db *Base) DropTableSQL(tableName string) (string, bool) { quote := db.dialect.Quoter().Quote return fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName)), true } +// HasRecords returns true if the SQL has records returned func (db *Base) HasRecords(queryer core.Queryer, ctx context.Context, query string, args ...interface{}) (bool, error) { rows, err := queryer.QueryContext(ctx, query, args...) if err != nil { @@ -118,6 +120,7 @@ func (db *Base) HasRecords(queryer core.Queryer, ctx context.Context, query stri return false, nil } +// IsColumnExist returns true if the column of the table exist func (db *Base) IsColumnExist(queryer core.Queryer, ctx context.Context, tableName, colName string) (bool, error) { quote := db.dialect.Quoter().Quote query := fmt.Sprintf( @@ -132,11 +135,13 @@ func (db *Base) IsColumnExist(queryer core.Queryer, ctx context.Context, tableNa return db.HasRecords(queryer, ctx, query, db.uri.DBName, tableName, colName) } +// AddColumnSQL returns a SQL to add a column func (db *Base) AddColumnSQL(tableName string, col *schemas.Column) string { s, _ := ColumnString(db.dialect, col, true) return fmt.Sprintf("ALTER TABLE %v ADD %v", db.dialect.Quoter().Quote(tableName), s) } +// CreateIndexSQL returns a SQL to create index func (db *Base) CreateIndexSQL(tableName string, index *schemas.Index) string { quoter := db.dialect.Quoter() var unique string @@ -150,6 +155,7 @@ func (db *Base) CreateIndexSQL(tableName string, index *schemas.Index) string { quoter.Join(index.Cols, ",")) } +// DropIndexSQL returns a SQL to drop index func (db *Base) DropIndexSQL(tableName string, index *schemas.Index) string { quote := db.dialect.Quoter().Quote var name string @@ -161,16 +167,19 @@ func (db *Base) DropIndexSQL(tableName string, index *schemas.Index) string { return fmt.Sprintf("DROP INDEX %v ON %s", quote(name), quote(tableName)) } +// ModifyColumnSQL returns a SQL to modify SQL func (db *Base) ModifyColumnSQL(tableName string, col *schemas.Column) string { s, _ := ColumnString(db.dialect, col, false) return fmt.Sprintf("ALTER TABLE %s MODIFY COLUMN %s", tableName, s) } -func (b *Base) ForUpdateSQL(query string) string { +// ForUpdateSQL returns for updateSQL +func (db *Base) ForUpdateSQL(query string) string { return query + " FOR UPDATE" } -func (b *Base) SetParams(params map[string]string) { +// SetParams set params +func (db *Base) SetParams(params map[string]string) { } var ( diff --git a/engine.go b/engine.go index ee98ed05..384928d6 100644 --- a/engine.go +++ b/engine.go @@ -1278,6 +1278,7 @@ func (engine *Engine) SetSchema(schema string) { engine.dialect.URI().SetSchema(schema) } +// AddHook adds a context Hook func (engine *Engine) AddHook(hook contexts.Hook) { engine.db.AddHook(hook) } @@ -1293,7 +1294,7 @@ func (engine *Engine) tbNameWithSchema(v string) string { return dialects.TableNameWithSchema(engine.dialect, v) } -// ContextHook creates a session with the context +// Context creates a session with the context func (engine *Engine) Context(ctx context.Context) *Session { session := engine.NewSession() session.isAutoClose = true diff --git a/engine_group.go b/engine_group.go index 3e91cbd6..3569690b 100644 --- a/engine_group.go +++ b/engine_group.go @@ -79,7 +79,7 @@ func (eg *EngineGroup) Close() error { return nil } -// ContextHook returned a group session +// Context returned a group session func (eg *EngineGroup) Context(ctx context.Context) *Session { sess := eg.NewSession() sess.isAutoClose = true @@ -144,6 +144,7 @@ func (eg *EngineGroup) SetLogger(logger interface{}) { } } +// AddHook adds Hook func (eg *EngineGroup) AddHook(hook contexts.Hook) { eg.Engine.AddHook(hook) for i := 0; i < len(eg.slaves); i++ { diff --git a/integrations/engine_test.go b/integrations/engine_test.go index 1e2e9f4a..3b843f16 100644 --- a/integrations/engine_test.go +++ b/integrations/engine_test.go @@ -190,7 +190,7 @@ func TestSetSchema(t *testing.T) { func TestImport(t *testing.T) { if testEngine.Dialect().URI().DBType != schemas.MYSQL { - t.SkipNow() + t.Skip() return } sess := testEngine.NewSession() diff --git a/integrations/tests.go b/integrations/tests.go index 840b1020..512f3962 100644 --- a/integrations/tests.go +++ b/integrations/tests.go @@ -8,6 +8,7 @@ import ( "database/sql" "flag" "fmt" + "net/url" "os" "strings" "testing" @@ -97,6 +98,13 @@ func createEngine(dbType, connStr string) error { return fmt.Errorf("db.Exec: %v", err) } db.Close() + case schemas.SQLITE, "sqlite": + u, err := url.Parse(connStr) + if err != nil { + return err + } + connStr = u.Path + *ignoreSelectUpdate = true default: *ignoreSelectUpdate = true } @@ -164,10 +172,12 @@ func createEngine(dbType, connStr string) error { return nil } +// PrepareEngine prepare tests ORM engine func PrepareEngine() error { return createEngine(dbType, connString) } +// MainTest the tests entrance func MainTest(m *testing.M) { flag.Parse() diff --git a/internal/json/json.go b/internal/json/json.go index c9a2eb4e..ef52f51f 100644 --- a/internal/json/json.go +++ b/internal/json/json.go @@ -6,15 +6,15 @@ package json import "encoding/json" -// JSONInterface represents an interface to handle json data -type JSONInterface interface { +// Interface represents an interface to handle json data +type Interface interface { Marshal(v interface{}) ([]byte, error) Unmarshal(data []byte, v interface{}) error } var ( // DefaultJSONHandler default json handler - DefaultJSONHandler JSONInterface = StdJSON{} + DefaultJSONHandler Interface = StdJSON{} ) // StdJSON implements JSONInterface via encoding/json diff --git a/internal/utils/name.go b/internal/utils/name.go index f5fc3ff7..840dd9e8 100644 --- a/internal/utils/name.go +++ b/internal/utils/name.go @@ -8,6 +8,7 @@ import ( "fmt" ) +// IndexName returns index name func IndexName(tableName, idxName string) string { return fmt.Sprintf("IDX_%v_%v", tableName, idxName) } diff --git a/internal/utils/reflect.go b/internal/utils/reflect.go index 3dad6bfe..7973d4d3 100644 --- a/internal/utils/reflect.go +++ b/internal/utils/reflect.go @@ -8,6 +8,7 @@ import ( "reflect" ) +// ReflectValue returns value of a bean func ReflectValue(bean interface{}) reflect.Value { return reflect.Indirect(reflect.ValueOf(bean)) } diff --git a/internal/utils/sql.go b/internal/utils/sql.go index 5e68c4a4..369ca2b8 100644 --- a/internal/utils/sql.go +++ b/internal/utils/sql.go @@ -8,6 +8,7 @@ import ( "strings" ) +// IsSubQuery returns true if it contains a sub query func IsSubQuery(tbName string) bool { const selStr = "select" if len(tbName) <= len(selStr)+1 { diff --git a/internal/utils/strings.go b/internal/utils/strings.go index 72466705..86469c0f 100644 --- a/internal/utils/strings.go +++ b/internal/utils/strings.go @@ -8,10 +8,12 @@ import ( "strings" ) +// IndexNoCase index a string in a string with no care of capitalize func IndexNoCase(s, sep string) int { return strings.Index(strings.ToLower(s), strings.ToLower(sep)) } +// SplitNoCase split a string by a seperator with no care of capitalize func SplitNoCase(s, sep string) []string { idx := IndexNoCase(s, sep) if idx < 0 { @@ -20,6 +22,7 @@ func SplitNoCase(s, sep string) []string { return strings.Split(s, s[idx:idx+len(sep)]) } +// SplitNNoCase split n by a seperator with no care of capitalize func SplitNNoCase(s, sep string, n int) []string { idx := IndexNoCase(s, sep) if idx < 0 { diff --git a/internal/utils/zero.go b/internal/utils/zero.go index 8f033c60..007e3c33 100644 --- a/internal/utils/zero.go +++ b/internal/utils/zero.go @@ -9,6 +9,7 @@ import ( "time" ) +// Zeroable represents an interface which could know if it's a zero value type Zeroable interface { IsZero() bool } @@ -21,39 +22,39 @@ func IsZero(k interface{}) bool { return true } - switch k.(type) { + switch t := k.(type) { case int: - return k.(int) == 0 + return t == 0 case int8: - return k.(int8) == 0 + return t == 0 case int16: - return k.(int16) == 0 + return t == 0 case int32: - return k.(int32) == 0 + return t == 0 case int64: - return k.(int64) == 0 + return t == 0 case uint: - return k.(uint) == 0 + return t == 0 case uint8: - return k.(uint8) == 0 + return t == 0 case uint16: - return k.(uint16) == 0 + return t == 0 case uint32: - return k.(uint32) == 0 + return t == 0 case uint64: - return k.(uint64) == 0 + return t == 0 case float32: - return k.(float32) == 0 + return t == 0 case float64: - return k.(float64) == 0 + return t == 0 case bool: - return k.(bool) == false + return !t case string: - return k.(string) == "" + return t == "" case *time.Time: - return k.(*time.Time) == nilTime || IsTimeZero(*k.(*time.Time)) + return t == nilTime || IsTimeZero(*t) case time.Time: - return IsTimeZero(k.(time.Time)) + return IsTimeZero(t) case Zeroable: return k.(Zeroable) == nil || k.(Zeroable).IsZero() case reflect.Value: // for go version less than 1.13 because reflect.Value has no method IsZero @@ -65,6 +66,7 @@ func IsZero(k interface{}) bool { var zeroType = reflect.TypeOf((*Zeroable)(nil)).Elem() +// IsValueZero returns true if the reflect Value is a zero func IsValueZero(v reflect.Value) bool { switch v.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Slice: @@ -88,6 +90,7 @@ func IsValueZero(v reflect.Value) bool { return false } +// IsStructZero returns true if the Value is a struct and all fields is zero func IsStructZero(v reflect.Value) bool { if !v.IsValid() || v.NumField() == 0 { return true @@ -120,6 +123,7 @@ func IsStructZero(v reflect.Value) bool { return true } +// IsArrayZero returns true is a slice of array is zero func IsArrayZero(v reflect.Value) bool { if !v.IsValid() || v.Len() == 0 { return true @@ -134,11 +138,13 @@ func IsArrayZero(v reflect.Value) bool { return true } +// represents all zero times const ( ZeroTime0 = "0000-00-00 00:00:00" ZeroTime1 = "0001-01-01 00:00:00" ) +// IsTimeZero return true if a time is zero func IsTimeZero(t time.Time) bool { return t.IsZero() || t.Format("2006-01-02 15:04:05") == ZeroTime0 || t.Format("2006-01-02 15:04:05") == ZeroTime1 diff --git a/migrate/migrate.go b/migrate/migrate.go index 82c58f90..19b4afe0 100644 --- a/migrate/migrate.go +++ b/migrate/migrate.go @@ -110,10 +110,7 @@ func (m *Migrate) RollbackLast() error { return err } - if err := m.RollbackMigration(lastRunnedMigration); err != nil { - return err - } - return nil + return m.RollbackMigration(lastRunnedMigration) } func (m *Migrate) getLastRunnedMigration() (*Migration, error) { diff --git a/migrate/migrate_test.go b/migrate/migrate_test.go index 19554f7e..3d7aa189 100644 --- a/migrate/migrate_test.go +++ b/migrate/migrate_test.go @@ -106,10 +106,7 @@ func TestInitSchema(t *testing.T) { if err := tx.Sync2(&Person{}); err != nil { return err } - if err := tx.Sync2(&Pet{}); err != nil { - return err - } - return nil + return tx.Sync2(&Pet{}) }) err = m.Migrate() diff --git a/session.go b/session.go index 17abd453..d5ccb6dc 100644 --- a/session.go +++ b/session.go @@ -169,6 +169,7 @@ func (session *Session) db() *core.DB { return session.engine.db } +// Engine returns session Engine func (session *Session) Engine() *Engine { return session.engine } @@ -895,7 +896,7 @@ func (session *Session) incrVersionFieldValue(fieldValue *reflect.Value) { } } -// ContextHook sets the context on this session +// Context sets the context on this session func (session *Session) Context(ctx context.Context) *Session { session.ctx = ctx return session diff --git a/session_get.go b/session_get.go index 6e65ea2f..e303176d 100644 --- a/session_get.go +++ b/session_get.go @@ -17,6 +17,7 @@ import ( ) var ( + // ErrObjectIsNil return error of object is nil ErrObjectIsNil = errors.New("object should not be nil") ) diff --git a/session_tx.go b/session_tx.go index 33ef72c6..8763784c 100644 --- a/session_tx.go +++ b/session_tx.go @@ -85,7 +85,7 @@ func (session *Session) Commit() error { return nil } -// if current session is in a transaction +// IsInTx if current session is in a transaction func (session *Session) IsInTx() bool { return !session.isAutoCommit } From 60cc3eaaf08848bad9c1f8c026482a26cda87ecb Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 11 Apr 2021 16:47:04 +0800 Subject: [PATCH 61/61] Unsigned Support (#1889) This PR add support to MySQL, for other databases unsigned type will be downgrade to the related signed type. Replace #1810 Reviewed-on: https://gitea.com/xorm/xorm/pulls/1889 Co-authored-by: Lunny Xiao Co-committed-by: Lunny Xiao --- dialects/mssql.go | 4 ++-- dialects/mysql.go | 29 ++++++++++++++++++-------- dialects/postgres.go | 8 ++++++-- dialects/sqlite3.go | 3 ++- go.mod | 4 ++-- go.sum | 4 ++-- integrations/types_test.go | 27 ++++++++++++++++++++++++ schemas/type.go | 42 +++++++++++++++++++++++--------------- 8 files changed, 87 insertions(+), 34 deletions(-) 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: