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 ( import (
"database/sql" "database/sql"
//"fmt" "fmt"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
@ -154,7 +154,7 @@ func (engine *Engine) MapType(t reflect.Type) *Table {
if ormTagStr != "" { if ormTagStr != "" {
col = Column{FieldName: t.Field(i).Name, Nullable: true, IsPrimaryKey: false, col = Column{FieldName: t.Field(i).Name, Nullable: true, IsPrimaryKey: false,
IsAutoIncrement: false} IsAutoIncrement: false, MapType: TWOSIDES}
ormTagStr = strings.ToLower(ormTagStr) ormTagStr = strings.ToLower(ormTagStr)
tags := strings.Split(ormTagStr, " ") tags := strings.Split(ormTagStr, " ")
// TODO: // TODO:
@ -162,9 +162,22 @@ func (engine *Engine) MapType(t reflect.Type) *Table {
if tags[0] == "-" { if tags[0] == "-" {
continue 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 { for j, key := range tags {
k := strings.ToLower(key) k := strings.ToLower(key)
switch { switch {
case k == "<-":
col.MapType = ONLYFROMDB
case k == "->":
col.MapType = ONLYTODB
case k == "pk": case k == "pk":
col.IsPrimaryKey = true col.IsPrimaryKey = true
col.Nullable = false col.Nullable = false
@ -230,7 +243,7 @@ func (engine *Engine) MapType(t reflect.Type) *Table {
} else { } else {
sqlType := Type2SQLType(fieldType) sqlType := Type2SQLType(fieldType)
col = Column{engine.Mapper.Obj2Table(t.Field(i).Name), t.Field(i).Name, sqlType, 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" { if col.Name == "id" {
col.IsPrimaryKey = true 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)] table := session.Engine.Tables[Type(obj)]
for key, data := range objMap { for key, data := range objMap {
structField := dataStruct.FieldByName(table.Columns[key].FieldName) fieldName := table.Columns[key].FieldName
if !structField.CanSet() { 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 continue
} }
@ -618,6 +631,9 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
if col.IsAutoIncrement && fieldValue.Int() == 0 { if col.IsAutoIncrement && fieldValue.Int() == 0 {
continue continue
} }
if col.MapType == ONLYFROMDB {
continue
}
if table, ok := session.Engine.Tables[fieldValue.Type()]; ok { if table, ok := session.Engine.Tables[fieldValue.Type()]; ok {
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName) pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName)
fmt.Println(pkField.Interface()) fmt.Println(pkField.Interface())
@ -636,6 +652,9 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
if col.IsAutoIncrement && fieldValue.Int() == 0 { if col.IsAutoIncrement && fieldValue.Int() == 0 {
continue continue
} }
if col.MapType == ONLYFROMDB {
continue
}
if table, ok := session.Engine.Tables[fieldValue.Type()]; ok { if table, ok := session.Engine.Tables[fieldValue.Type()]; ok {
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName) pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName)
args = append(args, pkField.Interface()) args = append(args, pkField.Interface())
@ -681,6 +700,9 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
if col.IsAutoIncrement && fieldValue.Int() == 0 { if col.IsAutoIncrement && fieldValue.Int() == 0 {
continue continue
} }
if col.MapType == ONLYFROMDB {
continue
}
if fieldTable, ok := session.Engine.Tables[fieldValue.Type()]; ok { if fieldTable, ok := session.Engine.Tables[fieldValue.Type()]; ok {
if fieldTable.PrimaryKey != "" { if fieldTable.PrimaryKey != "" {
pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumn().FieldName) pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumn().FieldName)

View File

@ -202,7 +202,9 @@ func (statement *Statement) selectColumnStr() string {
table := statement.RefTable table := statement.RefTable
colNames := make([]string, 0) colNames := make([]string, 0)
for _, col := range table.Columns { 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, ", ") return strings.Join(colNames, ", ")
} }

View File

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