-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
122 lines (106 loc) · 2.94 KB
/
index.js
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
function query() {
const defaultFn = o => { return o }
this.selectValue = defaultFn
this.whereValueOr = []
this.whereValueAnd = []
this.groupValue = defaultFn
this.havingValue = defaultFn
this.orderValue = defaultFn
this.fromValue = []
this.fromCalls = 0
this.selectCalls = 0
this.groupCalls = 0
this.havingCalls = 0
this.orderCalls = 0
this.select = function(f) {
this.selectValue = f || this.selectValue
this.selectCalls++
return this
}
this.from = function(v) {
const values = Array.prototype.slice.call(arguments)
this.fromValue = (values.length<2?v:values[0].map(i=>{ return values[1].map(x=>{ return [i,x] })})
.reduce((p,i) => {p.push(i[0]);p.push(i[1]);return p},[]))
this.fromCalls++
return this
}
this.where = function(v) {
const args = Array.prototype.slice.call(arguments)
if (args.length > 1) {
args.forEach(a => {
this.whereValueOr.push(a)
})
return this
}
this.whereValueAnd.push(v)
return this
}
this.groupBy = function(v) {
this.groupValue = Array.prototype.slice.call(arguments)
this.groupCalls++
return this
}
this.having = function(v) {
this.havingValue = v
this.havingCalls++
return this
}
this.orderBy = function(v) {
this.orderValue = v
this.orderCalls++
return this
}
const groupBy = (arr, i) => {
const idx = i || 0
if (this.groupCalls < 1) return arr
if (!this.groupValue[idx]) return arr
return arr.reduce( (prev, o) => {
if (prev.indexOf(this.groupValue[idx](o)) === -1) {
prev.push(this.groupValue[idx](o));
}
return prev
},[])
.map ((o) => {
return [o,
groupBy(arr.filter( (oo) => {
return this.groupValue[idx](oo) === o
}), idx+1)]
})
}
const havingFilter = (arr) => {
if (!this.havingCalls) return arr
if (!this.groupCalls) throw new Error('Call HAVING without GROUPS')
return arr.filter(this.havingValue)
}
const orderFilter = (arr) => {
if (!this.orderCalls) return arr
return [].concat(arr).sort((val1, val2) => {
return this.orderValue(val1[0] || val1, val2[0] || val2)
})
}
const whereFilterOr = (arr) => {
if (this.whereValueOr.length < 1) return arr
const r = this.whereValueOr.reduce((acc, i) => {
return acc.concat(arr.filter(i))
}, [])
return r
}
const whereFilterAnd = (arr) => {
if (this.whereValueAnd.length < 1) return arr
const r = this.whereValueAnd.reduce((acc, i) => {
return acc.filter(i)
},arr)
return r
}
this.execute = function() {
if (this.selectCalls > 1) throw new Error('Duplicate SELECT')
if (this.fromCalls > 1) throw new Error('Duplicate FROM')
if (this.groupCalls > 1) throw new Error('Duplicate GROUPBY')
if (this.orderCalls > 1) throw new Error('Duplicate ORDERBY')
return orderFilter(havingFilter(
groupBy(whereFilterAnd(whereFilterOr(this.fromValue)))))
.map(this.selectValue)
}
return this
}
module.exports = function() {return new query()}