Jelajahi Sumber

add test for tablename

* add test for update map

* refactor buildUpdates

* fix id condition not used bug
xormplus 7 tahun lalu
induk
melakukan
eecdbe9f54
11 mengubah file dengan 432 tambahan dan 238 penghapusan
  1. 1 1
      cache_lru_test.go
  2. 28 0
      engine_table_test.go
  3. 0 162
      helpers.go
  4. 107 0
      session_cols.go
  5. 11 2
      session_get_test.go
  6. 99 18
      session_insert.go
  7. 4 0
      session_query.go
  8. 94 6
      session_update.go
  9. 50 0
      session_update_test.go
  10. 37 48
      statement.go
  11. 1 1
      xorm_test.go

+ 1 - 1
cache_lru_test.go

@@ -7,8 +7,8 @@ package xorm
 import (
 	"testing"
 
-	"github.com/go-xorm/core"
 	"github.com/stretchr/testify/assert"
+	"github.com/xormplus/core"
 )
 
 func TestLRUCache(t *testing.T) {

+ 28 - 0
engine_table_test.go

@@ -0,0 +1,28 @@
+// Copyright 2018 The Xorm Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xorm
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+type MCC struct {
+	ID          int64  `xorm:"pk 'id'"`
+	Code        string `xorm:"'code'"`
+	Description string `xorm:"'description'"`
+}
+
+func (mcc *MCC) TableName() string {
+	return "mcc"
+}
+
+func TestTableName1(t *testing.T) {
+	assert.NoError(t, prepareEngine())
+
+	assert.EqualValues(t, "mcc", testEngine.TableName(new(MCC)))
+	assert.EqualValues(t, "mcc", testEngine.TableName("mcc"))
+}

+ 0 - 162
helpers.go

@@ -11,7 +11,6 @@ import (
 	"sort"
 	"strconv"
 	"strings"
-	"time"
 
 	"github.com/xormplus/core"
 )
@@ -293,19 +292,6 @@ func structName(v reflect.Type) string {
 	return v.Name()
 }
 
-func col2NewCols(columns ...string) []string {
-	newColumns := make([]string, 0, len(columns))
-	for _, col := range columns {
-		col = strings.Replace(col, "`", "", -1)
-		col = strings.Replace(col, `"`, "", -1)
-		ccols := strings.Split(col, ",")
-		for _, c := range ccols {
-			newColumns = append(newColumns, strings.TrimSpace(c))
-		}
-	}
-	return newColumns
-}
-
 func sliceEq(left, right []string) bool {
 	if len(left) != len(right) {
 		return false
@@ -320,154 +306,6 @@ func sliceEq(left, right []string) bool {
 	return true
 }
 
-func setColumnInt(bean interface{}, col *core.Column, t int64) {
-	v, err := col.ValueOf(bean)
-	if err != nil {
-		return
-	}
-	if v.CanSet() {
-		switch v.Type().Kind() {
-		case reflect.Int, reflect.Int64, reflect.Int32:
-			v.SetInt(t)
-		case reflect.Uint, reflect.Uint64, reflect.Uint32:
-			v.SetUint(uint64(t))
-		}
-	}
-}
-
-func setColumnTime(bean interface{}, col *core.Column, t time.Time) {
-	v, err := col.ValueOf(bean)
-	if err != nil {
-		return
-	}
-	if v.CanSet() {
-		switch v.Type().Kind() {
-		case reflect.Struct:
-			v.Set(reflect.ValueOf(t).Convert(v.Type()))
-		case reflect.Int, reflect.Int64, reflect.Int32:
-			v.SetInt(t.Unix())
-		case reflect.Uint, reflect.Uint64, reflect.Uint32:
-			v.SetUint(uint64(t.Unix()))
-		}
-	}
-}
-
-func genCols(table *core.Table, session *Session, bean interface{}, useCol bool, includeQuote bool) ([]string, []interface{}, error) {
-	colNames := make([]string, 0, len(table.ColumnsSeq()))
-	args := make([]interface{}, 0, len(table.ColumnsSeq()))
-
-	for _, col := range table.Columns() {
-		if useCol && !col.IsVersion && !col.IsCreated && !col.IsUpdated {
-			if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
-				continue
-			}
-		}
-		if col.MapType == core.ONLYFROMDB {
-			continue
-		}
-
-		fieldValuePtr, err := col.ValueOf(bean)
-		if err != nil {
-			return nil, nil, err
-		}
-		fieldValue := *fieldValuePtr
-
-		if col.IsAutoIncrement {
-			switch fieldValue.Type().Kind() {
-			case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
-				if fieldValue.Int() == 0 {
-					continue
-				}
-			case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
-				if fieldValue.Uint() == 0 {
-					continue
-				}
-			case reflect.String:
-				if len(fieldValue.String()) == 0 {
-					continue
-				}
-			case reflect.Ptr:
-				if fieldValue.Pointer() == 0 {
-					continue
-				}
-			}
-		}
-
-		if col.IsDeleted {
-			continue
-		}
-
-		if session.statement.ColumnStr != "" {
-			if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
-				continue
-			} else if _, ok := session.statement.incrColumns[col.Name]; ok {
-				continue
-			} else if _, ok := session.statement.decrColumns[col.Name]; ok {
-				continue
-			}
-		}
-		if session.statement.OmitStr != "" {
-			if _, ok := getFlagForColumn(session.statement.columnMap, col); ok {
-				continue
-			}
-		}
-
-		// !evalphobia! set fieldValue as nil when column is nullable and zero-value
-		if _, ok := getFlagForColumn(session.statement.nullableMap, col); ok {
-			if col.Nullable && isZero(fieldValue.Interface()) {
-				var nilValue *int
-				fieldValue = reflect.ValueOf(nilValue)
-			}
-		}
-
-		if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime /*&& isZero(fieldValue.Interface())*/ {
-			// if time is non-empty, then set to auto time
-			val, t := session.engine.nowTime(col)
-			args = append(args, val)
-
-			var colName = col.Name
-			session.afterClosures = append(session.afterClosures, func(bean interface{}) {
-				col := table.GetColumn(colName)
-				setColumnTime(bean, col, t)
-			})
-		} else if col.IsVersion && session.statement.checkVersion {
-			args = append(args, 1)
-		} else {
-			arg, err := session.value2Interface(col, fieldValue)
-			if err != nil {
-				return colNames, args, err
-			}
-			args = append(args, arg)
-		}
-
-		if includeQuote {
-			colNames = append(colNames, session.engine.Quote(col.Name)+" = ?")
-		} else {
-			colNames = append(colNames, col.Name)
-		}
-	}
-	return colNames, args, nil
-}
-
 func indexName(tableName, idxName string) string {
 	return fmt.Sprintf("IDX_%v_%v", tableName, idxName)
 }
-
-func getFlagForColumn(m map[string]bool, col *core.Column) (val bool, has bool) {
-	if len(m) == 0 {
-		return false, false
-	}
-
-	n := len(col.Name)
-
-	for mk := range m {
-		if len(mk) != n {
-			continue
-		}
-		if strings.EqualFold(mk, col.Name) {
-			return m[mk], true
-		}
-	}
-
-	return false, false
-}

+ 107 - 0
session_cols.go

@@ -4,6 +4,113 @@
 
 package xorm
 
+import (
+	"reflect"
+	"strings"
+	"time"
+
+	"github.com/xormplus/core"
+)
+
+type incrParam struct {
+	colName string
+	arg     interface{}
+}
+
+type decrParam struct {
+	colName string
+	arg     interface{}
+}
+
+type exprParam struct {
+	colName string
+	expr    string
+}
+
+type columnMap []string
+
+func (m columnMap) contain(colName string) bool {
+	if len(m) == 0 {
+		return false
+	}
+
+	n := len(colName)
+	for _, mk := range m {
+		if len(mk) != n {
+			continue
+		}
+		if strings.EqualFold(mk, colName) {
+			return true
+		}
+	}
+
+	return false
+}
+
+func setColumnInt(bean interface{}, col *core.Column, t int64) {
+	v, err := col.ValueOf(bean)
+	if err != nil {
+		return
+	}
+	if v.CanSet() {
+		switch v.Type().Kind() {
+		case reflect.Int, reflect.Int64, reflect.Int32:
+			v.SetInt(t)
+		case reflect.Uint, reflect.Uint64, reflect.Uint32:
+			v.SetUint(uint64(t))
+		}
+	}
+}
+
+func setColumnTime(bean interface{}, col *core.Column, t time.Time) {
+	v, err := col.ValueOf(bean)
+	if err != nil {
+		return
+	}
+	if v.CanSet() {
+		switch v.Type().Kind() {
+		case reflect.Struct:
+			v.Set(reflect.ValueOf(t).Convert(v.Type()))
+		case reflect.Int, reflect.Int64, reflect.Int32:
+			v.SetInt(t.Unix())
+		case reflect.Uint, reflect.Uint64, reflect.Uint32:
+			v.SetUint(uint64(t.Unix()))
+		}
+	}
+}
+
+func getFlagForColumn(m map[string]bool, col *core.Column) (val bool, has bool) {
+	if len(m) == 0 {
+		return false, false
+	}
+
+	n := len(col.Name)
+
+	for mk := range m {
+		if len(mk) != n {
+			continue
+		}
+		if strings.EqualFold(mk, col.Name) {
+			return m[mk], true
+		}
+	}
+
+	return false, false
+}
+
+func col2NewCols(columns ...string) []string {
+	newColumns := make([]string, 0, len(columns))
+	for _, col := range columns {
+		col = strings.Replace(col, "`", "", -1)
+		col = strings.Replace(col, `"`, "", -1)
+		ccols := strings.Split(col, ",")
+		for _, c := range ccols {
+			newColumns = append(newColumns, strings.TrimSpace(c))
+		}
+	}
+	return newColumns
+}
+
 // Incr provides a query string like "count = count + 1"
 func (session *Session) Incr(column string, args ...interface{}) *Session {
 	session.statement.Incr(column, args...)

+ 11 - 2
session_get_test.go

@@ -278,11 +278,20 @@ func TestGetActionMapping(t *testing.T) {
 
 	assertSync(t, new(ActionMapping))
 
+	_, err := testEngine.Insert(&ActionMapping{
+		ActionId: "1",
+		ScriptId: "2",
+	})
+	assert.NoError(t, err)
+
 	var valuesSlice = make([]string, 2)
-	_, err := testEngine.Table(new(ActionMapping)).
+	has, err := testEngine.Table(new(ActionMapping)).
 		Cols("script_id", "rollback_id").
-		ID(1).Get(&valuesSlice)
+		ID("1").Get(&valuesSlice)
 	assert.NoError(t, err)
+	assert.True(t, has)
+	assert.EqualValues(t, "2", valuesSlice[0])
+	assert.EqualValues(t, "", valuesSlice[1])
 }
 
 func TestGetStructId(t *testing.T) {

+ 99 - 18
session_insert.go

@@ -115,15 +115,11 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
 				if col.IsDeleted {
 					continue
 				}
-				if session.statement.ColumnStr != "" {
-					if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
-						continue
-					}
+				if session.statement.omitColumnMap.contain(col.Name) {
+					continue
 				}
-				if session.statement.OmitStr != "" {
-					if _, ok := getFlagForColumn(session.statement.columnMap, col); ok {
-						continue
-					}
+				if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
+					continue
 				}
 				if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime {
 					val, t := session.engine.nowTime(col)
@@ -170,15 +166,11 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
 				if col.IsDeleted {
 					continue
 				}
-				if session.statement.ColumnStr != "" {
-					if _, ok := getFlagForColumn(session.statement.columnMap, col); !ok {
-						continue
-					}
+				if session.statement.omitColumnMap.contain(col.Name) {
+					continue
 				}
-				if session.statement.OmitStr != "" {
-					if _, ok := getFlagForColumn(session.statement.columnMap, col); ok {
-						continue
-					}
+				if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
+					continue
 				}
 				if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime {
 					val, t := session.engine.nowTime(col)
@@ -316,8 +308,8 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 	if processor, ok := interface{}(bean).(BeforeInsertProcessor); ok {
 		processor.BeforeInsert()
 	}
-	// --
-	colNames, args, err := genCols(session.statement.RefTable, session, bean, false, false)
+
+	colNames, args, err := session.genInsertColumns(bean)
 	if err != nil {
 		return 0, err
 	}
@@ -552,3 +544,92 @@ func (session *Session) cacheInsert(table *core.Table, tables ...string) error {
 
 	return nil
 }
+
+// genInsertColumns generates insert needed columns
+func (session *Session) genInsertColumns(bean interface{}) ([]string, []interface{}, error) {
+	table := session.statement.RefTable
+	colNames := make([]string, 0, len(table.ColumnsSeq()))
+	args := make([]interface{}, 0, len(table.ColumnsSeq()))
+
+	for _, col := range table.Columns() {
+		if col.MapType == core.ONLYFROMDB {
+			continue
+		}
+
+		if col.IsDeleted {
+			continue
+		}
+
+		if session.statement.omitColumnMap.contain(col.Name) {
+			continue
+		}
+
+		if len(session.statement.columnMap) > 0 && !session.statement.columnMap.contain(col.Name) {
+			continue
+		}
+
+		if _, ok := session.statement.incrColumns[col.Name]; ok {
+			continue
+		} else if _, ok := session.statement.decrColumns[col.Name]; ok {
+			continue
+		}
+
+		fieldValuePtr, err := col.ValueOf(bean)
+		if err != nil {
+			return nil, nil, err
+		}
+		fieldValue := *fieldValuePtr
+
+		if col.IsAutoIncrement {
+			switch fieldValue.Type().Kind() {
+			case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
+				if fieldValue.Int() == 0 {
+					continue
+				}
+			case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
+				if fieldValue.Uint() == 0 {
+					continue
+				}
+			case reflect.String:
+				if len(fieldValue.String()) == 0 {
+					continue
+				}
+			case reflect.Ptr:
+				if fieldValue.Pointer() == 0 {
+					continue
+				}
+			}
+		}
+
+		// !evalphobia! set fieldValue as nil when column is nullable and zero-value
+		if _, ok := getFlagForColumn(session.statement.nullableMap, col); ok {
+			if col.Nullable && isZero(fieldValue.Interface()) {
+				var nilValue *int
+				fieldValue = reflect.ValueOf(nilValue)
+			}
+		}
+
+		if (col.IsCreated || col.IsUpdated) && session.statement.UseAutoTime /*&& isZero(fieldValue.Interface())*/ {
+			// if time is non-empty, then set to auto time
+			val, t := session.engine.nowTime(col)
+			args = append(args, val)
+
+			var colName = col.Name
+			session.afterClosures = append(session.afterClosures, func(bean interface{}) {
+				col := table.GetColumn(colName)
+				setColumnTime(bean, col, t)
+			})
+		} else if col.IsVersion && session.statement.checkVersion {
+			args = append(args, 1)
+		} else {
+			arg, err := session.value2Interface(col, fieldValue)
+			if err != nil {
+				return colNames, args, err
+			}
+			args = append(args, arg)
+		}
+
+		colNames = append(colNames, col.Name)
+	}
+	return colNames, args, nil
+}

+ 4 - 0
session_query.go

@@ -84,6 +84,10 @@ func (session *Session) genQuerySQL(sqlorArgs ...interface{}) (string, []interfa
 		}
 	}
 
+	if err := session.statement.processIDParam(); err != nil {
+		return "", nil, err
+	}
+
 	condSQL, condArgs, err := builder.ToSQL(session.statement.cond)
 	if err != nil {
 		return "", nil, err

+ 94 - 6
session_update.go

@@ -176,12 +176,10 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 		}
 
 		if session.statement.ColumnStr == "" {
-			colNames, args = buildUpdates(session.engine, session.statement.RefTable, bean, false, false,
-				false, false, session.statement.allUseBool, session.statement.useAllCols,
-				session.statement.mustColumnMap, session.statement.nullableMap,
-				session.statement.columnMap, true, session.statement.unscoped)
+			colNames, args = session.statement.buildUpdates(bean, false, false,
+				false, false, true)
 		} else {
-			colNames, args, err = genCols(session.statement.RefTable, session, bean, true, true)
+			colNames, args, err = session.genUpdateColumns(bean)
 			if err != nil {
 				return 0, err
 			}
@@ -202,7 +200,8 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 	table := session.statement.RefTable
 
 	if session.statement.UseAutoTime && table != nil && table.Updated != "" {
-		if _, ok := session.statement.columnMap[strings.ToLower(table.Updated)]; !ok {
+		if !session.statement.columnMap.contain(table.Updated) &&
+			!session.statement.omitColumnMap.contain(table.Updated) {
 			colNames = append(colNames, session.engine.Quote(table.Updated)+" = ?")
 			col := table.UpdatedColumn()
 			val, t := session.engine.nowTime(col)
@@ -402,3 +401,92 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
 
 	return res.RowsAffected()
 }
+
+func (session *Session) genUpdateColumns(bean interface{}) ([]string, []interface{}, error) {
+	table := session.statement.RefTable
+	colNames := make([]string, 0, len(table.ColumnsSeq()))
+	args := make([]interface{}, 0, len(table.ColumnsSeq()))
+
+	for _, col := range table.Columns() {
+		if !col.IsVersion && !col.IsCreated && !col.IsUpdated {
+			if session.statement.omitColumnMap.contain(col.Name) {
+				continue
+			}
+		}
+		if col.MapType == core.ONLYFROMDB {
+			continue
+		}
+
+		fieldValuePtr, err := col.ValueOf(bean)
+		if err != nil {
+			return nil, nil, err
+		}
+		fieldValue := *fieldValuePtr
+
+		if col.IsAutoIncrement {
+			switch fieldValue.Type().Kind() {
+			case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
+				if fieldValue.Int() == 0 {
+					continue
+				}
+			case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
+				if fieldValue.Uint() == 0 {
+					continue
+				}
+			case reflect.String:
+				if len(fieldValue.String()) == 0 {
+					continue
+				}
+			case reflect.Ptr:
+				if fieldValue.Pointer() == 0 {
+					continue
+				}
+			}
+		}
+
+		if col.IsDeleted || col.IsCreated {
+			continue
+		}
+
+		if len(session.statement.columnMap) > 0 {
+			if !session.statement.columnMap.contain(col.Name) {
+				continue
+			} else if _, ok := session.statement.incrColumns[col.Name]; ok {
+				continue
+			} else if _, ok := session.statement.decrColumns[col.Name]; ok {
+				continue
+			}
+		}
+
+		// !evalphobia! set fieldValue as nil when column is nullable and zero-value
+		if _, ok := getFlagForColumn(session.statement.nullableMap, col); ok {
+			if col.Nullable && isZero(fieldValue.Interface()) {
+				var nilValue *int
+				fieldValue = reflect.ValueOf(nilValue)
+			}
+		}
+
+		if col.IsUpdated && session.statement.UseAutoTime /*&& isZero(fieldValue.Interface())*/ {
+			// if time is non-empty, then set to auto time
+			val, t := session.engine.nowTime(col)
+			args = append(args, val)
+
+			var colName = col.Name
+			session.afterClosures = append(session.afterClosures, func(bean interface{}) {
+				col := table.GetColumn(colName)
+				setColumnTime(bean, col, t)
+			})
+		} else if col.IsVersion && session.statement.checkVersion {
+			args = append(args, 1)
+		} else {
+			arg, err := session.value2Interface(col, fieldValue)
+			if err != nil {
+				return colNames, args, err
+			}
+			args = append(args, arg)
+		}
+
+		colNames = append(colNames, session.engine.Quote(col.Name)+" = ?")
+	}
+	return colNames, args, nil
+}

+ 50 - 0
session_update_test.go

@@ -1164,3 +1164,53 @@ func TestUpdateMapCondition(t *testing.T) {
 	assert.True(t, has)
 	assert.EqualValues(t, "string1", c2.String)
 }
+
+func TestUpdateMapContent(t *testing.T) {
+	assert.NoError(t, prepareEngine())
+
+	type UpdateMapContent struct {
+		Id     int64
+		Name   string
+		IsMan  bool
+		Age    int
+		Gender int // 1 is man, 2 is woman
+	}
+
+	assertSync(t, new(UpdateMapContent))
+
+	var c = UpdateMapContent{
+		Name:   "lunny",
+		IsMan:  true,
+		Gender: 1,
+		Age:    18,
+	}
+	_, err := testEngine.Insert(&c)
+	assert.NoError(t, err)
+	assert.EqualValues(t, 18, c.Age)
+
+	cnt, err := testEngine.Table(new(UpdateMapContent)).ID(c.Id).Update(map[string]interface{}{"age": 0})
+	assert.NoError(t, err)
+	assert.EqualValues(t, 1, cnt)
+
+	var c1 UpdateMapContent
+	has, err := testEngine.ID(c.Id).Get(&c1)
+	assert.NoError(t, err)
+	assert.True(t, has)
+	assert.EqualValues(t, 0, c1.Age)
+
+	cnt, err = testEngine.Table(new(UpdateMapContent)).ID(c.Id).Update(map[string]interface{}{
+		"age": 16,
+		"is_man": false,
+		"gender": 2,
+	})
+	assert.NoError(t, err)
+	assert.EqualValues(t, 1, cnt)
+
+	var c2 UpdateMapContent
+	has, err = testEngine.ID(c.Id).Get(&c2)
+	assert.NoError(t, err)
+	assert.True(t, has)
+	assert.EqualValues(t, 16, c2.Age)
+	assert.EqualValues(t, false, c2.IsMan)
+	assert.EqualValues(t, 2, c2.Gender)
+}

+ 37 - 48
statement.go

@@ -18,21 +18,6 @@ import (
 	"github.com/xormplus/core"
 )
 
-type incrParam struct {
-	colName string
-	arg     interface{}
-}
-
-type decrParam struct {
-	colName string
-	arg     interface{}
-}
-
-type exprParam struct {
-	colName string
-	expr    string
-}
-
 // Statement save all the sql info for executing SQL
 type Statement struct {
 	RefTable        *core.Table
@@ -47,7 +32,6 @@ type Statement struct {
 	HavingStr       string
 	ColumnStr       string
 	selectStr       string
-	columnMap       map[string]bool
 	useAllCols      bool
 	OmitStr         string
 	AltTableName    string
@@ -67,6 +51,8 @@ type Statement struct {
 	allUseBool      bool
 	checkVersion    bool
 	unscoped        bool
+	columnMap       columnMap
+	omitColumnMap   columnMap
 	mustColumnMap   map[string]bool
 	nullableMap     map[string]bool
 	incrColumns     map[string]incrParam
@@ -89,7 +75,8 @@ func (statement *Statement) Init() {
 	statement.HavingStr = ""
 	statement.ColumnStr = ""
 	statement.OmitStr = ""
-	statement.columnMap = make(map[string]bool)
+	statement.columnMap = columnMap{}
+	statement.omitColumnMap = columnMap{}
 	statement.AltTableName = ""
 	statement.tableName = ""
 	statement.idParam = nil
@@ -236,11 +223,18 @@ func (statement *Statement) setRefBean(bean interface{}) error {
 }
 
 // Auto generating update columnes and values according a struct
-func buildUpdates(engine *Engine, table *core.Table, bean interface{},
-	includeVersion bool, includeUpdated bool, includeNil bool,
-	includeAutoIncr bool, allUseBool bool, useAllCols bool,
-	mustColumnMap map[string]bool, nullableMap map[string]bool,
-	columnMap map[string]bool, update, unscoped bool) ([]string, []interface{}) {
+func (statement *Statement) buildUpdates(bean interface{},
+	includeVersion, includeUpdated, includeNil,
+	includeAutoIncr, update bool) ([]string, []interface{}) {
+	engine := statement.Engine
+	table := statement.RefTable
+	allUseBool := statement.allUseBool
+	useAllCols := statement.useAllCols
+	mustColumnMap := statement.mustColumnMap
+	nullableMap := statement.nullableMap
+	columnMap := statement.columnMap
+	omitColumnMap := statement.omitColumnMap
+	unscoped := statement.unscoped
 
 	var colNames = make([]string, 0)
 	var args = make([]interface{}, 0)
@@ -260,7 +254,10 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{},
 		if col.IsDeleted && !unscoped {
 			continue
 		}
-		if use, ok := columnMap[strings.ToLower(col.Name)]; ok && !use {
+		if omitColumnMap.contain(col.Name) {
+			continue
+		}
+		if len(columnMap) > 0 && !columnMap.contain(col.Name) {
 			continue
 		}
 
@@ -596,17 +593,10 @@ func (statement *Statement) col2NewColsWithQuote(columns ...string) []string {
 }
 
 func (statement *Statement) colmap2NewColsWithQuote() []string {
-	newColumns := make([]string, 0, len(statement.columnMap))
-	for col := range statement.columnMap {
-		fields := strings.Split(strings.TrimSpace(col), ".")
-		if len(fields) == 1 {
-			newColumns = append(newColumns, statement.Engine.quote(fields[0]))
-		} else if len(fields) == 2 {
-			newColumns = append(newColumns, statement.Engine.quote(fields[0])+"."+
-				statement.Engine.quote(fields[1]))
-		} else {
-			panic(errors.New("unwanted colnames"))
-		}
+	newColumns := make([]string, len(statement.columnMap), len(statement.columnMap))
+	copy(newColumns, statement.columnMap)
+	for i := 0; i < len(statement.columnMap); i++ {
+		newColumns[i] = statement.Engine.Quote(newColumns[i])
 	}
 	return newColumns
 }
@@ -634,10 +624,11 @@ func (statement *Statement) Select(str string) *Statement {
 func (statement *Statement) Cols(columns ...string) *Statement {
 	cols := col2NewCols(columns...)
 	for _, nc := range cols {
-		statement.columnMap[strings.ToLower(nc)] = true
+		statement.columnMap = append(statement.columnMap, nc)
 	}
 
 	newColumns := statement.colmap2NewColsWithQuote()
+
 	statement.ColumnStr = strings.Join(newColumns, ", ")
 	statement.ColumnStr = strings.Replace(statement.ColumnStr, statement.Engine.quote("*"), "*", -1)
 	return statement
@@ -672,7 +663,7 @@ func (statement *Statement) UseBool(columns ...string) *Statement {
 func (statement *Statement) Omit(columns ...string) {
 	newColumns := col2NewCols(columns...)
 	for _, nc := range newColumns {
-		statement.columnMap[strings.ToLower(nc)] = false
+		statement.omitColumnMap = append(statement.omitColumnMap, nc)
 	}
 	statement.OmitStr = statement.Engine.Quote(strings.Join(newColumns, statement.Engine.Quote(", ")))
 }
@@ -796,10 +787,12 @@ func (statement *Statement) genColumnStr() string {
 	columns := statement.RefTable.Columns()
 
 	for _, col := range columns {
-		if statement.OmitStr != "" {
-			if _, ok := getFlagForColumn(statement.columnMap, col); ok {
-				continue
-			}
+		if statement.omitColumnMap.contain(col.Name) {
+			continue
+		}
+
+		if len(statement.columnMap) > 0 && !statement.columnMap.contain(col.Name) {
+			continue
 		}
 
 		if col.MapType == core.ONLYTODB {
@@ -810,10 +803,6 @@ func (statement *Statement) genColumnStr() string {
 			buf.WriteString(", ")
 		}
 
-		if col.IsPrimaryKey && statement.Engine.Dialect().DBType() == "ql" {
-			buf.WriteString("id() AS ")
-		}
-
 		if statement.JoinStr != "" {
 			if statement.TableAlias != "" {
 				buf.WriteString(statement.TableAlias)
@@ -959,6 +948,10 @@ func (statement *Statement) genGetSQL(bean interface{}) (string, []interface{},
 		columnStr = "*"
 	}
 
+	if err := statement.processIDParam(); err != nil {
+		return "", nil, err
+	}
+
 	if isStruct {
 		if err := statement.mergeConds(bean); err != nil {
 			return "", nil, err
@@ -1043,10 +1036,6 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string, needLimit, n
 	var top string
 	var mssqlCondi string
 
-	if err := statement.processIDParam(); err != nil {
-		return "", err
-	}
-
 	var buf bytes.Buffer
 	if len(condSQL) > 0 {
 		fmt.Fprintf(&buf, " WHERE %v", condSQL)

+ 1 - 1
xorm_test.go

@@ -9,9 +9,9 @@ import (
 
 	_ "github.com/denisenkom/go-mssqldb"
 	_ "github.com/go-sql-driver/mysql"
-	"github.com/go-xorm/core"
 	_ "github.com/lib/pq"
 	_ "github.com/mattn/go-sqlite3"
+	"github.com/xormplus/core"
 	_ "github.com/ziutek/mymysql/godrv"
 )