-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsorting.go
313 lines (302 loc) · 7.97 KB
/
sorting.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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
package schema
import (
"github.com/hewiefreeman/GopherDB/helpers"
"strings"
"time"
)
var ()
// Sorting Arrays for query filters
func sort(filter *Filter, ary []interface{}, by interface{}, asc bool) int {
itemType := filter.schemaItems[len(filter.schemaItems)-1].iType.(ArrayItem).dataType
switch itemType.typeName {
case ItemTypeInt8, ItemTypeInt16, ItemTypeInt32, ItemTypeInt64:
sortArrayInt(ary, asc)
case ItemTypeUint8, ItemTypeUint16, ItemTypeUint32, ItemTypeUint64:
sortArrayUint(ary, asc)
case ItemTypeFloat32, ItemTypeFloat64:
sortArrayFloat(ary, asc)
case ItemTypeString:
sortArrayString(ary, asc)
case ItemTypeTime:
sortArrayTime(ary, &itemType, asc)
case ItemTypeObject:
// Convert "by" to string array
var byArr []string
if s, ok := by.(string); ok {
if s == "" {
return helpers.ErrorArrayItemNotSortable
}
byArr = strings.Split(s, ".")
} else {
return helpers.ErrorInvalidMethodParameters
}
if len(byArr) == 0 {
return helpers.ErrorInvalidMethodParameters
}
if err := sortArrayByObjectItem(ary, &itemType, byArr, asc); err != 0 {
return err
}
default:
return helpers.ErrorArrayItemNotSortable
}
return 0
}
// Sort Int type Arrays
func sortArrayInt(ary []interface{}, asc bool) {
// Convert int type to int64
var fArr []int64 = make([]int64, len(ary), len(ary))
var tf int64
var ti interface{}
for i, v := range ary {
fArr[i], _ = makeInt64(v)
}
// Sort as int64
for i := 0; i < len(fArr)-1; i++ {
for j := len(fArr) - 1; j > i; j-- {
if (asc && fArr[i] > fArr[j]) || (!asc && fArr[i] < fArr[j]) {
tf = fArr[i]
fArr[i] = fArr[j]
fArr[j] = tf
ti = ary[i]
ary[i] = ary[j]
ary[j] = ti
}
}
}
}
// Sort Uint type Arrays
func sortArrayUint(ary []interface{}, asc bool) {
// Convert uint type to uint64
var fArr []uint64 = make([]uint64, len(ary), len(ary))
var tf uint64
var ti interface{}
for i, v := range ary {
fArr[i], _ = makeUint64(v)
}
// Sort as uint64
for i := 0; i < len(fArr)-1; i++ {
for j := len(fArr) - 1; j > i; j-- {
if (asc && fArr[i] > fArr[j]) || (!asc && fArr[i] < fArr[j]) {
tf = fArr[i]
fArr[i] = fArr[j]
fArr[j] = tf
ti = ary[i]
ary[i] = ary[j]
ary[j] = ti
}
}
}
}
// Sort Float type Arrays
func sortArrayFloat(ary []interface{}, asc bool) {
// Convert float type to float64
var fArr []float64 = make([]float64, len(ary), len(ary))
var tf float64
var ti interface{}
for i, v := range ary {
fArr[i], _ = makeFloat64(v)
}
// Sort as float64
for i := 0; i < len(fArr)-1; i++ {
for j := len(fArr) - 1; j > i; j-- {
if (asc && fArr[i] > fArr[j]) || (!asc && fArr[i] < fArr[j]) {
tf = fArr[i]
fArr[i] = fArr[j]
fArr[j] = tf
ti = ary[i]
ary[i] = ary[j]
ary[j] = ti
}
}
}
}
// Sort string Arrays
func sortArrayString(ary []interface{}, asc bool) {
var iItem string
var jItem string
for i := 0; i < len(ary)-1; i++ {
iItem, _ = ary[i].(string)
for j := len(ary) - 1; j > i; j-- {
jItem, _ = ary[j].(string)
if (asc && iItem > jItem) || (!asc && iItem < jItem) {
ary[i] = jItem
ary[j] = iItem
iItem = jItem
}
}
}
}
// Sort time Arrays
func sortArrayTime(ary []interface{}, itemType *SchemaItem, asc bool) {
var iItem time.Time
var jItem time.Time
var t interface{}
for i := 0; i < len(ary)-1; i++ {
iItem, _ = makeTime(ary[i], itemType)
for j := len(ary) - 1; j > i; j-- {
jItem, _ = makeTime(ary[j], itemType)
if (asc && iItem.After(jItem)) || (!asc && iItem.Before(jItem)) {
t = ary[i]
ary[i] = ary[j]
ary[j] = t
iItem = jItem
}
}
}
}
// Sort Array by inner Object item
func sortArrayByObjectItem(ary []interface{}, itemType *SchemaItem, byArr []string, asc bool) int {
// Check by item
var innerSi SchemaItem
var dataIndexes []int = make([]int, len(byArr), len(byArr))
var err int
if innerSi, err = checkSortByItem(itemType.iType.(ObjectItem).schema, byArr, dataIndexes, 0); err != 0 {
return err
}
// Create check array for inner object item values
checkAry := make([]interface{}, len(ary), len(ary))
for i, v := range ary {
checkAry[i] = getSortByValue(v.([]interface{}), dataIndexes, 0)
}
// Sort by inner type
switch innerSi.typeName {
case ItemTypeInt8, ItemTypeInt16, ItemTypeInt32, ItemTypeInt64:
// Convert int type to int64
var fArr []int64 = make([]int64, len(checkAry), len(checkAry))
var tf int64
var ti interface{}
for i, v := range checkAry {
fArr[i], _ = makeInt64(v)
}
for i := 0; i < len(fArr)-1; i++ {
for j := len(fArr) - 1; j > i; j-- {
if (asc && fArr[i] > fArr[j]) || (!asc && fArr[i] < fArr[j]) {
// Swap both ary and checkAry
ti = ary[i]
ary[i] = ary[j]
ary[j] = ti
tf = fArr[i]
fArr[i] = fArr[j]
fArr[j] = tf
}
}
}
return 0
case ItemTypeUint8, ItemTypeUint16, ItemTypeUint32, ItemTypeUint64:
// Convert uint type to uint64
var fArr []uint64 = make([]uint64, len(checkAry), len(checkAry))
var tf uint64
var ti interface{}
for i, v := range checkAry {
fArr[i], _ = makeUint64(v)
}
for i := 0; i < len(fArr)-1; i++ {
for j := len(fArr) - 1; j > i; j-- {
if (asc && fArr[i] > fArr[j]) || (!asc && fArr[i] < fArr[j]) {
// Swap both ary and checkAry
ti = ary[i]
ary[i] = ary[j]
ary[j] = ti
tf = fArr[i]
fArr[i] = fArr[j]
fArr[j] = tf
}
}
}
return 0
case ItemTypeFloat32, ItemTypeFloat64:
// Convert float type to float64
var fArr []float64 = make([]float64, len(checkAry), len(checkAry))
var tf float64
var ti interface{}
for i, v := range checkAry {
fArr[i], _ = makeFloat64(v)
}
for i := 0; i < len(fArr)-1; i++ {
for j := len(fArr) - 1; j > i; j-- {
if (asc && fArr[i] > fArr[j]) || (!asc && fArr[i] < fArr[j]) {
// Swap both ary and checkAry
ti = ary[i]
ary[i] = ary[j]
ary[j] = ti
tf = fArr[i]
fArr[i] = fArr[j]
fArr[j] = tf
}
}
}
return 0
case ItemTypeString:
// Sort as string
var iItem string
var jItem string
var t interface{}
for i := 0; i < len(checkAry)-1; i++ {
iItem, _ = checkAry[i].(string)
for j := len(checkAry) - 1; j > i; j-- {
jItem, _ = checkAry[j].(string) // could change with inner loop
if (asc && iItem > jItem) || (!asc && iItem < jItem) {
// Swap both ary and checkAry
t = ary[i]
ary[i] = ary[j]
ary[j] = t
checkAry[i] = jItem
checkAry[j] = iItem
iItem = jItem
}
}
}
return 0
case ItemTypeTime:
// Sort as Time
var iItem time.Time
var jItem time.Time
var t interface{}
for i := 0; i < len(checkAry)-1; i++ {
iItem, _ = makeTime(checkAry[i], &innerSi)
for j := len(checkAry) - 1; j > i; j-- {
jItem, _ = makeTime(checkAry[j], &innerSi)
if (asc && iItem.After(jItem)) || (!asc && iItem.Before(jItem)) {
// Swap both ary and checkAry
t = ary[i]
ary[i] = ary[j]
ary[j] = t
checkAry[i] = jItem
checkAry[j] = iItem
iItem = jItem
}
}
}
}
return 0
}
// Check validity of a sort-by query parameter
func checkSortByItem(schema Schema, byArr []string, dataIndexes []int, byOn int) (SchemaItem, int) {
si := schema[byArr[byOn]]
if si.QuickValidate() {
switch si.typeName {
case ItemTypeArray, ItemTypeMap:
// Not sortable
return SchemaItem{}, helpers.ErrorArrayItemNotSortable
case ItemTypeObject:
if len(byArr) == byOn+1 {
return SchemaItem{}, helpers.ErrorArrayItemNotSortable
}
dataIndexes[byOn] = int(schema[byArr[byOn]].dataIndex)
return checkSortByItem(si.iType.(ObjectItem).schema, byArr, dataIndexes, byOn+1)
}
if len(byArr) != byOn+1 {
return SchemaItem{}, helpers.ErrorInvalidMethodParameters
}
dataIndexes[byOn] = int(schema[byArr[byOn]].dataIndex)
return si, 0
}
return SchemaItem{}, helpers.ErrorInvalidMethodParameters
}
// Get the value of inner Objects for a sort-by query
func getSortByValue(i []interface{}, dataIndexes []int, iOn int) interface{} {
if iOn < len(dataIndexes)-1 {
return getSortByValue(i[dataIndexes[iOn]].([]interface{}), dataIndexes, iOn+1)
}
return i[dataIndexes[iOn]]
}