1 |
|
2 |
|
3 |
|
4 | 'use strict';
|
5 |
|
6 | const Base = require('../base/Base');
|
7 |
|
8 | module.exports = class Query extends Base {
|
9 |
|
10 | _index = null;
|
11 | _limit = null;
|
12 | _offset = null;
|
13 | _order = null;
|
14 | _where = null;
|
15 |
|
16 | db (db) {
|
17 | this._db = db;
|
18 | return this;
|
19 | }
|
20 |
|
21 | from (table) {
|
22 | this._from = table;
|
23 | return this;
|
24 | }
|
25 |
|
26 | index (column) {
|
27 | this._index = column;
|
28 | return this;
|
29 | }
|
30 |
|
31 | raw () {
|
32 | return this;
|
33 | }
|
34 |
|
35 | getDb () {
|
36 | return this._db;
|
37 | }
|
38 |
|
39 | getTable () {
|
40 | return this._from;
|
41 | }
|
42 |
|
43 | getIndex () {
|
44 | return this._index;
|
45 | }
|
46 |
|
47 | getRaw () {
|
48 | return this._raw;
|
49 | }
|
50 |
|
51 |
|
52 |
|
53 | select (data) {
|
54 | if (Array.isArray(data)) {
|
55 | for (const item of data) {
|
56 | this.addSelect(item);
|
57 | }
|
58 | } else if (typeof data === 'string') {
|
59 | this._select = {[data]: 1};
|
60 | } else {
|
61 | this._select = data;
|
62 | }
|
63 | return this;
|
64 | }
|
65 |
|
66 | addSelect (data) {
|
67 | if (Array.isArray(data)) {
|
68 | for (const item of data) {
|
69 | this.addSelect(item);
|
70 | }
|
71 | } else if (!this._select) {
|
72 | return this.select(data);
|
73 | }
|
74 | if (typeof data === 'string') {
|
75 | this._select[data] = 1;
|
76 | } else {
|
77 | Object.assign(this._select, data);
|
78 | }
|
79 | return this;
|
80 | }
|
81 |
|
82 |
|
83 |
|
84 | where (condition) {
|
85 | this._where = condition;
|
86 | return this;
|
87 | }
|
88 |
|
89 | getWhere () {
|
90 | return this._where;
|
91 | }
|
92 |
|
93 | addWhere (operator, ...conditions) {
|
94 | if (!this._where) {
|
95 | this._where = conditions.length > 1 ? [operator, ...conditions] : conditions[0];
|
96 | } else if (this._where[0] === operator) {
|
97 | this._where.push(...conditions);
|
98 | } else {
|
99 | this._where = [operator, this._where, ...conditions];
|
100 | }
|
101 | }
|
102 |
|
103 | and () {
|
104 | if (arguments[0]) {
|
105 | this.addWhere('AND', ...arguments);
|
106 | }
|
107 | return this;
|
108 | }
|
109 |
|
110 | or () {
|
111 | if (arguments[0]) {
|
112 | this.addWhere('OR', ...arguments);
|
113 | }
|
114 | return this;
|
115 | }
|
116 |
|
117 | filter (condition) {
|
118 | return this.where(this.filterCondition(condition));
|
119 | }
|
120 |
|
121 | andFilter (condition) {
|
122 | return this.and(this.filterCondition(condition));
|
123 | }
|
124 |
|
125 | orFilter (condition) {
|
126 | return this.or(this.filterCondition(condition));
|
127 | }
|
128 |
|
129 | andNotIn (key, value) {
|
130 | return this.and(['NOT IN', key, value]);
|
131 | }
|
132 |
|
133 |
|
134 | |
135 |
|
136 |
|
137 | order (data) {
|
138 | this._order = data;
|
139 | return this;
|
140 | }
|
141 |
|
142 | addOrder (data) {
|
143 | this._order = Object.assign(this._order || {}, data);
|
144 | return this;
|
145 | }
|
146 |
|
147 | orderByKeys (keys) {
|
148 | this._orderByKeys = keys;
|
149 | return this;
|
150 | }
|
151 |
|
152 |
|
153 |
|
154 | limit (limit) {
|
155 | this._limit = limit === null ? null : parseInt(limit);
|
156 | return this;
|
157 | }
|
158 |
|
159 | getLimit () {
|
160 | return this._limit;
|
161 | }
|
162 |
|
163 |
|
164 |
|
165 | offset (value) {
|
166 | this._offset = value === null ? null : parseInt(value);
|
167 | return this;
|
168 | }
|
169 |
|
170 | getOffset () {
|
171 | return this._offset;
|
172 | }
|
173 |
|
174 |
|
175 |
|
176 | all () {
|
177 | return this._db.queryAll(this);
|
178 | }
|
179 |
|
180 | one () {
|
181 | return this._db.queryOne(this);
|
182 | }
|
183 |
|
184 | column (key) {
|
185 | return this._db.queryColumn(this, key);
|
186 | }
|
187 |
|
188 | distinct (key) {
|
189 | return this._db.queryDistinct(this, key);
|
190 | }
|
191 |
|
192 | scalar (key) {
|
193 | return this._db.queryScalar(this, key);
|
194 | }
|
195 |
|
196 | insert (data) {
|
197 | return this._db.queryInsert(this, data);
|
198 | }
|
199 |
|
200 | update (data) {
|
201 | return this._db.queryUpdate(this, data);
|
202 | }
|
203 |
|
204 | updateAll (data) {
|
205 | return this._db.queryUpdateAll(this, data);
|
206 | }
|
207 |
|
208 | upsert (data) {
|
209 | return this._db.queryUpsert(this, data);
|
210 | }
|
211 |
|
212 | delete () {
|
213 | return this._db.queryDelete(this);
|
214 | }
|
215 |
|
216 | count () {
|
217 | return this._db.queryCount(this);
|
218 | }
|
219 |
|
220 | max (key) {
|
221 | this._order = {[key]: -1};
|
222 | this._limit = 1;
|
223 | return this.scalar(key);
|
224 | }
|
225 |
|
226 | min (key) {
|
227 | this._order = {[key]: 1};
|
228 | this._limit = 1;
|
229 | return this.scalar(key);
|
230 | }
|
231 |
|
232 |
|
233 |
|
234 | isEmptyValue (value) {
|
235 | return value === undefined || value === null || value === ''
|
236 | || (typeof value === 'string' && value.trim() === '')
|
237 | || (typeof value === 'object' && !Object.values(value).length);
|
238 | }
|
239 |
|
240 | prepare () {
|
241 | }
|
242 |
|
243 | afterBuild () {
|
244 |
|
245 | if (this._whereBeforeFilter !== undefined) {
|
246 | this._where = this._whereBeforeFilter;
|
247 | delete this._whereBeforeFilter;
|
248 | }
|
249 | }
|
250 |
|
251 | populate (docs) {
|
252 | return this._index
|
253 | ? QueryHelper.indexObjects(docs, this._index)
|
254 | : docs;
|
255 | }
|
256 |
|
257 | filterCondition (data) {
|
258 | return Array.isArray(data)
|
259 | ? this.filterOperatorCondition(data)
|
260 | : data ? this.filterHashCondition(data)
|
261 | : null;
|
262 | }
|
263 |
|
264 |
|
265 | filterOperatorCondition (data) {
|
266 | switch (data[0]) {
|
267 | case 'NOT':
|
268 | case 'AND':
|
269 | case 'OR':
|
270 | return this.filterSerialCondition();
|
271 | case 'BETWEEN':
|
272 | case 'NOT BETWEEN':
|
273 | return !this.isEmptyValue(data[1]) && !this.isEmptyValue(data[2]) ? data : null;
|
274 | }
|
275 | return this.isEmptyValue(data[1]) ? null : data;
|
276 | }
|
277 |
|
278 | filterSerialCondition (data) {
|
279 | for (let i = data.length - 1; i > 0; --i) {
|
280 | const item = this.filterCondition(data[i]);
|
281 | if (this.isEmptyValue(item)) {
|
282 | data.splice(i, 1);
|
283 | } else {
|
284 | data[i] = item;
|
285 | }
|
286 | }
|
287 | return data.length > 1 ? data : null;
|
288 | }
|
289 |
|
290 |
|
291 | filterHashCondition (data) {
|
292 | const result = {};
|
293 | for (const key of Object.keys(data)) {
|
294 | if (!this.isEmptyValue(data[key])) {
|
295 | result[key] = data[key];
|
296 | }
|
297 | }
|
298 | return Object.values(result).length ? result : null;
|
299 | }
|
300 |
|
301 |
|
302 | sortOrderByKeys (docs) {
|
303 | const keys = this._orderByKeys;
|
304 | if (!Array.isArray(keys) || keys.length < 2) {
|
305 | return docs;
|
306 | }
|
307 |
|
308 | const data = IndexHelper.indexObjectArrays(docs, this.refKey);
|
309 | const result = [];
|
310 | for (const key of keys) {
|
311 | if (Array.isArray(data[key])) {
|
312 | result.push(...data[key]);
|
313 | delete data[key];
|
314 | }
|
315 | }
|
316 | return result;
|
317 | }
|
318 | };
|
319 |
|
320 | const IndexHelper = require('../helper/IndexHelper');
|
321 | const QueryHelper = require('../helper/QueryHelper'); |
\ | No newline at end of file |