mapping now supported single mapping and struct derive

This commit is contained in:
Lunny Xiao 2013-06-24 12:08:58 +08:00
parent d82b879453
commit 5e90d61fa8
6 changed files with 169 additions and 6 deletions

View File

@ -2,7 +2,7 @@ package xorm
import (
"database/sql"
//"fmt"
"fmt"
"reflect"
"strconv"
"strings"
@ -154,7 +154,7 @@ func (engine *Engine) MapType(t reflect.Type) *Table {
if ormTagStr != "" {
col = Column{FieldName: t.Field(i).Name, Nullable: true, IsPrimaryKey: false,
IsAutoIncrement: false}
IsAutoIncrement: false, MapType: TWOSIDES}
ormTagStr = strings.ToLower(ormTagStr)
tags := strings.Split(ormTagStr, " ")
// TODO:
@ -162,9 +162,22 @@ func (engine *Engine) MapType(t reflect.Type) *Table {
if tags[0] == "-" {
continue
}
if (tags[0] == "extends") &&
(fieldType.Kind() == reflect.Struct) &&
t.Field(i).Anonymous {
parentTable := engine.MapType(fieldType)
for name, col := range parentTable.Columns {
col.FieldName = fmt.Sprintf("%v.%v", fieldType.Name(), col.FieldName)
table.Columns[name] = col
}
}
for j, key := range tags {
k := strings.ToLower(key)
switch {
case k == "<-":
col.MapType = ONLYFROMDB
case k == "->":
col.MapType = ONLYTODB
case k == "pk":
col.IsPrimaryKey = true
col.Nullable = false
@ -230,7 +243,7 @@ func (engine *Engine) MapType(t reflect.Type) *Table {
} else {
sqlType := Type2SQLType(fieldType)
col = Column{engine.Mapper.Obj2Table(t.Field(i).Name), t.Field(i).Name, sqlType,
sqlType.DefaultLength, sqlType.DefaultLength2, true, "", false, false, false}
sqlType.DefaultLength, sqlType.DefaultLength2, true, "", false, false, false, TWOSIDES}
if col.Name == "id" {
col.IsPrimaryKey = true

65
examples/derive.go Normal file
View File

@ -0,0 +1,65 @@
package main
import (
"fmt"
_ "github.com/mattn/go-sqlite3"
"os"
. "xorm"
)
type User struct {
Id int64
Name string
}
type LoginInfo struct {
Id int64
IP string
UserId int64
}
type LoginInfo1 struct {
LoginInfo `xorm:"extends"`
UserName string
}
func main() {
f := "derive.db"
os.Remove(f)
Orm, err := NewEngine("sqlite3", f)
if err != nil {
fmt.Println(err)
return
}
Orm.ShowSQL = true
err = Orm.CreateTables(&User{}, &LoginInfo{})
if err != nil {
fmt.Println(err)
return
}
_, err = Orm.Insert(&User{1, "xlw"}, &LoginInfo{1, "127.0.0.1", 1})
if err != nil {
fmt.Println(err)
return
}
info := LoginInfo{}
_, err = Orm.Id(1).Get(&info)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(info)
infos := make([]LoginInfo1, 0)
err = Orm.Sql(`select *, (select name from user where id = login_info.user_id) as user_name from
login_info limit 10`).Find(&infos)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(infos)
}

54
examples/singlemapping.go Normal file
View File

@ -0,0 +1,54 @@
package main
import (
"fmt"
_ "github.com/mattn/go-sqlite3"
"os"
. "xorm"
)
type User struct {
Id int64
Name string
}
type LoginInfo struct {
Id int64
IP string
UserId int64
// timestamp should be updated by database, so only allow get from db
TimeStamp string `xorm:"<-"`
// assume
Nonuse int `xorm:"->"`
}
func main() {
f := "singleMapping.db"
os.Remove(f)
Orm, err := NewEngine("sqlite3", f)
if err != nil {
fmt.Println(err)
return
}
Orm.ShowSQL = true
err = Orm.CreateTables(&User{}, &LoginInfo{})
if err != nil {
fmt.Println(err)
return
}
_, err = Orm.Insert(&User{1, "xlw"}, &LoginInfo{1, "127.0.0.1", 1, "", 23})
if err != nil {
fmt.Println(err)
return
}
info := LoginInfo{}
_, err = Orm.Id(1).Get(&info)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(info)
}

View File

@ -157,8 +157,21 @@ func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]b
table := session.Engine.Tables[Type(obj)]
for key, data := range objMap {
structField := dataStruct.FieldByName(table.Columns[key].FieldName)
if !structField.CanSet() {
fieldName := table.Columns[key].FieldName
fieldPath := strings.Split(fieldName, ".")
var structField reflect.Value
if len(fieldPath) > 2 {
fmt.Printf("xorm: Warning! Unsupported mutliderive %v\n", fieldName)
continue
} else if len(fieldPath) == 2 {
parentField := dataStruct.FieldByName(fieldPath[0])
if parentField.IsValid() {
structField = parentField.FieldByName(fieldPath[1])
}
} else {
structField = dataStruct.FieldByName(fieldName)
}
if !structField.IsValid() || !structField.CanSet() {
continue
}
@ -618,6 +631,9 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
if col.IsAutoIncrement && fieldValue.Int() == 0 {
continue
}
if col.MapType == ONLYFROMDB {
continue
}
if table, ok := session.Engine.Tables[fieldValue.Type()]; ok {
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName)
fmt.Println(pkField.Interface())
@ -636,6 +652,9 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
if col.IsAutoIncrement && fieldValue.Int() == 0 {
continue
}
if col.MapType == ONLYFROMDB {
continue
}
if table, ok := session.Engine.Tables[fieldValue.Type()]; ok {
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName)
args = append(args, pkField.Interface())
@ -681,6 +700,9 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
if col.IsAutoIncrement && fieldValue.Int() == 0 {
continue
}
if col.MapType == ONLYFROMDB {
continue
}
if fieldTable, ok := session.Engine.Tables[fieldValue.Type()]; ok {
if fieldTable.PrimaryKey != "" {
pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumn().FieldName)

View File

@ -202,7 +202,9 @@ func (statement *Statement) selectColumnStr() string {
table := statement.RefTable
colNames := make([]string, 0)
for _, col := range table.Columns {
colNames = append(colNames, statement.TableName()+"."+col.Name)
if col.MapType != ONLYTODB {
colNames = append(colNames, statement.TableName()+"."+col.Name)
}
}
return strings.Join(colNames, ", ")
}

View File

@ -64,6 +64,12 @@ func Type2SQLType(t reflect.Type) (st SQLType) {
return
}
const (
TWOSIDES = iota + 1
ONLYTODB
ONLYFROMDB
)
type Column struct {
Name string
FieldName string
@ -75,6 +81,7 @@ type Column struct {
IsUnique bool
IsPrimaryKey bool
IsAutoIncrement bool
MapType int
}
type Table struct {