瀏覽代碼

some comments, refactors improvements

xormplus 9 年之前
父節點
當前提交
6e437f24db
共有 5 個文件被更改,包括 203 次插入313 次删除
  1. 100 5
      helpers.go
  2. 56 258
      session.go
  3. 34 49
      statement.go
  4. 12 0
      types.go
  5. 1 1
      xorm.go

+ 100 - 5
helpers.go

@@ -5,6 +5,7 @@
 package xorm
 
 import (
+	"errors"
 	"fmt"
 	"reflect"
 	"sort"
@@ -15,6 +16,77 @@ import (
 	"github.com/xormplus/core"
 )
 
+// str2PK convert string value to primary key value according to tp
+func str2PK(s string, tp reflect.Type) (interface{}, error) {
+	var err error
+	var result interface{}
+	switch tp.Kind() {
+	case reflect.Int:
+		result, err = strconv.Atoi(s)
+		if err != nil {
+			return nil, errors.New("convert " + s + " as int: " + err.Error())
+		}
+	case reflect.Int8:
+		x, err := strconv.Atoi(s)
+		if err != nil {
+			return nil, errors.New("convert " + s + " as int16: " + err.Error())
+		}
+		result = int8(x)
+	case reflect.Int16:
+		x, err := strconv.Atoi(s)
+		if err != nil {
+			return nil, errors.New("convert " + s + " as int16: " + err.Error())
+		}
+		result = int16(x)
+	case reflect.Int32:
+		x, err := strconv.Atoi(s)
+		if err != nil {
+			return nil, errors.New("convert " + s + " as int32: " + err.Error())
+		}
+		result = int32(x)
+	case reflect.Int64:
+		result, err = strconv.ParseInt(s, 10, 64)
+		if err != nil {
+			return nil, errors.New("convert " + s + " as int64: " + err.Error())
+		}
+	case reflect.Uint:
+		x, err := strconv.ParseUint(s, 10, 64)
+		if err != nil {
+			return nil, errors.New("convert " + s + " as uint: " + err.Error())
+		}
+		result = uint(x)
+	case reflect.Uint8:
+		x, err := strconv.ParseUint(s, 10, 64)
+		if err != nil {
+			return nil, errors.New("convert " + s + " as uint8: " + err.Error())
+		}
+		result = uint8(x)
+	case reflect.Uint16:
+		x, err := strconv.ParseUint(s, 10, 64)
+		if err != nil {
+			return nil, errors.New("convert " + s + " as uint16: " + err.Error())
+		}
+		result = uint16(x)
+	case reflect.Uint32:
+		x, err := strconv.ParseUint(s, 10, 64)
+		if err != nil {
+			return nil, errors.New("convert " + s + " as uint32: " + err.Error())
+		}
+		result = uint32(x)
+	case reflect.Uint64:
+		result, err = strconv.ParseUint(s, 10, 64)
+		if err != nil {
+			return nil, errors.New("convert " + s + " as uint64: " + err.Error())
+		}
+	case reflect.String:
+		result = s
+	default:
+		panic("unsupported convert type")
+	}
+	result = reflect.ValueOf(result).Convert(tp).Interface()
+	return result, nil
+}
+
 func splitTag(tag string) (tags []string) {
 	tag = strings.TrimSpace(tag)
 	var hasQuote = false
@@ -75,15 +147,17 @@ func isZero(k interface{}) bool {
 	return false
 }
 
-func int64ToInt(id int64, k reflect.Kind) interface{} {
-	var v interface{} = id
-	switch k {
+func int64ToIntValue(id int64, tp reflect.Type) reflect.Value {
+	var v interface{}
+	switch tp.Kind() {
 	case reflect.Int16:
 		v = int16(id)
 	case reflect.Int32:
 		v = int32(id)
 	case reflect.Int:
 		v = int(id)
+	case reflect.Int64:
+		v = id
 	case reflect.Uint16:
 		v = uint16(id)
 	case reflect.Uint32:
@@ -93,7 +167,11 @@ func int64ToInt(id int64, k reflect.Kind) interface{} {
 	case reflect.Uint:
 		v = uint(id)
 	}
-	return v
+	return reflect.ValueOf(v).Convert(tp)
+}
+
+func int64ToInt(id int64, tp reflect.Type) interface{} {
+	return int64ToIntValue(id, tp).Interface()
 }
 
 func isPKZero(pk core.PK) bool {
@@ -154,6 +232,19 @@ 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
@@ -188,7 +279,7 @@ func reflect2value(rawValue *reflect.Value) (str string, err error) {
 		default:
 			err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name())
 		}
-	//时间类型
+	// time type
 	case reflect.Struct:
 		if aa.ConvertibleTo(core.TimeType) {
 			str = vv.Convert(core.TimeType).Interface().(time.Time).Format(time.RFC3339Nano)
@@ -447,3 +538,7 @@ func genCols(table *core.Table, session *Session, bean interface{}, useCol bool,
 	}
 	return colNames, args, nil
 }
+
+func indexName(tableName, idxName string) string {
+	return fmt.Sprintf("IDX_%v_%v", tableName, idxName)
+}

+ 56 - 258
session.go

@@ -961,7 +961,7 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
 			keyType := sliceValue.Type().Key()
 			var ikey interface{}
 			if len(key) == 1 {
-				ikey, err = Atot(fmt.Sprintf("%v", key[0]), keyType)
+				ikey, err = str2PK(fmt.Sprintf("%v", key[0]), keyType)
 				if err != nil {
 					return err
 				}
@@ -1124,75 +1124,6 @@ func (session *Session) Count(bean interface{}) (int64, error) {
 	return int64(total), err
 }
 
-func Atot(s string, tp reflect.Type) (interface{}, error) {
-	var err error
-	var result interface{}
-	switch tp.Kind() {
-	case reflect.Int:
-		result, err = strconv.Atoi(s)
-		if err != nil {
-			return nil, errors.New("convert " + s + " as int: " + err.Error())
-		}
-	case reflect.Int8:
-		x, err := strconv.Atoi(s)
-		if err != nil {
-			return nil, errors.New("convert " + s + " as int16: " + err.Error())
-		}
-		result = int8(x)
-	case reflect.Int16:
-		x, err := strconv.Atoi(s)
-		if err != nil {
-			return nil, errors.New("convert " + s + " as int16: " + err.Error())
-		}
-		result = int16(x)
-	case reflect.Int32:
-		x, err := strconv.Atoi(s)
-		if err != nil {
-			return nil, errors.New("convert " + s + " as int32: " + err.Error())
-		}
-		result = int32(x)
-	case reflect.Int64:
-		result, err = strconv.ParseInt(s, 10, 64)
-		if err != nil {
-			return nil, errors.New("convert " + s + " as int64: " + err.Error())
-		}
-	case reflect.Uint:
-		x, err := strconv.ParseUint(s, 10, 64)
-		if err != nil {
-			return nil, errors.New("convert " + s + " as uint: " + err.Error())
-		}
-		result = uint(x)
-	case reflect.Uint8:
-		x, err := strconv.ParseUint(s, 10, 64)
-		if err != nil {
-			return nil, errors.New("convert " + s + " as uint8: " + err.Error())
-		}
-		result = uint8(x)
-	case reflect.Uint16:
-		x, err := strconv.ParseUint(s, 10, 64)
-		if err != nil {
-			return nil, errors.New("convert " + s + " as uint16: " + err.Error())
-		}
-		result = uint16(x)
-	case reflect.Uint32:
-		x, err := strconv.ParseUint(s, 10, 64)
-		if err != nil {
-			return nil, errors.New("convert " + s + " as uint32: " + err.Error())
-		}
-		result = uint32(x)
-	case reflect.Uint64:
-		result, err = strconv.ParseUint(s, 10, 64)
-		if err != nil {
-			return nil, errors.New("convert " + s + " as uint64: " + err.Error())
-		}
-	case reflect.String:
-		result = s
-	default:
-		panic("unsupported convert type")
-	}
-	return result, nil
-}
-
 // Find retrieve records from table, condiBeans's non-empty fields
 // are conditions. beans could be []Struct, []*Struct, map[int64]Struct
 // map[int64]*Struct
@@ -1237,7 +1168,7 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
 		// !oinume! Add "<col> IS NULL" to WHERE whatever condiBean is given.
 		// See https://github.com/go-xorm/xorm/issues/179
 		if col := table.DeletedColumn(); col != nil && !session.Statement.unscoped { // tag "deleted" is enabled
-			var colName string = session.Engine.Quote(col.Name)
+			var colName = session.Engine.Quote(col.Name)
 			if addedTableName {
 				var nm = session.Statement.TableName()
 				if len(session.Statement.TableAlias) > 0 {
@@ -1326,8 +1257,6 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
 			return err
 		}
 
-		fieldsCount := len(fields)
-
 		var newElemFunc func() reflect.Value
 		if sliceElementType.Kind() == reflect.Ptr {
 			newElemFunc = func() reflect.Value {
@@ -1353,67 +1282,67 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
 			}
 		}
 
-		var newValue reflect.Value = newElemFunc()
+		var newValue = newElemFunc()
 		dataStruct := rValue(newValue.Interface())
 		if dataStruct.Kind() != reflect.Struct {
 			return errors.New("Expected a pointer to a struct")
 		}
 
-		table := session.Engine.autoMapType(dataStruct)
-		return session.rows2Beans(rawRows, fields, fieldsCount, table, newElemFunc, sliceValueSetFunc)
-	} else {
-		resultsSlice, err := session.query(sqlStr, args...)
+		return session.rows2Beans(rawRows, fields, len(fields), session.Engine.autoMapType(dataStruct), newElemFunc, sliceValueSetFunc)
+	}
+
+	resultsSlice, err := session.query(sqlStr, args...)
+	if err != nil {
+		return err
+	}
+
+	keyType := sliceValue.Type().Key()
+
+	for _, results := range resultsSlice {
+		var newValue reflect.Value
+		if sliceElementType.Kind() == reflect.Ptr {
+			newValue = reflect.New(sliceElementType.Elem())
+		} else {
+			newValue = reflect.New(sliceElementType)
+		}
+		err := session.scanMapIntoStruct(newValue.Interface(), results)
 		if err != nil {
 			return err
 		}
-
-		keyType := sliceValue.Type().Key()
-
-		for _, results := range resultsSlice {
-			var newValue reflect.Value
-			if sliceElementType.Kind() == reflect.Ptr {
-				newValue = reflect.New(sliceElementType.Elem())
-			} else {
-				newValue = reflect.New(sliceElementType)
-			}
-			err := session.scanMapIntoStruct(newValue.Interface(), results)
+		var key interface{}
+		// if there is only one pk, we can put the id as map key.
+		if len(table.PrimaryKeys) == 1 {
+			key, err = str2PK(string(results[table.PrimaryKeys[0]]), keyType)
 			if err != nil {
 				return err
 			}
-			var key interface{}
-			// if there is only one pk, we can put the id as map key.
-			if len(table.PrimaryKeys) == 1 {
-				key, err = Atot(string(results[table.PrimaryKeys[0]]), keyType)
-				if err != nil {
-					return err
-				}
+		} else {
+			if keyType.Kind() != reflect.Slice {
+				panic("don't support multiple primary key's map has non-slice key type")
 			} else {
-				if keyType.Kind() != reflect.Slice {
-					panic("don't support multiple primary key's map has non-slice key type")
-				} else {
-					keys := core.PK{}
-					for _, pk := range table.PrimaryKeys {
-						skey, err := Atot(string(results[pk]), keyType)
-						if err != nil {
-							return err
-						}
-						keys = append(keys, skey)
+				var keys core.PK = make([]interface{}, 0, len(table.PrimaryKeys))
+				for _, pk := range table.PrimaryKeys {
+					skey, err := str2PK(string(results[pk]), keyType)
+					if err != nil {
+						return err
 					}
-					key = keys
+					keys = append(keys, skey)
 				}
+				key = keys
 			}
+		}
 
-			if sliceElementType.Kind() == reflect.Ptr {
-				sliceValue.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(newValue.Interface()))
-			} else {
-				sliceValue.SetMapIndex(reflect.ValueOf(key), reflect.Indirect(reflect.ValueOf(newValue.Interface())))
-			}
+		if sliceElementType.Kind() == reflect.Ptr {
+			sliceValue.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(newValue.Interface()))
+		} else {
+			sliceValue.SetMapIndex(reflect.ValueOf(key), reflect.Indirect(reflect.ValueOf(newValue.Interface())))
 		}
 	}
+
 	return nil
 }
 
-// Test if database is ok
+// Ping test if database is ok
 func (session *Session) Ping() error {
 	defer session.resetStatement()
 	if session.IsAutoClose {
@@ -1434,6 +1363,7 @@ func (engine *Engine) tableName(beanOrTableName interface{}) (string, error) {
 	return "", errors.New("bean should be a struct or struct's point")
 }
 
+// IsTableExist if a table is exist
 func (session *Session) IsTableExist(beanOrTableName interface{}) (bool, error) {
 	tableName, err := session.Engine.tableName(beanOrTableName)
 	if err != nil {
@@ -1453,6 +1383,7 @@ func (session *Session) isTableExist(tableName string) (bool, error) {
 	return len(results) > 0, err
 }
 
+// IsTableEmpty if table have any records
 func (session *Session) IsTableEmpty(bean interface{}) (bool, error) {
 	v := rValue(bean)
 	t := v.Type()
@@ -2600,76 +2531,16 @@ func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value,
 			} else if session.Statement.UseCascade {
 				table := session.Engine.autoMapType(*fieldValue)
 				if table != nil {
+					// TODO: current only support 1 primary key
 					if len(table.PrimaryKeys) > 1 {
 						panic("unsupported composited primary key cascade")
 					}
 					var pk = make(core.PK, len(table.PrimaryKeys))
 					rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
-					switch rawValueType.Kind() {
-					case reflect.Int64:
-						x, err := strconv.ParseInt(string(data), 10, 64)
-						if err != nil {
-							return fmt.Errorf("arg %v as int: %s", key, err.Error())
-						}
-						pk[0] = x
-					case reflect.Int:
-						x, err := strconv.ParseInt(string(data), 10, 64)
-						if err != nil {
-							return fmt.Errorf("arg %v as int: %s", key, err.Error())
-						}
-						pk[0] = int(x)
-					case reflect.Int32:
-						x, err := strconv.ParseInt(string(data), 10, 64)
-						if err != nil {
-							return fmt.Errorf("arg %v as int: %s", key, err.Error())
-						}
-						pk[0] = int32(x)
-					case reflect.Int16:
-						x, err := strconv.ParseInt(string(data), 10, 64)
-						if err != nil {
-							return fmt.Errorf("arg %v as int: %s", key, err.Error())
-						}
-						pk[0] = int16(x)
-					case reflect.Int8:
-						x, err := strconv.ParseInt(string(data), 10, 64)
-						if err != nil {
-							return fmt.Errorf("arg %v as int: %s", key, err.Error())
-						}
-						pk[0] = int8(x)
-					case reflect.Uint64:
-						x, err := strconv.ParseUint(string(data), 10, 64)
-						if err != nil {
-							return fmt.Errorf("arg %v as int: %s", key, err.Error())
-						}
-						pk[0] = x
-					case reflect.Uint:
-						x, err := strconv.ParseUint(string(data), 10, 64)
-						if err != nil {
-							return fmt.Errorf("arg %v as int: %s", key, err.Error())
-						}
-						pk[0] = uint(x)
-					case reflect.Uint32:
-						x, err := strconv.ParseUint(string(data), 10, 64)
-						if err != nil {
-							return fmt.Errorf("arg %v as int: %s", key, err.Error())
-						}
-						pk[0] = uint32(x)
-					case reflect.Uint16:
-						x, err := strconv.ParseUint(string(data), 10, 64)
-						if err != nil {
-							return fmt.Errorf("arg %v as int: %s", key, err.Error())
-						}
-						pk[0] = uint16(x)
-					case reflect.Uint8:
-						x, err := strconv.ParseUint(string(data), 10, 64)
-						if err != nil {
-							return fmt.Errorf("arg %v as int: %s", key, err.Error())
-						}
-						pk[0] = uint8(x)
-					case reflect.String:
-						pk[0] = string(data)
-					default:
-						panic("unsupported primary key type cascade")
+					var err error
+					pk[0], err = str2PK(string(data), rawValueType)
+					if err != nil {
+						return err
 					}
 
 					if !isPKZero(pk) {
@@ -2943,82 +2814,11 @@ func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value,
 							panic("unsupported composited primary key cascade")
 						}
 						var pk = make(core.PK, len(table.PrimaryKeys))
+						var err error
 						rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
-						switch rawValueType.Kind() {
-						case reflect.Int64:
-							x, err := strconv.ParseInt(string(data), 10, 64)
-							if err != nil {
-								return fmt.Errorf("arg %v as int: %s", key, err.Error())
-							}
-
-							pk[0] = x
-						case reflect.Int:
-							x, err := strconv.ParseInt(string(data), 10, 64)
-							if err != nil {
-								return fmt.Errorf("arg %v as int: %s", key, err.Error())
-							}
-
-							pk[0] = int(x)
-						case reflect.Int32:
-							x, err := strconv.ParseInt(string(data), 10, 64)
-							if err != nil {
-								return fmt.Errorf("arg %v as int: %s", key, err.Error())
-							}
-
-							pk[0] = int32(x)
-						case reflect.Int16:
-							x, err := strconv.ParseInt(string(data), 10, 64)
-							if err != nil {
-								return fmt.Errorf("arg %v as int: %s", key, err.Error())
-							}
-
-							pk[0] = int16(x)
-						case reflect.Int8:
-							x, err := strconv.ParseInt(string(data), 10, 64)
-							if err != nil {
-								return fmt.Errorf("arg %v as int: %s", key, err.Error())
-							}
-
-							pk[0] = x
-						case reflect.Uint64:
-							x, err := strconv.ParseUint(string(data), 10, 64)
-							if err != nil {
-								return fmt.Errorf("arg %v as int: %s", key, err.Error())
-							}
-
-							pk[0] = x
-						case reflect.Uint:
-							x, err := strconv.ParseUint(string(data), 10, 64)
-							if err != nil {
-								return fmt.Errorf("arg %v as int: %s", key, err.Error())
-							}
-
-							pk[0] = uint(x)
-						case reflect.Uint32:
-							x, err := strconv.ParseUint(string(data), 10, 64)
-							if err != nil {
-								return fmt.Errorf("arg %v as int: %s", key, err.Error())
-							}
-
-							pk[0] = uint32(x)
-						case reflect.Uint16:
-							x, err := strconv.ParseUint(string(data), 10, 64)
-							if err != nil {
-								return fmt.Errorf("arg %v as int: %s", key, err.Error())
-							}
-
-							pk[0] = uint16(x)
-						case reflect.Uint8:
-							x, err := strconv.ParseUint(string(data), 10, 64)
-							if err != nil {
-								return fmt.Errorf("arg %v as int: %s", key, err.Error())
-							}
-
-							pk[0] = uint8(x)
-						case reflect.String:
-							pk[0] = string(data)
-						default:
-							panic("unsupported primary key type cascade")
+						pk[0], err = str2PK(string(data), rawValueType)
+						if err != nil {
+							return err
 						}
 
 						if !isPKZero(pk) {
@@ -3299,8 +3099,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 			return 1, nil
 		}
 
-		v := int64ToInt(id, aiValue.Type().Kind())
-		aiValue.Set(reflect.ValueOf(v))
+		aiValue.Set(int64ToIntValue(id, aiValue.Type()))
 
 		return 1, nil
 	} else if session.Engine.dialect.DBType() == core.POSTGRES && len(table.AutoIncrement) > 0 {
@@ -3345,8 +3144,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 			return 1, nil
 		}
 
-		v := int64ToInt(id, aiValue.Type().Kind())
-		aiValue.Set(reflect.ValueOf(v))
+		aiValue.Set(int64ToIntValue(id, aiValue.Type()))
 
 		return 1, nil
 	} else {
@@ -3388,7 +3186,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
 			return res.RowsAffected()
 		}
 
-		v := int64ToInt(id, aiValue.Type().Kind())
+		v := int64ToInt(id, aiValue.Type())
 		aiValue.Set(reflect.ValueOf(v))
 
 		return res.RowsAffected()

+ 34 - 49
statement.go

@@ -82,7 +82,7 @@ type Statement struct {
 	exprColumns     map[string]exprParam
 }
 
-// init
+// Init reset all the statment's fields
 func (statement *Statement) Init() {
 	statement.RefTable = nil
 	statement.Start = 0
@@ -207,7 +207,7 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{},
 	mustColumnMap map[string]bool, nullableMap map[string]bool,
 	columnMap map[string]bool, update, unscoped bool) ([]string, []interface{}) {
 
-	colNames := make([]string, 0)
+	var colNames = make([]string, 0)
 	var args = make([]interface{}, 0)
 	for _, col := range table.Columns() {
 		if !includeVersion && col.IsVersion {
@@ -667,7 +667,7 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{},
 	return colNames, args
 }
 
-// return current tableName
+// TableName return current tableName
 func (statement *Statement) TableName() string {
 	if statement.AltTableName != "" {
 		return statement.AltTableName
@@ -683,12 +683,7 @@ func (statement *Statement) TableName() string {
 	return ""
 }
 
-var (
-	ptrPkType = reflect.TypeOf(&core.PK{})
-	pkType    = reflect.TypeOf(core.PK{})
-)
-
-// Generate "where id = ? " statment or for composite key "where key1 = ? and key2 = ?"
+// Id generate "where id = ? " statment or for composite key "where key1 = ? and key2 = ?"
 func (statement *Statement) Id(id interface{}) *Statement {
 	idValue := reflect.ValueOf(id)
 	idType := reflect.TypeOf(idValue.Interface())
@@ -697,16 +692,22 @@ func (statement *Statement) Id(id interface{}) *Statement {
 	case ptrPkType:
 		if pkPtr, ok := (id).(*core.PK); ok {
 			statement.IdParam = pkPtr
+			return statement
 		}
 	case pkType:
 		if pk, ok := (id).(core.PK); ok {
 			statement.IdParam = &pk
+			return statement
 		}
-	default:
-		// TODO: treat as int primitve for now, need to handle type check?
-		statement.IdParam = &core.PK{id}
 	}
 
+	switch idType.Kind() {
+	case reflect.String:
+		statement.IdParam = &core.PK{idValue.Convert(reflect.TypeOf("")).Interface()}
+		return statement
+	}
+
+	statement.IdParam = &core.PK{id}
 	return statement
 }
 
@@ -754,7 +755,7 @@ func (statement *Statement) getExpr() map[string]exprParam {
 	return statement.exprColumns
 }
 
-// Generate "Where column IN (?) " statment
+// In generate "Where column IN (?) " statment
 func (statement *Statement) In(column string, args ...interface{}) *Statement {
 	length := len(args)
 	if length == 0 {
@@ -788,7 +789,7 @@ func (statement *Statement) genInSql() (string, []interface{}) {
 	}
 
 	inStrs := make([]string, len(statement.inColumns), len(statement.inColumns))
-	args := make([]interface{}, 0)
+	args := make([]interface{}, 0, len(statement.inColumns))
 	var buf bytes.Buffer
 	var i int
 	for _, params := range statement.inColumns {
@@ -818,19 +819,6 @@ func (statement *Statement) attachInSql() {
 	}
 }
 
-func col2NewCols(columns ...string) []string {
-	newColumns := make([]string, 0)
-	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 (statement *Statement) col2NewColsWithQuote(columns ...string) []string {
 	newColumns := make([]string, 0)
 	for _, col := range columns {
@@ -865,13 +853,13 @@ func (statement *Statement) ForUpdate() *Statement {
 	return statement
 }
 
-// replace select
+// Select replace select
 func (s *Statement) Select(str string) *Statement {
 	s.selectStr = str
 	return s
 }
 
-// Generate "col1, col2" statement
+// Cols generate "col1, col2" statement
 func (statement *Statement) Cols(columns ...string) *Statement {
 	cols := col2NewCols(columns...)
 	for _, nc := range cols {
@@ -885,13 +873,13 @@ func (statement *Statement) Cols(columns ...string) *Statement {
 	return statement
 }
 
-// Update use only: update all columns
+// AllCols update use only: update all columns
 func (statement *Statement) AllCols() *Statement {
 	statement.useAllCols = true
 	return statement
 }
 
-// Update use only: must update columns
+// MustCols update use only: must update columns
 func (statement *Statement) MustCols(columns ...string) *Statement {
 	newColumns := col2NewCols(columns...)
 	for _, nc := range newColumns {
@@ -900,7 +888,7 @@ func (statement *Statement) MustCols(columns ...string) *Statement {
 	return statement
 }
 
-// indicates that use bool fields as update contents and query contiditions
+// UseBool indicates that use bool fields as update contents and query contiditions
 func (statement *Statement) UseBool(columns ...string) *Statement {
 	if len(columns) > 0 {
 		statement.MustCols(columns...)
@@ -910,7 +898,7 @@ func (statement *Statement) UseBool(columns ...string) *Statement {
 	return statement
 }
 
-// do not use the columns
+// Omit do not use the columns
 func (statement *Statement) Omit(columns ...string) {
 	newColumns := col2NewCols(columns...)
 	for _, nc := range newColumns {
@@ -919,7 +907,7 @@ func (statement *Statement) Omit(columns ...string) {
 	statement.OmitStr = statement.Engine.Quote(strings.Join(newColumns, statement.Engine.Quote(", ")))
 }
 
-// Update use only: update columns to null when value is nullable and zero-value
+// Nullable Update use only: update columns to null when value is nullable and zero-value
 func (statement *Statement) Nullable(columns ...string) {
 	newColumns := col2NewCols(columns...)
 	for _, nc := range newColumns {
@@ -927,13 +915,13 @@ func (statement *Statement) Nullable(columns ...string) {
 	}
 }
 
-// Generate LIMIT limit statement
+// Top generate LIMIT limit statement
 func (statement *Statement) Top(limit int) *Statement {
 	statement.Limit(limit)
 	return statement
 }
 
-// Generate LIMIT start, limit statement
+// Limit generate LIMIT start, limit statement
 func (statement *Statement) Limit(limit int, start ...int) *Statement {
 	statement.LimitN = limit
 	if len(start) > 0 {
@@ -942,7 +930,7 @@ func (statement *Statement) Limit(limit int, start ...int) *Statement {
 	return statement
 }
 
-// Generate "Order By order" statement
+// OrderBy generate "Order By order" statement
 func (statement *Statement) OrderBy(order string) *Statement {
 	if len(statement.OrderStr) > 0 {
 		statement.OrderStr += ", "
@@ -951,6 +939,7 @@ func (statement *Statement) OrderBy(order string) *Statement {
 	return statement
 }
 
+// Desc generate `ORDER BY xx DESC`
 func (statement *Statement) Desc(colNames ...string) *Statement {
 	var buf bytes.Buffer
 	fmt.Fprintf(&buf, statement.OrderStr)
@@ -963,7 +952,7 @@ func (statement *Statement) Desc(colNames ...string) *Statement {
 	return statement
 }
 
-// Method Asc provide asc order by query condition, the input parameters are columns.
+// Asc provide asc order by query condition, the input parameters are columns.
 func (statement *Statement) Asc(colNames ...string) *Statement {
 	var buf bytes.Buffer
 	fmt.Fprintf(&buf, statement.OrderStr)
@@ -976,13 +965,13 @@ func (statement *Statement) Asc(colNames ...string) *Statement {
 	return statement
 }
 
-//The join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
-func (statement *Statement) Join(join_operator string, tablename interface{}, condition string, args ...interface{}) *Statement {
+// Join The joinOP should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
+func (statement *Statement) Join(joinOP string, tablename interface{}, condition string, args ...interface{}) *Statement {
 	var buf bytes.Buffer
 	if len(statement.JoinStr) > 0 {
-		fmt.Fprintf(&buf, "%v %v JOIN ", statement.JoinStr, join_operator)
+		fmt.Fprintf(&buf, "%v %v JOIN ", statement.JoinStr, joinOP)
 	} else {
-		fmt.Fprintf(&buf, "%v JOIN ", join_operator)
+		fmt.Fprintf(&buf, "%v JOIN ", joinOP)
 	}
 
 	switch tablename.(type) {
@@ -1024,19 +1013,19 @@ func (statement *Statement) Join(join_operator string, tablename interface{}, co
 	return statement
 }
 
-// Generate "Group By keys" statement
+// GroupBy generate "Group By keys" statement
 func (statement *Statement) GroupBy(keys string) *Statement {
 	statement.GroupByStr = keys
 	return statement
 }
 
-// Generate "Having conditions" statement
+// Having generate "Having conditions" statement
 func (statement *Statement) Having(conditions string) *Statement {
 	statement.HavingStr = fmt.Sprintf("HAVING %v", conditions)
 	return statement
 }
 
-// Always disable struct tag "deleted"
+// Unscoped always disable struct tag "deleted"
 func (statement *Statement) Unscoped() *Statement {
 	statement.unscoped = true
 	return statement
@@ -1085,10 +1074,6 @@ func (statement *Statement) genCreateTableSQL() string {
 		statement.StoreEngine, statement.Charset)
 }
 
-func indexName(tableName, idxName string) string {
-	return fmt.Sprintf("IDX_%v_%v", tableName, idxName)
-}
-
 func (s *Statement) genIndexSQL() []string {
 	var sqls []string = make([]string, 0)
 	tbName := s.TableName()

+ 12 - 0
types.go

@@ -0,0 +1,12 @@
+package xorm
+
+import (
+    "reflect"
+
+    "github.com/go-xorm/core"
+)
+
+var (
+	ptrPkType = reflect.TypeOf(&core.PK{})
+	pkType    = reflect.TypeOf(core.PK{})
+)

+ 1 - 1
xorm.go

@@ -16,7 +16,7 @@ import (
 )
 
 const (
-	Version string = "0.5.3.0331"
+	Version string = "0.5.3.0407"
 )
 
 func regDrvsNDialects() bool {