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 | getOptions () {
|
54 | return this._options;
|
55 | }
|
56 |
|
57 | options (data) {
|
58 | this._options = data;
|
59 | return this;
|
60 | }
|
61 |
|
62 | addOptions (data) {
|
63 | this._options = this._options ? Object.assign(this._options, data) : data;
|
64 | return this;
|
65 | }
|
66 |
|
67 |
|
68 |
|
69 | select (data) {
|
70 | if (Array.isArray(data)) {
|
71 | this.select(data[0]);
|
72 | for (let i = 1; i < data.length; ++i) {
|
73 | this.addSelect(data[i]);
|
74 | }
|
75 | } else if (typeof data === 'string') {
|
76 | this._select = {[data]: 1};
|
77 | } else {
|
78 | this._select = data;
|
79 | }
|
80 | return this;
|
81 | }
|
82 |
|
83 | addSelect (data) {
|
84 | if (!this._select) {
|
85 | return this.select(data);
|
86 | }
|
87 | if (Array.isArray(data)) {
|
88 | for (const item of data) {
|
89 | this.addSelect(item);
|
90 | }
|
91 | } else if (typeof data === 'string') {
|
92 | this._select[data] = 1;
|
93 | } else {
|
94 | Object.assign(this._select, data);
|
95 | }
|
96 | return this;
|
97 | }
|
98 |
|
99 | getSelect () {
|
100 | return this._select;
|
101 | }
|
102 |
|
103 |
|
104 |
|
105 | where (condition) {
|
106 | this._where = condition;
|
107 | return this;
|
108 | }
|
109 |
|
110 | addWhere (operator, ...conditions) {
|
111 | if (!this._where) {
|
112 | this._where = conditions.length > 1 ? [operator, ...conditions] : conditions[0];
|
113 | } else if (this._where[0] === operator) {
|
114 | this._where.push(...conditions);
|
115 | } else {
|
116 | this._where = [operator, this._where, ...conditions];
|
117 | }
|
118 | }
|
119 |
|
120 | getWhere () {
|
121 | return this._where;
|
122 | }
|
123 |
|
124 | and () {
|
125 | if (arguments[0]) {
|
126 | this.addWhere('AND', ...arguments);
|
127 | }
|
128 | return this;
|
129 | }
|
130 |
|
131 | or () {
|
132 | if (arguments[0]) {
|
133 | this.addWhere('OR', ...arguments);
|
134 | }
|
135 | return this;
|
136 | }
|
137 |
|
138 | filter (condition) {
|
139 | return this.where(this.filterCondition(condition));
|
140 | }
|
141 |
|
142 | andFilter (condition) {
|
143 | return this.and(this.filterCondition(condition));
|
144 | }
|
145 |
|
146 | orFilter (condition) {
|
147 | return this.or(this.filterCondition(condition));
|
148 | }
|
149 |
|
150 | andNotIn (key, value) {
|
151 | return this.and(['NOT IN', key, value]);
|
152 | }
|
153 |
|
154 |
|
155 | |
156 |
|
157 |
|
158 | order (data) {
|
159 | this._order = data;
|
160 | return this;
|
161 | }
|
162 |
|
163 | addOrder (data) {
|
164 | this._order = this._order ? Object.assign(this._order, data) : data;
|
165 | return this;
|
166 | }
|
167 |
|
168 | orderByKeys (keys) {
|
169 | this._orderByKeys = keys;
|
170 | return this;
|
171 | }
|
172 |
|
173 |
|
174 |
|
175 | limit (limit) {
|
176 | this._limit = limit === null ? null : parseInt(limit);
|
177 | return this;
|
178 | }
|
179 |
|
180 | getLimit () {
|
181 | return this._limit;
|
182 | }
|
183 |
|
184 |
|
185 |
|
186 | offset (value) {
|
187 | this._offset = value === null ? null : parseInt(value);
|
188 | return this;
|
189 | }
|
190 |
|
191 | getOffset () {
|
192 | return this._offset;
|
193 | }
|
194 |
|
195 |
|
196 |
|
197 | all () {
|
198 | return this._db.queryAll(this);
|
199 | }
|
200 |
|
201 | one () {
|
202 | return this._db.queryOne(this);
|
203 | }
|
204 |
|
205 | column (key) {
|
206 | return this._db.queryColumn(this, key);
|
207 | }
|
208 |
|
209 | distinct (key) {
|
210 | return this._db.queryDistinct(this, key);
|
211 | }
|
212 |
|
213 | id () {
|
214 | return this._db.queryScalar(this, '_id');
|
215 | }
|
216 |
|
217 | ids () {
|
218 | return this._db.queryColumn(this, '_id');
|
219 | }
|
220 |
|
221 | scalar (key) {
|
222 | return this._db.queryScalar(this, key);
|
223 | }
|
224 |
|
225 | insert (data) {
|
226 | return this._db.queryInsert(this, data);
|
227 | }
|
228 |
|
229 | update (data) {
|
230 | return this._db.queryUpdate(this, data);
|
231 | }
|
232 |
|
233 | updateAll (data) {
|
234 | return this._db.queryUpdateAll(this, data);
|
235 | }
|
236 |
|
237 | upsert (data) {
|
238 | return this._db.queryUpsert(this, data);
|
239 | }
|
240 |
|
241 | delete () {
|
242 | return this._db.queryDelete(this);
|
243 | }
|
244 |
|
245 | count () {
|
246 | return this._db.queryCount(this);
|
247 | }
|
248 |
|
249 | max (key) {
|
250 | this._order = {[key]: -1};
|
251 | this._limit = 1;
|
252 | return this.scalar(key);
|
253 | }
|
254 |
|
255 | min (key) {
|
256 | this._order = {[key]: 1};
|
257 | this._limit = 1;
|
258 | return this.scalar(key);
|
259 | }
|
260 |
|
261 |
|
262 |
|
263 | isEmptyValue (value) {
|
264 | return value === undefined || value === null || value === ''
|
265 | || (typeof value === 'string' && value.trim() === '')
|
266 | || (typeof value === 'object' && !Object.values(value).length);
|
267 | }
|
268 |
|
269 | prepare () {
|
270 | }
|
271 |
|
272 | afterBuild () {
|
273 |
|
274 | if (this._whereBeforeFilter !== undefined) {
|
275 | this._where = this._whereBeforeFilter;
|
276 | delete this._whereBeforeFilter;
|
277 | }
|
278 | }
|
279 |
|
280 | populate (docs) {
|
281 | return this._index
|
282 | ? QueryHelper.indexObjects(docs, this._index)
|
283 | : docs;
|
284 | }
|
285 |
|
286 | filterCondition (data) {
|
287 | return Array.isArray(data)
|
288 | ? this.filterOperatorCondition(data)
|
289 | : data ? this.filterHashCondition(data)
|
290 | : null;
|
291 | }
|
292 |
|
293 |
|
294 | filterOperatorCondition (data) {
|
295 | switch (data[0]) {
|
296 | case 'NOT':
|
297 | case 'AND':
|
298 | case 'OR':
|
299 | return this.filterSerialCondition();
|
300 | case 'BETWEEN':
|
301 | case 'NOT BETWEEN':
|
302 | return !this.isEmptyValue(data[1]) && !this.isEmptyValue(data[2]) ? data : null;
|
303 | }
|
304 | return this.isEmptyValue(data[1]) ? null : data;
|
305 | }
|
306 |
|
307 | filterSerialCondition (data) {
|
308 | for (let i = data.length - 1; i > 0; --i) {
|
309 | const item = this.filterCondition(data[i]);
|
310 | if (this.isEmptyValue(item)) {
|
311 | data.splice(i, 1);
|
312 | } else {
|
313 | data[i] = item;
|
314 | }
|
315 | }
|
316 | return data.length > 1 ? data : null;
|
317 | }
|
318 |
|
319 |
|
320 | filterHashCondition (data) {
|
321 | const result = {};
|
322 | for (const key of Object.keys(data)) {
|
323 | if (!this.isEmptyValue(data[key])) {
|
324 | result[key] = data[key];
|
325 | }
|
326 | }
|
327 | return Object.values(result).length ? result : null;
|
328 | }
|
329 |
|
330 |
|
331 | sortOrderByKeys (docs) {
|
332 | const keys = this._orderByKeys;
|
333 | if (!Array.isArray(keys) || keys.length < 2) {
|
334 | return docs;
|
335 | }
|
336 |
|
337 | const data = IndexHelper.indexObjectArrays(docs, this.refKey);
|
338 | const result = [];
|
339 | for (const key of keys) {
|
340 | if (Array.isArray(data[key])) {
|
341 | result.push(...data[key]);
|
342 | delete data[key];
|
343 | }
|
344 | }
|
345 | return result;
|
346 | }
|
347 | };
|
348 |
|
349 | const IndexHelper = require('../helper/IndexHelper');
|
350 | const QueryHelper = require('../helper/QueryHelper'); |
\ | No newline at end of file |