table.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. package orm
  2. import (
  3. "fmt"
  4. "math"
  5. "reflect"
  6. "strconv"
  7. "strings"
  8. "sync"
  9. )
  10. type table struct {
  11. rt reflect.Type
  12. rv reflect.Value
  13. l *sync.RWMutex
  14. tFn, cFn MapperFn
  15. cols columns
  16. rels relations
  17. mapped bool
  18. }
  19. func (t *table) Make() MappableInterface {
  20. return reflect.New(t.getType()).Interface().(MappableInterface)
  21. }
  22. func (t *table) CallMethod(i MappableInterface, n string, args ...interface{}) (ret []interface{}, err error) {
  23. if t.getValue(true).MethodByName(n).IsValid() {
  24. fn := reflect.ValueOf(i).MethodByName(n)
  25. fnt := fn.Type()
  26. in := []reflect.Value{}
  27. if fnt.IsVariadic() && len(args) < (fnt.NumIn()-1) {
  28. return ret, fmt.Errorf("To few arguments to «%s». Got «%d», expected «%d»", n, len(args), fnt.NumIn()-1)
  29. } else if !fnt.IsVariadic() && len(args) != fnt.NumIn() {
  30. return ret, fmt.Errorf("To few arguments to «%s». Got «%d», expected «%d»", n, len(args), fnt.NumIn()-1)
  31. }
  32. for x := 0; x < len(args); x++ {
  33. var inType reflect.Type
  34. if fnt.IsVariadic() && x >= fnt.NumIn()-1 {
  35. inType = fnt.In(fnt.NumIn() - 1).Elem()
  36. } else {
  37. inType = fnt.In(x)
  38. }
  39. argv := reflect.ValueOf(args[x])
  40. if !argv.IsValid() || !argv.Type().ConvertibleTo(inType) {
  41. switch inType.Kind() {
  42. case
  43. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
  44. reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  45. var val uint64 = 0
  46. argx := args[x].([]uint8)
  47. for xi := len(argx) - 1; xi >= 0; xi-- {
  48. val += uint64(math.Pow(10, float64(len(argx)-xi-1))) * uint64(argx[xi]-'0')
  49. }
  50. args[x] = val
  51. return t.CallMethod(i, n, args...)
  52. case reflect.Float32, reflect.Float64:
  53. if val, err := strconv.ParseFloat(string(args[x].([]byte)), 64); err == nil {
  54. args[x] = val
  55. return t.CallMethod(i, n, args...)
  56. }
  57. case reflect.Complex64, reflect.Complex128:
  58. // Not implemented
  59. return ret, fmt.Errorf("Complex not implemented")
  60. }
  61. return ret, fmt.Errorf("Invalid argument to «%s». Got %s, expected %s", n, argv.String(), inType.String())
  62. }
  63. in = append(in, argv.Convert(inType))
  64. }
  65. var out []reflect.Value
  66. defer func() {
  67. if r := recover(); r != nil {
  68. fmt.Println("Recovered: ", r)
  69. err = fmt.Errorf("Recovered: %v", r)
  70. }
  71. }()
  72. out = fn.Call(in)[0:fnt.NumOut()]
  73. if strings.HasPrefix(n, "Get") {
  74. for _, val := range out {
  75. switch val.Kind() {
  76. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  77. ret = append(ret, val.Uint())
  78. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  79. ret = append(ret, val.Int())
  80. case reflect.Float32, reflect.Float64:
  81. ret = append(ret, val.Float())
  82. case reflect.String:
  83. ret = append(ret, val.String())
  84. case reflect.Interface:
  85. if !val.IsNil() && val.CanInterface() && val.Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
  86. err = val.Interface().(error)
  87. }
  88. case reflect.Struct, reflect.Ptr:
  89. if val.CanInterface() && !val.IsNil() {
  90. ret = append(ret, val.Interface())
  91. } else if val.IsNil() {
  92. ret = append(ret, nil)
  93. }
  94. }
  95. }
  96. }
  97. return ret, err
  98. }
  99. return ret, fmt.Errorf("Invalid method «%s» on «%s»", n, t.getType())
  100. }
  101. // getPrimaryKey tries to find primary key
  102. func (t *table) getPrimaryKey() *column {
  103. var pkey *column = nil
  104. if c := t.hasTaggedColumn("primary"); c != nil {
  105. pkey = c
  106. } else if c := t.hasColumn("Id"); c != nil {
  107. pkey = c
  108. }
  109. return pkey
  110. }
  111. func (t *table) getRelations() map[relType][]relation {
  112. return t.rels.rmap
  113. }
  114. func (t *table) getColumns() columns {
  115. return t.cols
  116. }
  117. // hasTaggetColumn checks for a collumn tagget as
  118. func (t *table) hasTaggedColumn(ct string) *column {
  119. for _, col := range t.cols {
  120. if col.hasTag(ct) {
  121. return &col
  122. }
  123. }
  124. return nil
  125. }
  126. // hasColumn checks for a column by name
  127. func (t *table) hasColumn(c string) *column {
  128. for _, col := range t.cols {
  129. if col.ref == t.cFn(c) {
  130. return &col
  131. }
  132. }
  133. return nil
  134. }
  135. // addField from struct; both «relations» and «columns»
  136. // Communicates over a channel, to do relation mapping
  137. func (t *table) addField(f field, cbCh chan<- mapperCallback) {
  138. if f.hasTags("omit", "-") {
  139. return // Skip "omitted" and "dashed" fields
  140. }
  141. switch f.getType() {
  142. case Relation:
  143. // Make callback to itself, relations should be mapped after columns
  144. cbCh <- mapperCallback{
  145. from: t.getStructName(),
  146. to: t.getStructName(),
  147. fn: func(self *table) {
  148. // Get Primary Key
  149. pkey := self.getPrimaryKey()
  150. // Or at least try to
  151. if pkey == nil {
  152. return
  153. }
  154. // Predict related table name
  155. rtbl := f.getFieldType()
  156. // And check for tag
  157. if tag, ok := f.getTag("table"); ok {
  158. rtbl = tag
  159. }
  160. // Predict column name
  161. cn := f.getFieldName() + "Id"
  162. // And check for tag
  163. if tag, ok := f.getTag("fkey"); ok {
  164. cn = tag
  165. }
  166. /*
  167. if self.getStructName() == "PlatformCalendar" {
  168. fmt.Println(self.getStructName(), f.getFieldType(), cn)
  169. }
  170. */
  171. // Check if it contains reference itself
  172. if c := self.hasColumn(cn); c != nil {
  173. // Make a call to load related table into scope;
  174. // we need its addr and must be loaded from mapper
  175. cbCh <- mapperCallback{
  176. from: self.getStructName(),
  177. to: rtbl,
  178. fn: func(tbl *table) {
  179. key := tbl.getPrimaryKey()
  180. switch f.MakeType().Kind() {
  181. case reflect.Map, reflect.Slice:
  182. self.rels.addRelation(belongsTo, relation{tbl, f, *c, *key})
  183. default:
  184. self.rels.addRelation(belongsTo, relation{tbl, f, *key, *c})
  185. }
  186. },
  187. }
  188. } else {
  189. // Or predict column name in related table
  190. cn = self.getStructName() + "Id"
  191. // Check for reference tag
  192. if tag, ok := f.getTag("ref"); ok {
  193. cn = tag
  194. }
  195. // Make a callback to the related table to check for relationg
  196. cbCh <- mapperCallback{
  197. from: self.getStructName(),
  198. to: rtbl,
  199. fn: func(tbl *table) {
  200. // Check for relation on column mane
  201. if c := tbl.hasColumn(cn); c != nil {
  202. has := hasOne
  203. switch f.MakeType().Kind() {
  204. case reflect.Map, reflect.Slice:
  205. has = hasMany
  206. }
  207. self.rels.addRelation(has, relation{tbl, f, *c, *pkey})
  208. }
  209. },
  210. }
  211. }
  212. return
  213. },
  214. }
  215. default: // Add column
  216. switch f.getKind() {
  217. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  218. fallthrough // Support all Uint types
  219. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  220. fallthrough // Support all Int types
  221. case reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
  222. fallthrough // Support all Float and Complex types
  223. case reflect.String, reflect.Bool, reflect.Struct:
  224. // Support string and boolean
  225. // Map column name
  226. dbf := t.cFn(f.getFieldName())
  227. // override with tagging
  228. if tag, ok := f.getTag("field"); ok {
  229. dbf = t.cFn(tag)
  230. }
  231. t.cols = append(t.cols, column{
  232. f, dbf,
  233. })
  234. case reflect.Ptr:
  235. f.t = f.t.Elem()
  236. f.v = f.v.Elem()
  237. t.addField(f, cbCh)
  238. default:
  239. fmt.Println(t.getStructName(), "not supporting", f)
  240. }
  241. }
  242. }
  243. // getType returns the reflect.Type of the «table»
  244. func (t *table) getType() reflect.Type {
  245. return t.rt
  246. }
  247. // getValue returns the reflect.Value of the «table»
  248. func (t *table) getValue(ptr ...bool) reflect.Value {
  249. if len(ptr) > 0 && ptr[0] {
  250. return t.rv
  251. }
  252. return t.rv.Elem()
  253. }
  254. // isMapped returns true when columns is mapped
  255. // Not relations! They will be mapped in separate routines
  256. func (t *table) isMapped() bool {
  257. return t.mapped
  258. }
  259. // Lock read lock
  260. func (t *table) Lock() *table {
  261. t.l.RLock()
  262. return t
  263. }
  264. // Unlock read lock
  265. func (t *table) Unlock() {
  266. t.l.RUnlock()
  267. }
  268. // lock write lock
  269. func (t *table) lock() *table {
  270. t.l.Lock()
  271. return t
  272. }
  273. // unlock write lock
  274. func (t *table) unlock() {
  275. t.l.Unlock()
  276. }
  277. // getStructName returns the name of the struct
  278. func (t *table) getStructName() string {
  279. return t.getType().Name()
  280. }
  281. // getName returns the mapped table name
  282. // as identified in the database
  283. func (t *table) getName(q bool) string {
  284. if q {
  285. return SqlFlavor.Quote(t.getName(false))
  286. }
  287. return t.tFn(t.getType().Name())
  288. }
  289. func (t *table) getNameAs(q bool) string {
  290. return t.getName(q) + " AS " + t.getAlias(q)
  291. }
  292. func (t *table) getAlias(q bool) string {
  293. if q {
  294. return SqlFlavor.Quote(t.getAlias(false))
  295. }
  296. return t.getStructName()
  297. }
  298. // tables is simply a collection of tables
  299. type tables map[string]*table