sql-love 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -10
- package/dist/index.cjs +84 -538
- package/dist/index.mjs +60 -505
- package/package.json +15 -15
package/dist/index.cjs
CHANGED
|
@@ -1,71 +1,65 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
6
|
+
var __toCommonJS = (from) => {
|
|
7
|
+
var entry = __moduleCache.get(from), desc;
|
|
8
|
+
if (entry)
|
|
9
|
+
return entry;
|
|
10
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
12
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
13
|
+
get: () => from[key],
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
}));
|
|
16
|
+
__moduleCache.set(from, entry);
|
|
17
|
+
return entry;
|
|
18
|
+
};
|
|
5
19
|
var __export = (target, all) => {
|
|
6
20
|
for (var name in all)
|
|
7
|
-
__defProp(target, name, {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
21
|
+
__defProp(target, name, {
|
|
22
|
+
get: all[name],
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
set: (newValue) => all[name] = () => newValue
|
|
26
|
+
});
|
|
16
27
|
};
|
|
17
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
28
|
|
|
19
29
|
// index.ts
|
|
20
|
-
var
|
|
21
|
-
__export(
|
|
22
|
-
|
|
23
|
-
SelectBuilder: () => SelectBuilder,
|
|
24
|
-
extractGrouped: () => extractGrouped,
|
|
25
|
-
extractIndexed: () => extractIndexed,
|
|
26
|
-
extractLookup: () => extractLookup,
|
|
27
|
-
getPagination: () => getPagination,
|
|
28
|
-
runMysql: () => runMysql,
|
|
29
|
-
runMysqlAsync: () => runMysqlAsync,
|
|
30
|
-
runMysqlAsyncWithCount: () => runMysqlAsyncWithCount,
|
|
31
|
-
runMysqlWithCount: () => runMysqlWithCount,
|
|
32
|
-
runPrisma: () => runPrisma,
|
|
33
|
-
runPrismaWithCount: () => runPrismaWithCount,
|
|
34
|
-
toSafeJsonRecord: () => toSafeJsonRecord,
|
|
35
|
-
toSafeJsonRecords: () => toSafeJsonRecords,
|
|
30
|
+
var exports_sql_love = {};
|
|
31
|
+
__export(exports_sql_love, {
|
|
32
|
+
toSafeJsonValue: () => toSafeJsonValue,
|
|
36
33
|
toSafeJsonString: () => toSafeJsonString,
|
|
37
|
-
|
|
34
|
+
toSafeJsonRecords: () => toSafeJsonRecords,
|
|
35
|
+
toSafeJsonRecord: () => toSafeJsonRecord,
|
|
36
|
+
runPrismaWithCount: () => runPrismaWithCount,
|
|
37
|
+
runPrisma: () => runPrisma,
|
|
38
|
+
runMysqlWithCount: () => runMysqlWithCount,
|
|
39
|
+
runMysqlAsyncWithCount: () => runMysqlAsyncWithCount,
|
|
40
|
+
runMysqlAsync: () => runMysqlAsync,
|
|
41
|
+
runMysql: () => runMysql,
|
|
42
|
+
getPagination: () => getPagination,
|
|
43
|
+
extractLookup: () => extractLookup,
|
|
44
|
+
extractIndexed: () => extractIndexed,
|
|
45
|
+
extractGrouped: () => extractGrouped,
|
|
46
|
+
SelectBuilder: () => SelectBuilder,
|
|
47
|
+
Parser: () => Parser
|
|
38
48
|
});
|
|
39
|
-
module.exports = __toCommonJS(
|
|
49
|
+
module.exports = __toCommonJS(exports_sql_love);
|
|
40
50
|
|
|
41
51
|
// src/Parser/Parser.ts
|
|
42
|
-
|
|
52
|
+
class Parser {
|
|
43
53
|
query;
|
|
44
|
-
/**
|
|
45
|
-
* Create a new instance
|
|
46
|
-
* @param query A Select object on which to build parsed conditions
|
|
47
|
-
*/
|
|
48
54
|
constructor(query) {
|
|
49
55
|
this.query = query;
|
|
50
56
|
}
|
|
51
|
-
/**
|
|
52
|
-
* Strip single-line and multi-line comment blocks
|
|
53
|
-
* @param sql The SQL string
|
|
54
|
-
* @return The SQL string without comments
|
|
55
|
-
* @private
|
|
56
|
-
*/
|
|
57
57
|
_stripComments(sql) {
|
|
58
58
|
sql = sql.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
59
59
|
sql = sql.replace(/--([\r\n]|\s+[^\r\n]+[\r\n])/g, "");
|
|
60
60
|
sql = sql.replace(/#[^\r\n]+[\r\n]/g, "");
|
|
61
61
|
return sql;
|
|
62
62
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Before splitting into SQL clauses, extract some regex-able subQueries
|
|
65
|
-
* @param sql The unparsed sql string
|
|
66
|
-
* @return An array with new sql and subQueries
|
|
67
|
-
* @private
|
|
68
|
-
*/
|
|
69
63
|
_extractSubQueries(sql) {
|
|
70
64
|
const subQueries = {};
|
|
71
65
|
let i = 0;
|
|
@@ -79,11 +73,6 @@ var Parser = class {
|
|
|
79
73
|
sql = sql.replace(/\bIN\s*\(\s*SELECT\s.+?\)/, extractor);
|
|
80
74
|
return { sql, subQueries };
|
|
81
75
|
}
|
|
82
|
-
/**
|
|
83
|
-
* Inject column subQueries back into this object
|
|
84
|
-
* @param subQueries The lookup of extracted subQueries
|
|
85
|
-
* @private
|
|
86
|
-
*/
|
|
87
76
|
_injectSubQueries(subQueries) {
|
|
88
77
|
const replacer = ($0) => {
|
|
89
78
|
return subQueries[$0] || $0;
|
|
@@ -96,21 +85,10 @@ var Parser = class {
|
|
|
96
85
|
this.query._wheres = this.query._wheres.map(mapper);
|
|
97
86
|
this.query._havings = this.query._havings.map(mapper);
|
|
98
87
|
}
|
|
99
|
-
/**
|
|
100
|
-
* Split SQL into clauses (used by parse())
|
|
101
|
-
* @param sql The SQL to split
|
|
102
|
-
* @return
|
|
103
|
-
* @private
|
|
104
|
-
*/
|
|
105
88
|
_split(sql) {
|
|
106
89
|
const splitter = /(?:^|\s)(SELECT|FROM|(?:INNER|LEFT\s+OUTER|RIGHT\s+OUTER|LEFT|RIGHT|CROSS|FULL|FULL\s+OUTER)\s+JOIN|WHERE|GROUP\s+BY|HAVING|ORDER\s+BY|LIMIT|OFFSET|FETCH\s+NEXT)\b/i;
|
|
107
90
|
return sql.split(splitter);
|
|
108
91
|
}
|
|
109
|
-
/**
|
|
110
|
-
* Get a QuickSelect object representing the given SQL SELECT statement
|
|
111
|
-
* @param rawSql The raw SQL for the SELECT statement
|
|
112
|
-
* @return True if the SQL was parsed successfully
|
|
113
|
-
*/
|
|
114
92
|
parse(rawSql) {
|
|
115
93
|
const stripped = this._stripComments(rawSql);
|
|
116
94
|
const { sql, subQueries } = this._extractSubQueries(stripped);
|
|
@@ -126,11 +104,6 @@ var Parser = class {
|
|
|
126
104
|
this._injectSubQueries(subQueries);
|
|
127
105
|
return true;
|
|
128
106
|
}
|
|
129
|
-
/**
|
|
130
|
-
* Handle SQL_CALC_FOUND_ROWS and column names
|
|
131
|
-
* @param clause The clause after the SELECT
|
|
132
|
-
* @private
|
|
133
|
-
*/
|
|
134
107
|
_handleSELECT(clause) {
|
|
135
108
|
let columns = clause.split(/s*,s*/);
|
|
136
109
|
let buffer = "";
|
|
@@ -158,84 +131,34 @@ var Parser = class {
|
|
|
158
131
|
}
|
|
159
132
|
});
|
|
160
133
|
}
|
|
161
|
-
/**
|
|
162
|
-
* Handle table names
|
|
163
|
-
* @param clause The clause after the FROM
|
|
164
|
-
* @private
|
|
165
|
-
*/
|
|
166
134
|
_handleFROM(clause) {
|
|
167
135
|
const tables = clause.split(/\s*,\s*/);
|
|
168
136
|
tables.forEach((table) => this.query.table(table));
|
|
169
137
|
}
|
|
170
|
-
/**
|
|
171
|
-
* Handle INNER JOIN statements
|
|
172
|
-
* @param clause The clause after the INNER JOIN
|
|
173
|
-
* @private
|
|
174
|
-
*/
|
|
175
138
|
_handleINNER_JOIN(clause) {
|
|
176
139
|
this.query.innerJoin(clause);
|
|
177
140
|
}
|
|
178
|
-
/**
|
|
179
|
-
* Handle LEFT JOIN statements
|
|
180
|
-
* @param clause The clause after the LEFT JOIN
|
|
181
|
-
* @private
|
|
182
|
-
*/
|
|
183
141
|
_handleLEFT_JOIN(clause) {
|
|
184
142
|
this.query.leftJoin(clause);
|
|
185
143
|
}
|
|
186
|
-
/**
|
|
187
|
-
* Handle LEFT OUTER JOIN statements
|
|
188
|
-
* @param clause The clause after the LEFT OUTER JOIN
|
|
189
|
-
* @private
|
|
190
|
-
*/
|
|
191
144
|
_handleLEFT_OUTER_JOIN(clause) {
|
|
192
145
|
this.query.leftOuterJoin(clause);
|
|
193
146
|
}
|
|
194
|
-
/**
|
|
195
|
-
* Handle RIGHT JOIN statements
|
|
196
|
-
* @param clause The clause after the RIGHT JOIN
|
|
197
|
-
* @private
|
|
198
|
-
*/
|
|
199
147
|
_handleRIGHT_JOIN(clause) {
|
|
200
148
|
this.query.rightJoin(clause);
|
|
201
149
|
}
|
|
202
|
-
/**
|
|
203
|
-
* Handle RIGHT OUTER JOIN statements
|
|
204
|
-
* @param clause The clause after the RIGHT OUTER JOIN
|
|
205
|
-
* @private
|
|
206
|
-
*/
|
|
207
150
|
_handleRIGHT_OUTER_JOIN(clause) {
|
|
208
151
|
this.query.rightOuterJoin(clause);
|
|
209
152
|
}
|
|
210
|
-
/**
|
|
211
|
-
* Handle CROSS JOIN statements
|
|
212
|
-
* @param clause The clause after the CROSS JOIN
|
|
213
|
-
* @private
|
|
214
|
-
*/
|
|
215
153
|
_handleCROSS_JOIN(clause) {
|
|
216
154
|
this.query.crossJoin(clause);
|
|
217
155
|
}
|
|
218
|
-
/**
|
|
219
|
-
* Handle FULL JOIN statements
|
|
220
|
-
* @param clause The clause after the FULL JOIN
|
|
221
|
-
* @private
|
|
222
|
-
*/
|
|
223
156
|
_handleFULL_JOIN(clause) {
|
|
224
157
|
this.query.fullJoin(clause);
|
|
225
158
|
}
|
|
226
|
-
/**
|
|
227
|
-
* Handle FULL OUTER JOIN statements
|
|
228
|
-
* @param clause The clause after the FULL OUTER JOIN
|
|
229
|
-
* @private
|
|
230
|
-
*/
|
|
231
159
|
_handleFULL_OUTER_JOIN(clause) {
|
|
232
160
|
this.query.fullOuterJoin(clause);
|
|
233
161
|
}
|
|
234
|
-
/**
|
|
235
|
-
* Handle WHERE conditions
|
|
236
|
-
* @param clause All the conditions after WHERE
|
|
237
|
-
* @private
|
|
238
|
-
*/
|
|
239
162
|
_handleWHERE(clause) {
|
|
240
163
|
if (/^(1|'1'|true)$/i.test(clause)) {
|
|
241
164
|
this.query._wheres.push(clause);
|
|
@@ -243,20 +166,9 @@ var Parser = class {
|
|
|
243
166
|
this._handleConditions("where", clause);
|
|
244
167
|
}
|
|
245
168
|
}
|
|
246
|
-
/**
|
|
247
|
-
* Handle HAVING statements
|
|
248
|
-
* @param clause All the conditions after HAVING
|
|
249
|
-
* @private
|
|
250
|
-
*/
|
|
251
169
|
_handleHAVING(clause) {
|
|
252
170
|
this._handleConditions("having", clause);
|
|
253
171
|
}
|
|
254
|
-
/**
|
|
255
|
-
* Build a conditions list
|
|
256
|
-
* @param type Either where or having
|
|
257
|
-
* @param clause The expressions following the type keyword
|
|
258
|
-
* @private
|
|
259
|
-
*/
|
|
260
172
|
_handleConditions(type, clause) {
|
|
261
173
|
const andGroups = clause.split(/\bAND\b/i);
|
|
262
174
|
andGroups.forEach((andGroup) => {
|
|
@@ -270,29 +182,14 @@ var Parser = class {
|
|
|
270
182
|
}
|
|
271
183
|
});
|
|
272
184
|
}
|
|
273
|
-
/**
|
|
274
|
-
* Handle GROUP BY statements
|
|
275
|
-
* @param clause The clauses after the GROUP BY
|
|
276
|
-
* @private
|
|
277
|
-
*/
|
|
278
185
|
_handleGROUP_BY(clause) {
|
|
279
186
|
const columns = clause.split(/\s*,\s*/);
|
|
280
187
|
columns.forEach((column) => this.query.groupBy(column));
|
|
281
188
|
}
|
|
282
|
-
/**
|
|
283
|
-
* Handle ORDER BY statements
|
|
284
|
-
* @param clause The clause after the ORDER BY
|
|
285
|
-
* @private
|
|
286
|
-
*/
|
|
287
189
|
_handleORDER_BY(clause) {
|
|
288
190
|
const columns = clause.split(/\s*,\s*/);
|
|
289
191
|
columns.forEach((column) => this.query.orderBy(column));
|
|
290
192
|
}
|
|
291
|
-
/**
|
|
292
|
-
* Handle LIMIT statements including "LIMIT #" and "LIMIT #, #"
|
|
293
|
-
* @param clause The clause after the LIMIT
|
|
294
|
-
* @private
|
|
295
|
-
*/
|
|
296
193
|
_handleLIMIT(clause) {
|
|
297
194
|
const offsetLimit = clause.match(/^(\d+|\?|:\w+)\s*,\s*(\d+|\?|:\w+)$/);
|
|
298
195
|
if (offsetLimit) {
|
|
@@ -303,26 +200,15 @@ var Parser = class {
|
|
|
303
200
|
this.query.limit(clause);
|
|
304
201
|
}
|
|
305
202
|
}
|
|
306
|
-
/**
|
|
307
|
-
* Handle OFFSET statements
|
|
308
|
-
* @param clause The number after the OFFSET
|
|
309
|
-
* @private
|
|
310
|
-
*/
|
|
311
203
|
_handleOFFSET(clause) {
|
|
312
204
|
clause = clause.replace(/^(\d+) ROWS$/i, "$1");
|
|
313
205
|
this.query.offset(clause);
|
|
314
206
|
}
|
|
315
|
-
/**
|
|
316
|
-
* Handle OFFSET statements
|
|
317
|
-
* @param clause The number after the OFFSET
|
|
318
|
-
* @private
|
|
319
|
-
*/
|
|
320
207
|
_handleFETCH_NEXT(clause) {
|
|
321
208
|
clause = clause.replace(/^(\d+) ROWS ONLY$/i, "$1");
|
|
322
209
|
this.query.limit(clause);
|
|
323
210
|
}
|
|
324
|
-
}
|
|
325
|
-
|
|
211
|
+
}
|
|
326
212
|
// src/substrCount/substrCount.ts
|
|
327
213
|
function substrCount(haystack, needle) {
|
|
328
214
|
let count = 0;
|
|
@@ -335,75 +221,22 @@ function substrCount(haystack, needle) {
|
|
|
335
221
|
}
|
|
336
222
|
|
|
337
223
|
// src/SelectBuilder/SelectBuilder.ts
|
|
338
|
-
var isNullish = (v) => v ===
|
|
224
|
+
var isNullish = (v) => v === undefined || v === null || v === false || isNaN(v);
|
|
339
225
|
var defaultEngine = "mysql";
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
* The list of values to bind to the query
|
|
343
|
-
* @private
|
|
344
|
-
*/
|
|
226
|
+
|
|
227
|
+
class SelectBuilder {
|
|
345
228
|
_bindings = [];
|
|
346
|
-
/**
|
|
347
|
-
* The list of strings to come immediately after "SELECT"
|
|
348
|
-
* and before column names
|
|
349
|
-
* @private
|
|
350
|
-
*/
|
|
351
229
|
_options = [];
|
|
352
|
-
/**
|
|
353
|
-
* The list of column names to select
|
|
354
|
-
* @private
|
|
355
|
-
*/
|
|
356
230
|
_tables = [];
|
|
357
|
-
/**
|
|
358
|
-
* The list of tables in the FROM clause
|
|
359
|
-
* @private
|
|
360
|
-
*/
|
|
361
231
|
_columns = [];
|
|
362
|
-
/**
|
|
363
|
-
* The list of JOIN strings to add
|
|
364
|
-
* @private
|
|
365
|
-
*/
|
|
366
232
|
_joins = [];
|
|
367
|
-
/**
|
|
368
|
-
* The list of WHERE clauses to join with AND
|
|
369
|
-
* @private
|
|
370
|
-
*/
|
|
371
233
|
_wheres = [];
|
|
372
|
-
/**
|
|
373
|
-
* The list of GROUP BY clauses to join with commas
|
|
374
|
-
* @private
|
|
375
|
-
*/
|
|
376
234
|
_groupBys = [];
|
|
377
|
-
/**
|
|
378
|
-
* The list of HAVING clauses to join with AND
|
|
379
|
-
* @private
|
|
380
|
-
*/
|
|
381
235
|
_havings = [];
|
|
382
|
-
/**
|
|
383
|
-
* The list of ORDER BY clauses to join with commas
|
|
384
|
-
* @private
|
|
385
|
-
*/
|
|
386
236
|
_orderBys = [];
|
|
387
|
-
/**
|
|
388
|
-
* The LIMIT to use
|
|
389
|
-
* @private
|
|
390
|
-
*/
|
|
391
237
|
_limit;
|
|
392
|
-
/**
|
|
393
|
-
* The OFFSET to use
|
|
394
|
-
* @private
|
|
395
|
-
*/
|
|
396
238
|
_offset;
|
|
397
|
-
/**
|
|
398
|
-
* The page used to construct an OFFSET based on the LIMIT
|
|
399
|
-
* @private
|
|
400
|
-
*/
|
|
401
239
|
_page;
|
|
402
|
-
/**
|
|
403
|
-
* Select constructor
|
|
404
|
-
* @param [sql] A base SQL query to parse
|
|
405
|
-
* @param [bindings] Placeholders to bind to the query
|
|
406
|
-
*/
|
|
407
240
|
constructor(sql = null, bindings = null) {
|
|
408
241
|
if (sql) {
|
|
409
242
|
if (bindings) {
|
|
@@ -417,33 +250,32 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
417
250
|
new Parser(this).parse(sql);
|
|
418
251
|
}
|
|
419
252
|
}
|
|
420
|
-
/**
|
|
421
|
-
* Set the default database engine style (mssql, mysql, oracle, pg)
|
|
422
|
-
* @param engine
|
|
423
|
-
*/
|
|
424
253
|
static setDefaultEngine(engine) {
|
|
425
254
|
defaultEngine = engine;
|
|
426
|
-
return
|
|
255
|
+
return SelectBuilder;
|
|
427
256
|
}
|
|
428
|
-
/**
|
|
429
|
-
* Get the SQL as a pretty-printed string alongside an array of bindings
|
|
430
|
-
* @param engine The database engine style (mssql, mysql, oracle, pg)
|
|
431
|
-
* @return The SQL query as a string
|
|
432
|
-
*/
|
|
433
257
|
compile({
|
|
434
258
|
engine = defaultEngine,
|
|
435
259
|
bindingIndex = 1
|
|
436
260
|
} = {}) {
|
|
437
261
|
const lines = [
|
|
438
262
|
"SELECT",
|
|
439
|
-
this._options.length ? ` ${this._options.join(
|
|
440
|
-
|
|
263
|
+
this._options.length ? ` ${this._options.join(`
|
|
264
|
+
`)}` : null,
|
|
265
|
+
this._columns.length ? ` ${this._columns.join(`,
|
|
266
|
+
`)}` : ` *
|
|
267
|
+
`,
|
|
441
268
|
`FROM ${this._tables.join(", ")}`,
|
|
442
|
-
this._joins.length ? this._joins.join(
|
|
443
|
-
|
|
444
|
-
this.
|
|
445
|
-
|
|
446
|
-
this.
|
|
269
|
+
this._joins.length ? this._joins.join(`
|
|
270
|
+
`) : null,
|
|
271
|
+
this._wheres.length ? `WHERE ${this._wheres.join(`
|
|
272
|
+
AND `)}` : null,
|
|
273
|
+
this._groupBys.length ? `GROUP BY ${this._groupBys.join(`,
|
|
274
|
+
`)}` : null,
|
|
275
|
+
this._havings.length ? `HAVING ${this._havings.join(`
|
|
276
|
+
AND `)}` : null,
|
|
277
|
+
this._orderBys.length ? `ORDER BY ${this._orderBys.join(`,
|
|
278
|
+
`)}` : null
|
|
447
279
|
];
|
|
448
280
|
if (this._page > 0) {
|
|
449
281
|
const offset = (this._page - 1) * this._limit;
|
|
@@ -457,7 +289,8 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
457
289
|
lines.push(this._compileLIMIT(engine, this._limit));
|
|
458
290
|
}
|
|
459
291
|
}
|
|
460
|
-
const pretty = lines.filter(Boolean).join(
|
|
292
|
+
const pretty = lines.filter(Boolean).join(`
|
|
293
|
+
`).trim();
|
|
461
294
|
let replacer;
|
|
462
295
|
const bindings = [];
|
|
463
296
|
if (engine === "pg") {
|
|
@@ -489,11 +322,6 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
489
322
|
return `OFFSET ${offset} ROWS`;
|
|
490
323
|
}
|
|
491
324
|
}
|
|
492
|
-
/**
|
|
493
|
-
* Get SQL needed to return the found rows of this query
|
|
494
|
-
* @param engineStyle The database engine style (mssql, mysql, oracle, pg)
|
|
495
|
-
* @param countExpr The expression to use inside the COUNT()
|
|
496
|
-
*/
|
|
497
325
|
compileCount({
|
|
498
326
|
countExpr = "*",
|
|
499
327
|
engine = defaultEngine,
|
|
@@ -504,7 +332,8 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
504
332
|
if (this._havings.length === 0) {
|
|
505
333
|
return { sql, bindings };
|
|
506
334
|
} else {
|
|
507
|
-
const subquerySql = sql.replace(/\n/g,
|
|
335
|
+
const subquerySql = sql.replace(/\n/g, `
|
|
336
|
+
`);
|
|
508
337
|
return {
|
|
509
338
|
sql: `SELECT COUNT(*) AS found_rows
|
|
510
339
|
FROM (
|
|
@@ -514,11 +343,6 @@ ${subquerySql}
|
|
|
514
343
|
};
|
|
515
344
|
}
|
|
516
345
|
}
|
|
517
|
-
/**
|
|
518
|
-
* Get SQL needed to union this query with another
|
|
519
|
-
* @param query The query to union
|
|
520
|
-
* @param engine The database engine style (mssql, mysql, oracle, pg)
|
|
521
|
-
*/
|
|
522
346
|
compileUnion(query, {
|
|
523
347
|
engine = defaultEngine,
|
|
524
348
|
bindingIndex = 1
|
|
@@ -535,11 +359,6 @@ UNION
|
|
|
535
359
|
bindings: [...first.bindings, ...second.bindings]
|
|
536
360
|
};
|
|
537
361
|
}
|
|
538
|
-
/**
|
|
539
|
-
* @param [fieldOrFields] If given, reset the given component(s), otherwise reset all query components
|
|
540
|
-
* Valid components: option, column, table, where, orWhere, having, groupBy, orderBy, limit, offset, page
|
|
541
|
-
* @return This object
|
|
542
|
-
*/
|
|
543
362
|
reset(fieldOrFields = null) {
|
|
544
363
|
if (Array.isArray(fieldOrFields)) {
|
|
545
364
|
fieldOrFields.forEach((name) => this.reset(name));
|
|
@@ -577,11 +396,8 @@ UNION
|
|
|
577
396
|
}
|
|
578
397
|
return this;
|
|
579
398
|
}
|
|
580
|
-
/**
|
|
581
|
-
* Clone this builder object
|
|
582
|
-
*/
|
|
583
399
|
getClone() {
|
|
584
|
-
const copy = new
|
|
400
|
+
const copy = new SelectBuilder;
|
|
585
401
|
copy._options = [...this._options];
|
|
586
402
|
copy._columns = [...this._columns];
|
|
587
403
|
copy._tables = [...this._tables];
|
|
@@ -596,10 +412,6 @@ UNION
|
|
|
596
412
|
copy._bindings = [...this._bindings];
|
|
597
413
|
return copy;
|
|
598
414
|
}
|
|
599
|
-
/**
|
|
600
|
-
* Build a version of this query that simply returns COUNT(*)
|
|
601
|
-
* @param [countExpr="*"] Use to specify `DISTINCT colname` if needed
|
|
602
|
-
*/
|
|
603
415
|
getFoundRowsQuery(countExpr = "*") {
|
|
604
416
|
if (this._havings.length === 0) {
|
|
605
417
|
const clone = this.getClone();
|
|
@@ -619,74 +431,34 @@ UNION
|
|
|
619
431
|
return subquery;
|
|
620
432
|
}
|
|
621
433
|
}
|
|
622
|
-
/**
|
|
623
|
-
* Add an array of column names to fetch
|
|
624
|
-
* @param columnNames The names of columns
|
|
625
|
-
*/
|
|
626
434
|
select(columnNames) {
|
|
627
435
|
this._columns = this._columns.concat(columnNames);
|
|
628
436
|
return this;
|
|
629
437
|
}
|
|
630
|
-
/**
|
|
631
|
-
* Add an array of column names to fetch
|
|
632
|
-
* @param columnNames The names of columns
|
|
633
|
-
*/
|
|
634
438
|
columns(columnNames) {
|
|
635
439
|
this._columns = this._columns.concat(columnNames);
|
|
636
440
|
return this;
|
|
637
441
|
}
|
|
638
|
-
/**
|
|
639
|
-
* Add a column name to fetch
|
|
640
|
-
* @param columnName The name of the column
|
|
641
|
-
*/
|
|
642
442
|
column(columnName) {
|
|
643
443
|
this._columns.push(columnName);
|
|
644
444
|
return this;
|
|
645
445
|
}
|
|
646
|
-
/**
|
|
647
|
-
* Add an option expression such as "TOP 10" or "SQL_CALC_FOUND_ROWS"
|
|
648
|
-
* @param optionExpression Expression to go after "SELECT" and before column list
|
|
649
|
-
*/
|
|
650
446
|
option(optionExpression) {
|
|
651
447
|
this._options.push(optionExpression);
|
|
652
448
|
return this;
|
|
653
449
|
}
|
|
654
|
-
/**
|
|
655
|
-
* Add a table to the "FROM" clause (same as .from())
|
|
656
|
-
* @param {String} tableName The name of the table to query
|
|
657
|
-
* @return {Select}
|
|
658
|
-
*/
|
|
659
450
|
table(tableName) {
|
|
660
451
|
this._tables.push(tableName);
|
|
661
452
|
return this;
|
|
662
453
|
}
|
|
663
|
-
/**
|
|
664
|
-
* Add multiple table to the "FROM" clause
|
|
665
|
-
* @param {Array} tableNames The names of the tables to query
|
|
666
|
-
* @return {Select}
|
|
667
|
-
*/
|
|
668
454
|
tables(tableNames) {
|
|
669
455
|
this._tables.push(...tableNames);
|
|
670
456
|
return this;
|
|
671
457
|
}
|
|
672
|
-
/**
|
|
673
|
-
* Add a table to the "FROM" clause (same as .table())
|
|
674
|
-
* @param {String} tableName The name of the table to query
|
|
675
|
-
* @return {Select}
|
|
676
|
-
*/
|
|
677
458
|
from(tableName) {
|
|
678
459
|
this._tables.push(tableName);
|
|
679
460
|
return this;
|
|
680
461
|
}
|
|
681
|
-
/**
|
|
682
|
-
* Add the given join type expression
|
|
683
|
-
* @param joinType The type of join (e.g. "INNER JOIN", "LEFT JOIN", etc.)
|
|
684
|
-
* @param expression The expression following the INNER JOIN keyword
|
|
685
|
-
* @param bindings A list of values to bind to ? placeholders in the expression
|
|
686
|
-
* @example
|
|
687
|
-
* query.join('posts p ON p.id = c.post_id');
|
|
688
|
-
* query.join('posts p ON p.id = c.post_id AND p.deleted_at < ?', [myDate]);
|
|
689
|
-
*/
|
|
690
462
|
_addJoin(joinType, expression, bindings = []) {
|
|
691
463
|
if (bindings.length > 0) {
|
|
692
464
|
expression = expression.replace(/\?/g, () => {
|
|
@@ -696,118 +468,42 @@ UNION
|
|
|
696
468
|
}
|
|
697
469
|
this._joins.push(`${joinType} ${expression}`);
|
|
698
470
|
}
|
|
699
|
-
/**
|
|
700
|
-
* Add a JOIN expression
|
|
701
|
-
* @param expression The expression following the INNER JOIN keyword
|
|
702
|
-
* @param bindings A list of values to bind to ? placeholders in the expression
|
|
703
|
-
* @example
|
|
704
|
-
* query.join('posts p ON p.id = c.post_id');
|
|
705
|
-
* query.join('posts p ON p.id = c.post_id AND p.deleted_at < ?', [myDate]);
|
|
706
|
-
*/
|
|
707
471
|
join(expression, bindings = []) {
|
|
708
472
|
this._addJoin("JOIN", expression, bindings);
|
|
709
473
|
return this;
|
|
710
474
|
}
|
|
711
|
-
/**
|
|
712
|
-
* Add a LEFT JOIN expression
|
|
713
|
-
* @param expression The expression following the LEFT JOIN keyword
|
|
714
|
-
* @param bindings A list of values to bind to ? placeholders in the expression
|
|
715
|
-
* @example
|
|
716
|
-
* query.leftJoin('posts p ON p.id = c.post_id');
|
|
717
|
-
* query.leftJoin('posts p ON p.id = c.post_id AND p.deleted_at < ?', [myDate]);
|
|
718
|
-
*/
|
|
719
475
|
leftJoin(expression, bindings = []) {
|
|
720
476
|
this._addJoin("LEFT JOIN", expression, bindings);
|
|
721
477
|
return this;
|
|
722
478
|
}
|
|
723
|
-
/**
|
|
724
|
-
* Add a FULL JOIN expression
|
|
725
|
-
* @param expression The expression following the FULL JOIN keyword
|
|
726
|
-
* @param bindings A list of values to bind to ? placeholders in the expression
|
|
727
|
-
* @example
|
|
728
|
-
* query.fullJoin('posts p ON p.id = c.post_id');
|
|
729
|
-
* query.fullJoin('posts p ON p.id = c.post_id AND p.deleted_at < ?', [myDate]);
|
|
730
|
-
*/
|
|
731
479
|
fullJoin(expression, bindings = []) {
|
|
732
480
|
this._addJoin("FULL JOIN", expression, bindings);
|
|
733
481
|
return this;
|
|
734
482
|
}
|
|
735
|
-
/**
|
|
736
|
-
* Add a RIGHT JOIN expression
|
|
737
|
-
* @param expression The expression following the RIGHT JOIN keyword
|
|
738
|
-
* @param bindings A list of values to bind to ? placeholders in the expression
|
|
739
|
-
* @example
|
|
740
|
-
* query.rightJoin('posts p ON p.id = c.post_id');
|
|
741
|
-
* query.rightJoin('posts p ON p.id = c.post_id AND p.deleted_at < ?', [myDate]);
|
|
742
|
-
*/
|
|
743
483
|
rightJoin(expression, bindings = []) {
|
|
744
484
|
this._addJoin("RIGHT JOIN", expression, bindings);
|
|
745
485
|
return this;
|
|
746
486
|
}
|
|
747
|
-
/**
|
|
748
|
-
* Add a CROSS JOIN expression
|
|
749
|
-
* @param expression The expression following the CROSS JOIN keyword
|
|
750
|
-
* @param bindings A list of values to bind to ? placeholders in the expression
|
|
751
|
-
* @example
|
|
752
|
-
* query.crossJoin('posts p ON p.id = c.post_id');
|
|
753
|
-
* query.crossJoin('posts p ON p.id = c.post_id AND p.deleted_at < ?', [myDate]);
|
|
754
|
-
*/
|
|
755
487
|
crossJoin(expression, bindings = []) {
|
|
756
488
|
this._addJoin("CROSS JOIN", expression, bindings);
|
|
757
489
|
return this;
|
|
758
490
|
}
|
|
759
|
-
/**
|
|
760
|
-
* Add an INNER JOIN expression (same as ->join())
|
|
761
|
-
* @param expression The expression following the INNER JOIN keyword
|
|
762
|
-
* @param bindings A list of values to bind to ? placeholders in the expression
|
|
763
|
-
* @example
|
|
764
|
-
* query.innerJoin('posts p ON p.id = c.post_id');
|
|
765
|
-
* query.innerJoin('posts p ON p.id = c.post_id AND p.deleted_at < ?', [myDate]);
|
|
766
|
-
*/
|
|
767
491
|
innerJoin(expression, bindings = []) {
|
|
768
492
|
this._addJoin("INNER JOIN", expression, bindings);
|
|
769
493
|
return this;
|
|
770
494
|
}
|
|
771
|
-
/**
|
|
772
|
-
* Add a LEFT OUTER JOIN expression
|
|
773
|
-
* @param expression The expression following the LEFT OUTER JOIN keyword
|
|
774
|
-
* @param bindings A list of values to bind to ? placeholders in the expression
|
|
775
|
-
* @example
|
|
776
|
-
* query.leftOuterJoin('posts p ON p.id = c.post_id');
|
|
777
|
-
* query.leftOuterJoin('posts p ON p.id = c.post_id AND p.deleted_at < ?', [myDate]);
|
|
778
|
-
*/
|
|
779
495
|
leftOuterJoin(expression, bindings = []) {
|
|
780
496
|
this._addJoin("LEFT OUTER JOIN", expression, bindings);
|
|
781
497
|
return this;
|
|
782
498
|
}
|
|
783
|
-
/**
|
|
784
|
-
* Add a FULL OUTER JOIN expression
|
|
785
|
-
* @param expression The expression following the FULL OUTER JOIN keyword
|
|
786
|
-
* @param bindings A list of values to bind to ? placeholders in the expression
|
|
787
|
-
* @example
|
|
788
|
-
* query.fullOuterJoin('posts p ON p.id = c.post_id');
|
|
789
|
-
* query.fullOuterJoin('posts p ON p.id = c.post_id AND p.deleted_at < ?', [myDate]);
|
|
790
|
-
*/
|
|
791
499
|
fullOuterJoin(expression, bindings = []) {
|
|
792
500
|
this._addJoin("FULL OUTER JOIN", expression, bindings);
|
|
793
501
|
return this;
|
|
794
502
|
}
|
|
795
|
-
/**
|
|
796
|
-
* Add a RIGHT OUTER JOIN expression
|
|
797
|
-
* @param expression The expression following the RIGHT OUTER JOIN keyword
|
|
798
|
-
* @param bindings A list of values to bind to ? placeholders in the expression
|
|
799
|
-
* @example
|
|
800
|
-
* query.rightOuterJoin('posts p ON p.id = c.post_id');
|
|
801
|
-
* query.rightOuterJoin('posts p ON p.id = c.post_id AND p.deleted_at < ?', [myDate]);
|
|
802
|
-
*/
|
|
803
503
|
rightOuterJoin(expression, bindings = []) {
|
|
804
504
|
this._addJoin("RIGHT OUTER JOIN", expression, bindings);
|
|
805
505
|
return this;
|
|
806
506
|
}
|
|
807
|
-
/**
|
|
808
|
-
* Remove a join condition with the specified table
|
|
809
|
-
* @param table The name of the table or tables in the first part of the join statement
|
|
810
|
-
*/
|
|
811
507
|
unjoin(table) {
|
|
812
508
|
if (Array.isArray(table)) {
|
|
813
509
|
table.forEach((t) => this.unjoin(t));
|
|
@@ -819,34 +515,6 @@ UNION
|
|
|
819
515
|
});
|
|
820
516
|
return this;
|
|
821
517
|
}
|
|
822
|
-
/**
|
|
823
|
-
* Utility function to add conditions for a clause (WHERE, HAVING)
|
|
824
|
-
* @param collection The collection to add the clauses to (e.g. this._wheres or this._havings)
|
|
825
|
-
* @param criteria Criteria adhering to WhereCriteria type
|
|
826
|
-
* @example The following are equivalent
|
|
827
|
-
* this._conditions(this._wheres, ['deleted_at IS NULL']);
|
|
828
|
-
* this._conditions(this._wheres, ['deleted_at', null]);
|
|
829
|
-
* this._conditions(this._wheres, ['deleted_at', '=', null]);
|
|
830
|
-
* @example More examples
|
|
831
|
-
* this._conditions(this._wheres, ['fname', 'LIKE', 'joe']); // `fname` LIKE 'joe'
|
|
832
|
-
* this._conditions(this._wheres, ['fname', 'LIKE ?', 'joe']); // `fname` LIKE 'joe'
|
|
833
|
-
* this._conditions(this._wheres, ['fname LIKE %?%', 'joe']); // `fname` LIKE '%joe%'
|
|
834
|
-
* this._conditions(this._wheres, ['fname LIKE ?%', 'joe']); // `fname` LIKE 'joe%'
|
|
835
|
-
* this._conditions(this._wheres, ['fname', 'LIKE ?%', 'joe']); // `fname` LIKE 'joe%'
|
|
836
|
-
* this._conditions(this._wheres, ['price >', 10]); // `price` > 10
|
|
837
|
-
* this._conditions(this._wheres, ['price', '>', 10]); // `price` > 10
|
|
838
|
-
* this._conditions(this._wheres, ['price =', 10]); // `price` = 10
|
|
839
|
-
* this._conditions(this._wheres, ['price !=', 10]); // `price` != 10
|
|
840
|
-
* this._conditions(this._wheres, ['price', 10]); // `price` = 10
|
|
841
|
-
* this._conditions(this._wheres, ['price', '=', 10]); // `price` = 10
|
|
842
|
-
* this._conditions(this._wheres, ['price', '!=', 10]); // `price` != 10
|
|
843
|
-
* this._conditions(this._wheres, ['price', 'BETWEEN', [10,20]]); // `price` BETWEEN 10 AND 20
|
|
844
|
-
* this._conditions(this._wheres, ['price', 'NOT BETWEEN', [10,20]]); // `price` NOT BETWEEN 10 AND 20
|
|
845
|
-
* this._conditions(this._wheres, ['price', [10,20]]); // `price` IN(10,20)
|
|
846
|
-
* this._conditions(this._wheres, ['price', '=', [10,20]]); // `price` IN(10,20)
|
|
847
|
-
* this._conditions(this._wheres, ['price', 'IN', [10,20]]); // `price` IN(10,20)
|
|
848
|
-
* this._conditions(this._wheres, ['price', 'NOT IN', [10,20]]); // `price` NOT IN(10,20)
|
|
849
|
-
*/
|
|
850
518
|
_conditions(collection, criteria) {
|
|
851
519
|
const numArgs = criteria.length;
|
|
852
520
|
let [column, operator, value] = criteria;
|
|
@@ -877,15 +545,11 @@ UNION
|
|
|
877
545
|
operator = "=";
|
|
878
546
|
}
|
|
879
547
|
operator = operator.toLocaleUpperCase();
|
|
880
|
-
const likeMatch = operator.match(
|
|
881
|
-
/^(LIKE|NOT LIKE|ILIKE|NOT ILIKE)(?: (\?|\?%|%\?|%\?%))?$/i
|
|
882
|
-
);
|
|
548
|
+
const likeMatch = operator.match(/^(LIKE|NOT LIKE|ILIKE|NOT ILIKE)(?: (\?|\?%|%\?|%\?%))?$/i);
|
|
883
549
|
if (operator === "NOT BETWEEN" || operator === "BETWEEN") {
|
|
884
550
|
const one = this._bindings.length;
|
|
885
551
|
const two = this._bindings.length + 1;
|
|
886
|
-
collection.push(
|
|
887
|
-
`${column} ${operator} __BOUND_${one}__ AND __BOUND_${two}__`
|
|
888
|
-
);
|
|
552
|
+
collection.push(`${column} ${operator} __BOUND_${one}__ AND __BOUND_${two}__`);
|
|
889
553
|
this._bindings.push(value[0], value[1]);
|
|
890
554
|
} else if (likeMatch) {
|
|
891
555
|
const like = likeMatch[1].toUpperCase();
|
|
@@ -903,52 +567,32 @@ UNION
|
|
|
903
567
|
this._bindings.push(infix.replace("?", value || ""));
|
|
904
568
|
}
|
|
905
569
|
} else if (value === null) {
|
|
906
|
-
collection.push(
|
|
907
|
-
operator === "=" ? `${column} IS NULL` : `${column} IS NOT NULL`
|
|
908
|
-
);
|
|
570
|
+
collection.push(operator === "=" ? `${column} IS NULL` : `${column} IS NOT NULL`);
|
|
909
571
|
} else if (Array.isArray(value)) {
|
|
910
572
|
const inVals = [];
|
|
911
|
-
for (let i = 0;
|
|
573
|
+
for (let i = 0;i < value.length; i++) {
|
|
912
574
|
inVals.push(`__BOUND_${this._bindings.length}__`);
|
|
913
575
|
this._bindings.push(value[i]);
|
|
914
576
|
}
|
|
915
577
|
const joined = inVals.join(", ");
|
|
916
|
-
collection.push(
|
|
917
|
-
operator === "=" || operator === "IN" ? `${column} IN(${joined})` : `${column} NOT IN(${joined})`
|
|
918
|
-
);
|
|
578
|
+
collection.push(operator === "=" || operator === "IN" ? `${column} IN(${joined})` : `${column} NOT IN(${joined})`);
|
|
919
579
|
} else if (operator === "IN" || operator === "NOT IN") {
|
|
920
|
-
collection.push(
|
|
921
|
-
`${column} ${operator}(__BOUND_${this._bindings.length}__)`
|
|
922
|
-
);
|
|
580
|
+
collection.push(`${column} ${operator}(__BOUND_${this._bindings.length}__)`);
|
|
923
581
|
this._bindings.push(value);
|
|
924
582
|
} else {
|
|
925
|
-
collection.push(
|
|
926
|
-
`${column} ${operator} __BOUND_${this._bindings.length}__`
|
|
927
|
-
);
|
|
583
|
+
collection.push(`${column} ${operator} __BOUND_${this._bindings.length}__`);
|
|
928
584
|
this._bindings.push(value);
|
|
929
585
|
}
|
|
930
586
|
return this;
|
|
931
587
|
}
|
|
932
|
-
/**
|
|
933
|
-
* Add a group by column or expression
|
|
934
|
-
* @param column The name of a column (or expression) to group by
|
|
935
|
-
*/
|
|
936
588
|
groupBy(column) {
|
|
937
589
|
this._groupBys.push(column);
|
|
938
590
|
return this;
|
|
939
591
|
}
|
|
940
|
-
/**
|
|
941
|
-
* Add WHERE clauses to conditions (See _conditions for usage)
|
|
942
|
-
*/
|
|
943
592
|
where(...args) {
|
|
944
593
|
this._conditions(this._wheres, args);
|
|
945
594
|
return this;
|
|
946
595
|
}
|
|
947
|
-
/**
|
|
948
|
-
* Add a WHERE clause with a BETWEEN condition
|
|
949
|
-
* @param column The column name
|
|
950
|
-
* @param twoValueArray The two values to be between
|
|
951
|
-
*/
|
|
952
596
|
whereBetween(column, twoValueArray) {
|
|
953
597
|
if (!isNullish(twoValueArray[0]) && !isNullish(twoValueArray[1])) {
|
|
954
598
|
this.where(column, "BETWEEN", twoValueArray);
|
|
@@ -956,14 +600,9 @@ UNION
|
|
|
956
600
|
this.where(column, ">=", twoValueArray[0]);
|
|
957
601
|
} else if (isNullish(twoValueArray[0]) && !isNullish(twoValueArray[1])) {
|
|
958
602
|
this.where(column, "<=", twoValueArray[1]);
|
|
959
|
-
} else {
|
|
960
|
-
}
|
|
603
|
+
} else {}
|
|
961
604
|
return this;
|
|
962
605
|
}
|
|
963
|
-
/**
|
|
964
|
-
* Add a series of WHERE clauses joined by OR (See _conditions for usage)
|
|
965
|
-
* @param conditions
|
|
966
|
-
*/
|
|
967
606
|
_orConditions(conditions) {
|
|
968
607
|
const items = [];
|
|
969
608
|
if (Array.isArray(conditions)) {
|
|
@@ -988,41 +627,20 @@ UNION
|
|
|
988
627
|
return joined;
|
|
989
628
|
}
|
|
990
629
|
}
|
|
991
|
-
/**
|
|
992
|
-
* Add WHERE conditions to place inside an OR block (See _conditions for usage)
|
|
993
|
-
* @param conditions A list or object where each item is an array with parameters that would be taken by where()
|
|
994
|
-
*/
|
|
995
630
|
orWhere(conditions) {
|
|
996
631
|
const joined = this._orConditions(conditions);
|
|
997
632
|
this.where(`(${joined})`);
|
|
998
633
|
return this;
|
|
999
634
|
}
|
|
1000
|
-
/**
|
|
1001
|
-
* Add an OR with conditions under the HAVING clause
|
|
1002
|
-
* @param conditions A list or object where each item is an array with parameters that would be taken by having()
|
|
1003
|
-
*/
|
|
1004
635
|
orHaving(conditions) {
|
|
1005
636
|
const joined = this._orConditions(conditions);
|
|
1006
637
|
this.having(`(${joined})`);
|
|
1007
638
|
return this;
|
|
1008
639
|
}
|
|
1009
|
-
/**
|
|
1010
|
-
* Add a HAVING condition (See _conditions for usage)
|
|
1011
|
-
*/
|
|
1012
640
|
having(...args) {
|
|
1013
641
|
this._conditions(this._havings, args);
|
|
1014
642
|
return this;
|
|
1015
643
|
}
|
|
1016
|
-
/**
|
|
1017
|
-
* Add a column or expression to order by
|
|
1018
|
-
* @param column The column name or expression to sort by. Include DESC or prefix with - to sort descending
|
|
1019
|
-
* @param [direction] The direction to sort by (ASC or DESC)
|
|
1020
|
-
* @example
|
|
1021
|
-
* query.sortField('modified_at'); // ORDER BY modified_at
|
|
1022
|
-
* query.sortField('-modified_at'); // ORDER BY modified_at DESC
|
|
1023
|
-
* query.sortField('COUNT(*)'); // ORDER BY COUNT(*)
|
|
1024
|
-
* query.sortField('COUNT(*) DESC'); // ORDER BY COUNT(*) DESC
|
|
1025
|
-
*/
|
|
1026
644
|
orderBy(column, direction = null) {
|
|
1027
645
|
if (direction) {
|
|
1028
646
|
this._orderBys.push(`${column} ${direction}`);
|
|
@@ -1032,14 +650,6 @@ UNION
|
|
|
1032
650
|
}
|
|
1033
651
|
return this;
|
|
1034
652
|
}
|
|
1035
|
-
/**
|
|
1036
|
-
* Sort by the given column, with a map of columns to translate
|
|
1037
|
-
* @param fieldName The file name such as "created_at" or "-created_at" for descending
|
|
1038
|
-
* @param [mapNames] Column names to translate from field to column expression
|
|
1039
|
-
* @example
|
|
1040
|
-
* query.sortField('-modified_at'); // ORDER BY modified_at DESC
|
|
1041
|
-
* query.sortField('-created', {'created': 'created_at'}); // ORDER BY created_at DESC
|
|
1042
|
-
*/
|
|
1043
653
|
sortField(fieldName, mapNames = {}) {
|
|
1044
654
|
let direction = "ASC";
|
|
1045
655
|
if (fieldName.startsWith("-")) {
|
|
@@ -1050,26 +660,12 @@ UNION
|
|
|
1050
660
|
this.orderBy(column, direction);
|
|
1051
661
|
return this;
|
|
1052
662
|
}
|
|
1053
|
-
/**
|
|
1054
|
-
* Check to see if the given string is 0 or all digits not starting with 0
|
|
1055
|
-
* @param string The input string
|
|
1056
|
-
* @private
|
|
1057
|
-
*/
|
|
1058
663
|
_isEntirelyDigits(string) {
|
|
1059
664
|
return /^(0|[1-9]\d*)$/.test(string);
|
|
1060
665
|
}
|
|
1061
|
-
/**
|
|
1062
|
-
* Check to see if the given string is all digits
|
|
1063
|
-
* @param string The input string
|
|
1064
|
-
* @private
|
|
1065
|
-
*/
|
|
1066
666
|
_isEntirelyDigitsNoZeros(string) {
|
|
1067
667
|
return /^[1-9]\d*$/.test(string);
|
|
1068
668
|
}
|
|
1069
|
-
/**
|
|
1070
|
-
* Limit results to the given number
|
|
1071
|
-
* @param max The number to limit by (placeholder string or integer greater than 0)
|
|
1072
|
-
*/
|
|
1073
669
|
limit(max) {
|
|
1074
670
|
if (typeof max === "string") {
|
|
1075
671
|
max = max.trim();
|
|
@@ -1079,55 +675,38 @@ UNION
|
|
|
1079
675
|
} else if (typeof max === "number" && Number.isInteger(max) && max >= 1) {
|
|
1080
676
|
this._limit = max;
|
|
1081
677
|
} else {
|
|
1082
|
-
throw new Error(
|
|
1083
|
-
`SelectBuilder: "limit(n)" must receive a positive integer (got "${max}")`
|
|
1084
|
-
);
|
|
678
|
+
throw new Error(`SelectBuilder: "limit(n)" must receive a positive integer (got "${max}")`);
|
|
1085
679
|
}
|
|
1086
680
|
return this;
|
|
1087
681
|
}
|
|
1088
|
-
/**
|
|
1089
|
-
* Fetch results from the given offset
|
|
1090
|
-
* @param number The offset (placeholder string or integer greater than or equal to 0)
|
|
1091
|
-
*/
|
|
1092
682
|
offset(number) {
|
|
1093
683
|
if (typeof number === "string" && this._isEntirelyDigits(number.trim())) {
|
|
1094
684
|
this._offset = parseInt(number, 10);
|
|
1095
685
|
} else if (typeof number === "number" && Number.isInteger(number) && number >= 0) {
|
|
1096
686
|
this._offset = number;
|
|
1097
687
|
} else {
|
|
1098
|
-
throw new Error(
|
|
1099
|
-
`SelectBuilder: "offset(n)" must receive a positive integer (got "${number}")`
|
|
1100
|
-
);
|
|
688
|
+
throw new Error(`SelectBuilder: "offset(n)" must receive a positive integer (got "${number}")`);
|
|
1101
689
|
}
|
|
1102
690
|
return this;
|
|
1103
691
|
}
|
|
1104
|
-
/**
|
|
1105
|
-
* Set the offset based on the limit with the given page number
|
|
1106
|
-
* @param number The page number (integer greater than 0)
|
|
1107
|
-
*/
|
|
1108
692
|
page(number) {
|
|
1109
693
|
if (typeof number === "string" && this._isEntirelyDigitsNoZeros(number.trim())) {
|
|
1110
694
|
this._page = parseInt(number, 10);
|
|
1111
695
|
} else if (typeof number === "number" && Number.isInteger(number) && number >= 1) {
|
|
1112
696
|
this._page = number;
|
|
1113
697
|
} else {
|
|
1114
|
-
throw new Error(
|
|
1115
|
-
'SelectBuilder: "page(n)" must receive a positive integer'
|
|
1116
|
-
);
|
|
698
|
+
throw new Error('SelectBuilder: "page(n)" must receive a positive integer');
|
|
1117
699
|
}
|
|
1118
700
|
return this;
|
|
1119
701
|
}
|
|
1120
|
-
}
|
|
1121
|
-
|
|
702
|
+
}
|
|
1122
703
|
// src/extractGrouped/extractGrouped.ts
|
|
1123
704
|
function extractGrouped(field, records) {
|
|
1124
705
|
let idx = 0;
|
|
1125
706
|
const grouped = {};
|
|
1126
707
|
for (const record of records) {
|
|
1127
708
|
if (!(field in record)) {
|
|
1128
|
-
throw new Error(
|
|
1129
|
-
`Column "${String(field)}" is not present in record ${idx}`
|
|
1130
|
-
);
|
|
709
|
+
throw new Error(`Column "${String(field)}" is not present in record ${idx}`);
|
|
1131
710
|
}
|
|
1132
711
|
if (!grouped[record[field]]) {
|
|
1133
712
|
grouped[record[field]] = [];
|
|
@@ -1137,44 +716,35 @@ function extractGrouped(field, records) {
|
|
|
1137
716
|
}
|
|
1138
717
|
return grouped;
|
|
1139
718
|
}
|
|
1140
|
-
|
|
1141
719
|
// src/extractIndexed/extractIndexed.ts
|
|
1142
720
|
function extractIndexed(field, records) {
|
|
1143
721
|
let idx = 0;
|
|
1144
722
|
const indexed = {};
|
|
1145
723
|
for (const record of records) {
|
|
1146
724
|
if (!(field in record)) {
|
|
1147
|
-
throw new Error(
|
|
1148
|
-
`Column "${String(field)}" is not present in record ${idx}`
|
|
1149
|
-
);
|
|
725
|
+
throw new Error(`Column "${String(field)}" is not present in record ${idx}`);
|
|
1150
726
|
}
|
|
1151
727
|
indexed[record[field]] = record;
|
|
1152
728
|
idx++;
|
|
1153
729
|
}
|
|
1154
730
|
return indexed;
|
|
1155
731
|
}
|
|
1156
|
-
|
|
1157
732
|
// src/extractLookup/extractLookup.ts
|
|
1158
733
|
function extractLookup(keyField, valueField, records) {
|
|
1159
734
|
const lookup = {};
|
|
1160
735
|
let idx = 0;
|
|
1161
736
|
for (const record of records) {
|
|
1162
737
|
if (!(keyField in record)) {
|
|
1163
|
-
throw new Error(
|
|
1164
|
-
`Column "${String(keyField)}" is not present in record ${idx}`
|
|
1165
|
-
);
|
|
738
|
+
throw new Error(`Column "${String(keyField)}" is not present in record ${idx}`);
|
|
1166
739
|
}
|
|
1167
740
|
if (!(valueField in record)) {
|
|
1168
|
-
throw new Error(
|
|
1169
|
-
`Column "${String(valueField)}" is not present in record ${idx}`
|
|
1170
|
-
);
|
|
741
|
+
throw new Error(`Column "${String(valueField)}" is not present in record ${idx}`);
|
|
1171
742
|
}
|
|
1172
743
|
idx++;
|
|
1173
744
|
lookup[String(record[keyField])] = record[valueField];
|
|
1174
745
|
}
|
|
1175
746
|
return lookup;
|
|
1176
747
|
}
|
|
1177
|
-
|
|
1178
748
|
// src/getPagination/getPagination.ts
|
|
1179
749
|
function getPagination(query, total) {
|
|
1180
750
|
total = Number(total) || 0;
|
|
@@ -1207,7 +777,6 @@ function getPagination(query, total) {
|
|
|
1207
777
|
isLast
|
|
1208
778
|
};
|
|
1209
779
|
}
|
|
1210
|
-
|
|
1211
780
|
// src/runMysql/runMysql.ts
|
|
1212
781
|
function _queryToPromise(mysqlClient, sql, bindings) {
|
|
1213
782
|
return new Promise((resolve, reject) => {
|
|
@@ -1258,7 +827,6 @@ async function runMysqlAsyncWithCount(mysqlClient, query, {
|
|
|
1258
827
|
return { records, total: 0, pagination: getPagination(query, 0), fields };
|
|
1259
828
|
}
|
|
1260
829
|
}
|
|
1261
|
-
|
|
1262
830
|
// src/toSafeJson/toSafeJson.ts
|
|
1263
831
|
function toSafeJsonValue(value) {
|
|
1264
832
|
if (typeof value === "bigint") {
|
|
@@ -1285,19 +853,16 @@ function toSafeJsonString(records) {
|
|
|
1285
853
|
}
|
|
1286
854
|
|
|
1287
855
|
// src/runPrisma/runPrisma.ts
|
|
1288
|
-
async function runPrisma(prisma, query, { engine =
|
|
856
|
+
async function runPrisma(prisma, query, { engine = undefined } = {}) {
|
|
1289
857
|
const { sql, bindings } = query.compile({ engine });
|
|
1290
858
|
return prisma.$queryRawUnsafe(sql, ...bindings);
|
|
1291
859
|
}
|
|
1292
860
|
async function runPrismaWithCount(prisma, query, {
|
|
1293
|
-
engine =
|
|
861
|
+
engine = undefined,
|
|
1294
862
|
countExpr = "*"
|
|
1295
863
|
} = {}) {
|
|
1296
864
|
const { sql, bindings } = query.compile({ engine });
|
|
1297
|
-
const records = await prisma.$queryRawUnsafe(
|
|
1298
|
-
sql,
|
|
1299
|
-
...bindings
|
|
1300
|
-
);
|
|
865
|
+
const records = await prisma.$queryRawUnsafe(sql, ...bindings);
|
|
1301
866
|
if (records.length > 0) {
|
|
1302
867
|
const { sql: sql2, bindings: bindings2 } = query.compileCount({ engine, countExpr });
|
|
1303
868
|
const result = await prisma.$queryRawUnsafe(sql2, ...bindings2);
|
|
@@ -1307,22 +872,3 @@ async function runPrismaWithCount(prisma, query, {
|
|
|
1307
872
|
return { records, total: 0, pagination: getPagination(query, 0) };
|
|
1308
873
|
}
|
|
1309
874
|
}
|
|
1310
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
1311
|
-
0 && (module.exports = {
|
|
1312
|
-
Parser,
|
|
1313
|
-
SelectBuilder,
|
|
1314
|
-
extractGrouped,
|
|
1315
|
-
extractIndexed,
|
|
1316
|
-
extractLookup,
|
|
1317
|
-
getPagination,
|
|
1318
|
-
runMysql,
|
|
1319
|
-
runMysqlAsync,
|
|
1320
|
-
runMysqlAsyncWithCount,
|
|
1321
|
-
runMysqlWithCount,
|
|
1322
|
-
runPrisma,
|
|
1323
|
-
runPrismaWithCount,
|
|
1324
|
-
toSafeJsonRecord,
|
|
1325
|
-
toSafeJsonRecords,
|
|
1326
|
-
toSafeJsonString,
|
|
1327
|
-
toSafeJsonValue
|
|
1328
|
-
});
|