forked from go-rel/rel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cursor.go
111 lines (89 loc) · 1.84 KB
/
cursor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package rel
import (
"database/sql"
"reflect"
)
// Cursor is interface to work with database result (used by adapter).
type Cursor interface {
Close() error
Fields() ([]string, error)
Next() bool
Scan(...interface{}) error
NopScanner() interface{} // TODO: conflict with manual scanners interface
}
func scanOne(cur Cursor, doc *Document) error {
defer cur.Close()
fields, err := cur.Fields()
if err != nil {
return err
}
if !cur.Next() {
return NotFoundError{}
}
var (
scanners = doc.Scanners(fields)
)
return cur.Scan(scanners...)
}
func scanAll(cur Cursor, col *Collection) error {
defer cur.Close()
fields, err := cur.Fields()
if err != nil {
return err
}
for cur.Next() {
var (
doc = col.Add()
scanners = doc.Scanners(fields)
)
if err := cur.Scan(scanners...); err != nil {
return err
}
}
return nil
}
func scanMulti(cur Cursor, keyField string, keyType reflect.Type, cols map[interface{}][]slice) error {
defer cur.Close()
fields, err := cur.Fields()
if err != nil {
return err
}
var (
found = false
keyValue = reflect.New(keyType)
keyScanners = make([]interface{}, len(fields))
)
for i, field := range fields {
if keyField == field {
found = true
keyScanners[i] = keyValue.Interface()
} else {
// need to create distinct copies
// otherwise next scan result will be corrupted
keyScanners[i] = &sql.RawBytes{}
}
}
if !found {
panic("rel: primary key row does not exists")
}
// scan the result
for cur.Next() {
// scan key
if err := cur.Scan(keyScanners...); err != nil {
return err
}
var (
key = reflect.Indirect(keyValue).Interface()
)
for _, col := range cols[key] {
var (
doc = col.Add()
scanners = doc.Scanners(fields)
)
if err := cur.Scan(scanners...); err != nil {
return err
}
}
}
return nil
}