|
@@ -1,7 +1,10 @@
|
|
|
package orm
|
|
|
|
|
|
import (
|
|
|
+ "fmt"
|
|
|
+ "math"
|
|
|
"reflect"
|
|
|
+ "strconv"
|
|
|
"sync"
|
|
|
|
|
|
"github.com/go-openapi/inflect"
|
|
@@ -17,17 +20,111 @@ type table struct {
|
|
|
mapped bool
|
|
|
}
|
|
|
|
|
|
+func (t *table) Make() MappableInterface {
|
|
|
+ return reflect.New(t.getType()).Interface().(MappableInterface)
|
|
|
+}
|
|
|
+
|
|
|
+func (t *table) CallMethod(i MappableInterface, n string, args ...interface{}) ([]interface{}, error) {
|
|
|
+ var ret []interface{}
|
|
|
+ if t.getValue(true).MethodByName(n).IsValid() {
|
|
|
+ fn := reflect.ValueOf(i).MethodByName(n)
|
|
|
+ fnt := fn.Type()
|
|
|
+ in := []reflect.Value{}
|
|
|
+
|
|
|
+ if fnt.IsVariadic() && len(args) < (fnt.NumIn()-1) {
|
|
|
+ return ret, fmt.Errorf("To few arguments to «%s». Got «%d», expected «%d»", n, len(args), fnt.NumIn()-1)
|
|
|
+ } else if !fnt.IsVariadic() && len(args) != fnt.NumIn() {
|
|
|
+ return ret, fmt.Errorf("To few arguments to «%s». Got «%d», expected «%d»", n, len(args), fnt.NumIn()-1)
|
|
|
+ }
|
|
|
+
|
|
|
+ for x := 0; x < len(args); x++ {
|
|
|
+
|
|
|
+ var inType reflect.Type
|
|
|
+ if fnt.IsVariadic() && x >= fnt.NumIn()-1 {
|
|
|
+ inType = fnt.In(fnt.NumIn() - 1).Elem()
|
|
|
+ } else {
|
|
|
+ inType = fnt.In(x)
|
|
|
+ }
|
|
|
+
|
|
|
+ argv := reflect.ValueOf(args[x])
|
|
|
+
|
|
|
+ if !argv.IsValid() || !argv.Type().ConvertibleTo(inType) {
|
|
|
+
|
|
|
+ switch inType.Kind() {
|
|
|
+ case
|
|
|
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
|
|
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
|
+ var val uint64 = 0
|
|
|
+ argx := args[x].([]uint8)
|
|
|
+ for xi := len(argx) - 1; xi >= 0; xi-- {
|
|
|
+ val += uint64(math.Pow(10, float64(len(argx)-xi-1))) * uint64(argx[xi]-'0')
|
|
|
+ }
|
|
|
+ args[x] = val
|
|
|
+ return t.CallMethod(i, n, args...)
|
|
|
+ case reflect.Float32, reflect.Float64:
|
|
|
+ if val, err := strconv.ParseFloat(string(args[x].([]byte)), 64); err == nil {
|
|
|
+ args[x] = val
|
|
|
+ return t.CallMethod(i, n, args...)
|
|
|
+ }
|
|
|
+ case reflect.Complex64, reflect.Complex128:
|
|
|
+ // Not implemented
|
|
|
+ return ret, fmt.Errorf("Complex not implemented")
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret, fmt.Errorf("Invalid argument to «%s». Got %s, expected %s", n, argv.String(), inType.String())
|
|
|
+ }
|
|
|
+
|
|
|
+ in = append(in, argv.Convert(inType))
|
|
|
+ }
|
|
|
+
|
|
|
+ var err error = nil
|
|
|
+ out := fn.Call(in)[0:fnt.NumOut()]
|
|
|
+
|
|
|
+ for _, val := range out {
|
|
|
+ switch val.Kind() {
|
|
|
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
|
+ ret = append(ret, val.Uint())
|
|
|
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
|
+ ret = append(ret, val.Int())
|
|
|
+ case reflect.Float32, reflect.Float64:
|
|
|
+ ret = append(ret, val.Float())
|
|
|
+ case reflect.String:
|
|
|
+ ret = append(ret, val.String())
|
|
|
+ case reflect.Interface:
|
|
|
+ if !val.IsNil() && val.CanInterface() && val.Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
|
|
+ err = val.Interface().(error)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret, err
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret, fmt.Errorf("Invalid method «%s» on «%s»", n, t.getType())
|
|
|
+}
|
|
|
+
|
|
|
// getPrimaryKey tries to find primary key
|
|
|
func (t *table) getPrimaryKey() *column {
|
|
|
- var pkey *column
|
|
|
+ var pkey *column = nil
|
|
|
+
|
|
|
if c := t.hasTaggedColumn("primary"); c != nil {
|
|
|
pkey = c
|
|
|
} else if c := t.hasColumn("Id"); c != nil {
|
|
|
pkey = c
|
|
|
}
|
|
|
+
|
|
|
return pkey
|
|
|
}
|
|
|
|
|
|
+func (t *table) getRelations() map[relType][]relation {
|
|
|
+ return t.rels.rmap
|
|
|
+}
|
|
|
+
|
|
|
+func (t *table) getColumns() columns {
|
|
|
+ return t.cols
|
|
|
+}
|
|
|
+
|
|
|
// hasTaggetColumn checks for a collumn tagget as
|
|
|
func (t *table) hasTaggedColumn(ct string) *column {
|
|
|
for _, col := range t.cols {
|
|
@@ -66,7 +163,7 @@ func (t *table) addField(f field, cbCh chan<- mapperCallback) {
|
|
|
|
|
|
fn: func(self *table) {
|
|
|
// Get Primary Key
|
|
|
- pkey := t.getPrimaryKey()
|
|
|
+ pkey := self.getPrimaryKey()
|
|
|
|
|
|
// Or at least try to
|
|
|
if pkey == nil {
|
|
@@ -89,6 +186,12 @@ func (t *table) addField(f field, cbCh chan<- mapperCallback) {
|
|
|
cn = tag
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ if self.getStructName() == "PlatformCalendar" {
|
|
|
+ fmt.Println(self.getStructName(), f.getFieldType(), cn)
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
// Check if it contains reference itself
|
|
|
if c := self.hasColumn(cn); c != nil {
|
|
|
// Make a call to load related table into scope;
|
|
@@ -169,6 +272,8 @@ func (t *table) addField(f field, cbCh chan<- mapperCallback) {
|
|
|
t.cols = append(t.cols, column{
|
|
|
f, dbf,
|
|
|
})
|
|
|
+ default:
|
|
|
+ fmt.Println(t.getStructName(), "not supporting", f)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -179,8 +284,11 @@ func (t *table) getType() reflect.Type {
|
|
|
}
|
|
|
|
|
|
// getValue returns the reflect.Value of the «table»
|
|
|
-func (t *table) getValue() reflect.Value {
|
|
|
- return t.rv
|
|
|
+func (t *table) getValue(ptr ...bool) reflect.Value {
|
|
|
+ if len(ptr) > 0 && ptr[0] {
|
|
|
+ return t.rv
|
|
|
+ }
|
|
|
+ return t.rv.Elem()
|
|
|
}
|
|
|
|
|
|
// isMapped returns true when columns is mapped
|
|
@@ -218,9 +326,24 @@ func (t *table) getStructName() string {
|
|
|
|
|
|
// getName returns the mapped table name
|
|
|
// as identified in the database
|
|
|
-func (t *table) getName() string {
|
|
|
+func (t *table) getName(q bool) string {
|
|
|
+ if q {
|
|
|
+ return SqlFlavor.Quote(t.getName(false))
|
|
|
+ }
|
|
|
return t.tFn(t.getType().Name())
|
|
|
}
|
|
|
|
|
|
+func (t *table) getNameAs(q bool) string {
|
|
|
+ return t.getName(q) + " AS " + t.getAlias(q)
|
|
|
+}
|
|
|
+
|
|
|
+func (t *table) getAlias(q bool) string {
|
|
|
+ if q {
|
|
|
+ return SqlFlavor.Quote(t.getAlias(false))
|
|
|
+ }
|
|
|
+
|
|
|
+ return t.getStructName()
|
|
|
+}
|
|
|
+
|
|
|
// tables is simply a collection of tables
|
|
|
type tables map[string]*table
|