leoric 2.6.1 → 2.6.2
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/package.json +1 -1
- package/src/constants.js +5 -2
- package/src/drivers/abstract/spellbook.js +12 -10
- package/src/expr_formatter.js +27 -1
- package/types/index.d.ts +10 -5
package/package.json
CHANGED
package/src/constants.js
CHANGED
|
@@ -8,6 +8,8 @@ const AGGREGATOR_MAP = {
|
|
|
8
8
|
sum: 'sum'
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
const AGGREGATORS = Object.values(AGGREGATOR_MAP);
|
|
12
|
+
|
|
11
13
|
const LEGACY_TIMESTAMP_MAP = {
|
|
12
14
|
gmtCreate: 'createdAt',
|
|
13
15
|
gmtModified: 'updatedAt',
|
|
@@ -20,7 +22,7 @@ const LEGACY_TIMESTAMP_COLUMN_MAP = {
|
|
|
20
22
|
deleted_at: 'gmt_deleted',
|
|
21
23
|
};
|
|
22
24
|
|
|
23
|
-
const TIMESTAMP_ATTRIBUTE_NAMES = [
|
|
25
|
+
const TIMESTAMP_ATTRIBUTE_NAMES = [
|
|
24
26
|
'createdAt', 'updatedAt', 'deletedAt',
|
|
25
27
|
'gmtCreate', 'gmtModified', 'gmtDeleted',
|
|
26
28
|
'created_at', 'updated_at', 'deleted_at',
|
|
@@ -40,5 +42,6 @@ module.exports = {
|
|
|
40
42
|
TIMESTAMP_NAMES,
|
|
41
43
|
LEGACY_TIMESTAMP_COLUMN_MAP,
|
|
42
44
|
ASSOCIATE_METADATA_MAP,
|
|
43
|
-
TIMESTAMP_ATTRIBUTE_NAMES
|
|
45
|
+
TIMESTAMP_ATTRIBUTE_NAMES,
|
|
46
|
+
AGGREGATORS,
|
|
44
47
|
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const SqlString = require('sqlstring');
|
|
4
4
|
|
|
5
5
|
const { copyExpr, findExpr, walkExpr } = require('../../expr');
|
|
6
|
-
const { formatExpr, formatConditions, collectLiteral } = require('../../expr_formatter');
|
|
6
|
+
const { formatExpr, formatConditions, collectLiteral, isAggregatorExpr } = require('../../expr_formatter');
|
|
7
7
|
const Raw = require('../../raw');
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -91,10 +91,12 @@ function formatSelectExpr(spell, values) {
|
|
|
91
91
|
const baseName = Model.tableAlias;
|
|
92
92
|
const selects = new Set();
|
|
93
93
|
const map = {};
|
|
94
|
+
let isAggregate = false;
|
|
94
95
|
|
|
95
96
|
for (const token of columns) {
|
|
96
97
|
collectLiteral(spell, token, values);
|
|
97
98
|
const selectExpr = formatExpr(spell, token);
|
|
99
|
+
isAggregate = isAggregate || isAggregatorExpr(spell, token);
|
|
98
100
|
const qualifier = token.qualifiers ? token.qualifiers[0] : '';
|
|
99
101
|
const list = map[qualifier] || (map[qualifier] = []);
|
|
100
102
|
list.push(selectExpr);
|
|
@@ -104,7 +106,7 @@ function formatSelectExpr(spell, values) {
|
|
|
104
106
|
const list = map[qualifier];
|
|
105
107
|
if (list) {
|
|
106
108
|
for (const selectExpr of list) selects.add(selectExpr);
|
|
107
|
-
} else if (groups.length === 0 && Model.driver.type !== 'sqlite') {
|
|
109
|
+
} else if (groups.length === 0 && Model.driver.type !== 'sqlite' && !isAggregate) {
|
|
108
110
|
selects.add(`${escapeId(qualifier)}.*`);
|
|
109
111
|
}
|
|
110
112
|
}
|
|
@@ -163,7 +165,7 @@ class SpellBook {
|
|
|
163
165
|
const { escapeId } = Model.driver;
|
|
164
166
|
let columns = [];
|
|
165
167
|
let updateOnDuplicateColumns = [];
|
|
166
|
-
|
|
168
|
+
|
|
167
169
|
let values = [];
|
|
168
170
|
let placeholders = [];
|
|
169
171
|
if (Array.isArray(sets)) {
|
|
@@ -181,14 +183,14 @@ class SpellBook {
|
|
|
181
183
|
columnAttributes.push(Model.columnAttributes[name]);
|
|
182
184
|
}
|
|
183
185
|
}
|
|
184
|
-
|
|
186
|
+
|
|
185
187
|
for (const entry of columnAttributes) {
|
|
186
188
|
columns.push(entry.columnName);
|
|
187
|
-
if (updateOnDuplicate && createdAt && entry.name === createdAt
|
|
189
|
+
if (updateOnDuplicate && createdAt && entry.name === createdAt
|
|
188
190
|
&& !(Array.isArray(updateOnDuplicate) && updateOnDuplicate.includes(createdAt))) continue;
|
|
189
191
|
updateOnDuplicateColumns.push(entry.columnName);
|
|
190
192
|
}
|
|
191
|
-
|
|
193
|
+
|
|
192
194
|
for (const entry of sets) {
|
|
193
195
|
if (shardingKey && entry[shardingKey] == null) {
|
|
194
196
|
throw new Error(`Sharding key ${Model.table}.${shardingKey} cannot be NULL.`);
|
|
@@ -199,7 +201,7 @@ class SpellBook {
|
|
|
199
201
|
}
|
|
200
202
|
placeholders.push(`(${new Array(columnAttributes.length).fill('?').join(',')})`);
|
|
201
203
|
}
|
|
202
|
-
|
|
204
|
+
|
|
203
205
|
} else {
|
|
204
206
|
if (shardingKey && sets[shardingKey] == null) {
|
|
205
207
|
throw new Error(`Sharding key ${Model.table}.${shardingKey} cannot be NULL.`);
|
|
@@ -216,10 +218,10 @@ class SpellBook {
|
|
|
216
218
|
updateOnDuplicateColumns.push(Model.unalias(name));
|
|
217
219
|
}
|
|
218
220
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
+
|
|
222
|
+
|
|
221
223
|
const chunks = ['INSERT'];
|
|
222
|
-
|
|
224
|
+
|
|
223
225
|
// see https://dev.mysql.com/doc/refman/8.0/en/optimizer-hints.html
|
|
224
226
|
const hintStr = this.formatOptimizerHints(spell);
|
|
225
227
|
if (hintStr) {
|
package/src/expr_formatter.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { precedes, walkExpr } = require('./expr');
|
|
4
|
+
const { AGGREGATORS } = require('./constants');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Find model by qualifiers.
|
|
@@ -65,6 +66,31 @@ function formatLiteral(spell, ast) {
|
|
|
65
66
|
return '?';
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Format the abstract syntax tree of an expression into escaped string.
|
|
71
|
+
* @param {Spell} spell
|
|
72
|
+
* @param {Object} ast
|
|
73
|
+
*/
|
|
74
|
+
function isAggregatorExpr(spell, ast) {
|
|
75
|
+
const { type, name, args } = ast;
|
|
76
|
+
switch (type) {
|
|
77
|
+
case 'literal':
|
|
78
|
+
case 'subquery':
|
|
79
|
+
case 'wildcard':
|
|
80
|
+
case 'mod':
|
|
81
|
+
case 'id':
|
|
82
|
+
case 'raw':
|
|
83
|
+
case 'op':
|
|
84
|
+
return false;
|
|
85
|
+
case 'alias':
|
|
86
|
+
return isAggregatorExpr(spell, args[0]);
|
|
87
|
+
case 'func':
|
|
88
|
+
return AGGREGATORS.includes(name);
|
|
89
|
+
default:
|
|
90
|
+
throw new Error(`Unexpected type ${type}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
68
94
|
/**
|
|
69
95
|
* Format the abstract syntax tree of an expression into escaped string.
|
|
70
96
|
* @param {Spell} spell
|
|
@@ -216,4 +242,4 @@ function coerceLiteral(spell, ast) {
|
|
|
216
242
|
}
|
|
217
243
|
}
|
|
218
244
|
|
|
219
|
-
module.exports = { formatExpr, formatConditions, collectLiteral };
|
|
245
|
+
module.exports = { formatExpr, formatConditions, collectLiteral, isAggregatorExpr };
|
package/types/index.d.ts
CHANGED
|
@@ -205,6 +205,11 @@ interface QueryOptions {
|
|
|
205
205
|
hooks?: boolean;
|
|
206
206
|
paranoid?: boolean;
|
|
207
207
|
silent?: boolean;
|
|
208
|
+
connection?: Connection;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
interface TransactionOptions {
|
|
212
|
+
connection: Connection;
|
|
208
213
|
}
|
|
209
214
|
|
|
210
215
|
interface QueryResult {
|
|
@@ -214,7 +219,7 @@ interface QueryResult {
|
|
|
214
219
|
fields?: Array<{ table: string, name: string }>,
|
|
215
220
|
}
|
|
216
221
|
|
|
217
|
-
interface Connection {
|
|
222
|
+
export interface Connection {
|
|
218
223
|
/**
|
|
219
224
|
* MySQL
|
|
220
225
|
*/
|
|
@@ -322,10 +327,10 @@ declare class AbstractDriver {
|
|
|
322
327
|
* @param callback
|
|
323
328
|
*/
|
|
324
329
|
disconnect(callback?: Function): Promise<boolean | void>;
|
|
325
|
-
|
|
330
|
+
|
|
326
331
|
/**
|
|
327
332
|
* query with spell
|
|
328
|
-
* @param spell
|
|
333
|
+
* @param spell
|
|
329
334
|
*/
|
|
330
335
|
cast(spell: Spell<typeof Bone, ResultSet | number | null>): Promise<QueryResult>;
|
|
331
336
|
|
|
@@ -424,7 +429,7 @@ declare class AbstractDriver {
|
|
|
424
429
|
* remove index in table
|
|
425
430
|
* @param table string
|
|
426
431
|
* @param attributes attributes name
|
|
427
|
-
* @param opts
|
|
432
|
+
* @param opts
|
|
428
433
|
*/
|
|
429
434
|
removeIndex(table: string, attributes: string[], opts?: { unique?: boolean, type?: string }): Promise<void>;
|
|
430
435
|
|
|
@@ -695,7 +700,7 @@ export class Bone {
|
|
|
695
700
|
* });
|
|
696
701
|
*/
|
|
697
702
|
static transaction(callback: GeneratorFunction): Promise<RawQueryResult>;
|
|
698
|
-
static transaction(callback: (connection:
|
|
703
|
+
static transaction(callback: (connection: TransactionOptions) => Promise<RawQueryResult | void>): Promise<RawQueryResult>;
|
|
699
704
|
|
|
700
705
|
/**
|
|
701
706
|
* DROP the table
|