-
Notifications
You must be signed in to change notification settings - Fork 34
/
privates.go
148 lines (132 loc) · 3.15 KB
/
privates.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package simdb
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"strings"
)
// addError adds error to error list
func (d *Driver) addError(err error) *Driver {
d.errors = append(d.errors, fmt.Errorf("simd: %v", err))
return d
}
func (d *Driver) openDB(entity interface{}) ([]interface{}, error) {
entityName, err := d.getEntityName()
if err != nil {
return nil, err
}
file := filepath.Join(d.dir, entityName)
f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE, 0666)
if err != nil {
return nil, err
}
defer f.Close()
b, readErr := ioutil.ReadFile(file)
if readErr != nil {
return nil, readErr
}
array := make([]interface{}, 0)
json.Unmarshal(b, &array)
return array, nil
}
func (d *Driver) isDBOpened() bool {
if !d.isOpened {
err := errors.New("should call Open() before doing any query on json file")
d.addError(err)
}
return d.isOpened
}
func (d *Driver) getEntityName() (string, error) {
typeName := strings.Split(reflect.TypeOf(d.entityDealingWith).String(), ".")
if len(typeName) <= 0 {
return "", fmt.Errorf("unable to infer the type of the entity passed")
}
return typeName[len(typeName)-1], nil
}
func (d *Driver) readAppend(entity interface{}) (err error) {
result, err := d.openDB(entity)
if err != nil {
return
}
mergedArray, err := mergeToExisting(result, entity)
if err != nil {
return
}
err = d.writeAll(mergedArray)
return
}
func (d *Driver) writeAll(entities []interface{}) (err error) {
entityName, err := d.getEntityName()
file := filepath.Join(d.dir, entityName)
f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE, 0666)
if err != nil {
return
}
defer f.Close()
b, err := json.MarshalIndent(entities, "", "\t")
if err != nil {
return
}
f.Truncate(0)
f.Seek(0, 0)
f.Write(b)
f.Sync()
return
}
// findInArray traverses through a list and returns the value list.
// This helps to process Where/OrWhere queries
func (d *Driver) findInArray(aa []interface{}) []interface{} {
result := make([]interface{}, 0)
for _, a := range aa {
if m, ok := a.(map[string]interface{}); ok {
findResult, err := d.findInMap(m)
if err == nil {
result = append(result, findResult...)
} else {
d.addError(err)
}
}
}
return result
}
// findInMap traverses through a map and returns the matched value list.
// This helps to process Where/OrWhere queries
func (d *Driver) findInMap(vm map[string]interface{}) ([]interface{}, error) {
result := make([]interface{}, 0)
orPassed := false
for _, qList := range d.queries {
andPassed := true
for _, q := range qList {
cf, ok := d.queryMap[q.operator]
if !ok {
return nil, fmt.Errorf("invalid operator %s " + q.operator)
}
nv, errnv := getNestedValue(vm, q.key)
if errnv != nil {
return nil, errnv
} else {
qb, err := cf(nv, q.value)
if err != nil {
return nil, err
}
andPassed = andPassed && qb
}
}
orPassed = orPassed || andPassed
}
if orPassed {
result = append(result, vm)
}
return result, nil
}
// processQuery makes the result
func (d *Driver) processQuery() *Driver {
if aa, ok := d.originalJSON.([]interface{}); ok {
d.jsonContent = d.findInArray(aa)
}
return d
}