@naturalcycles/mysql-lib 3.12.0 → 3.12.1
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/dist/mysql.db.js +16 -4
- package/dist/query.util.d.ts +10 -3
- package/dist/query.util.js +30 -5
- package/package.json +1 -1
- package/src/mysql.db.ts +17 -5
- package/src/query.util.ts +33 -8
package/dist/mysql.db.js
CHANGED
|
@@ -116,6 +116,11 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
116
116
|
// QUERY
|
|
117
117
|
async runQuery(q, _opt = {}) {
|
|
118
118
|
const sql = (0, query_util_1.dbQueryToSQLSelect)(q);
|
|
119
|
+
if (!sql) {
|
|
120
|
+
return {
|
|
121
|
+
rows: [],
|
|
122
|
+
};
|
|
123
|
+
}
|
|
119
124
|
const rows = (await this.runSQL({ sql })).map(row => (0, js_lib_1._mapKeys)((0, js_lib_1._filterUndefinedValues)(row, true), k => (0, mysql_schema_util_1.mapNameFromMySQL)(k)));
|
|
120
125
|
// edge case where 0 fields are selected
|
|
121
126
|
if (q._selectedFieldNames?.length === 0) {
|
|
@@ -157,6 +162,9 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
157
162
|
}
|
|
158
163
|
streamQuery(q, _opt = {}) {
|
|
159
164
|
const sql = (0, query_util_1.dbQueryToSQLSelect)(q);
|
|
165
|
+
if (!sql) {
|
|
166
|
+
return stream_1.Readable.from([]);
|
|
167
|
+
}
|
|
160
168
|
if (this.cfg.logSQL)
|
|
161
169
|
this.cfg.logger.log(`stream: ${sql}`);
|
|
162
170
|
// return this.streamSQL(sql, opt)
|
|
@@ -205,13 +213,17 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
205
213
|
if (!ids.length)
|
|
206
214
|
return 0;
|
|
207
215
|
const sql = (0, query_util_1.dbQueryToSQLDelete)(new db_lib_1.DBQuery(table).filterEq('id', ids));
|
|
208
|
-
|
|
209
|
-
|
|
216
|
+
if (!sql)
|
|
217
|
+
return 0;
|
|
218
|
+
const { affectedRows } = await this.runSQL({ sql });
|
|
219
|
+
return affectedRows;
|
|
210
220
|
}
|
|
211
221
|
async deleteByQuery(q, _opt) {
|
|
212
222
|
const sql = (0, query_util_1.dbQueryToSQLDelete)(q);
|
|
213
|
-
|
|
214
|
-
|
|
223
|
+
if (!sql)
|
|
224
|
+
return 0;
|
|
225
|
+
const { affectedRows } = await this.runSQL({ sql });
|
|
226
|
+
return affectedRows;
|
|
215
227
|
}
|
|
216
228
|
/**
|
|
217
229
|
* Use with caution!
|
package/dist/query.util.d.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { DBQuery } from '@naturalcycles/db-lib';
|
|
2
2
|
import { CommonLogger } from '@naturalcycles/js-lib';
|
|
3
3
|
import { QueryOptions } from 'mysql';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Returns `null` if it detects that 0 rows will be returned,
|
|
6
|
+
* e.g when `IN ()` (empty array) is used.
|
|
7
|
+
*/
|
|
8
|
+
export declare function dbQueryToSQLSelect(q: DBQuery<any>): string | null;
|
|
9
|
+
/**
|
|
10
|
+
* Returns null in "0 rows" case.
|
|
11
|
+
*/
|
|
12
|
+
export declare function dbQueryToSQLDelete(q: DBQuery<any>): string | null;
|
|
6
13
|
/**
|
|
7
14
|
* Returns array of sql statements to respect the max sql size.
|
|
8
15
|
*/
|
|
9
16
|
export declare function insertSQL(table: string, rows: Record<any, any>[], verb?: 'INSERT' | 'REPLACE', logger?: CommonLogger): string[];
|
|
10
17
|
export declare function insertSQLSingle(table: string, record: Record<any, any>): string;
|
|
11
18
|
export declare function insertSQLSetSingle(table: string, record: Record<any, any>): QueryOptions;
|
|
12
|
-
export declare function dbQueryToSQLUpdate(q: DBQuery<any>, record: Record<any, any>): string;
|
|
19
|
+
export declare function dbQueryToSQLUpdate(q: DBQuery<any>, record: Record<any, any>): string | null;
|
package/dist/query.util.js
CHANGED
|
@@ -7,10 +7,17 @@ const mysql = require("mysql");
|
|
|
7
7
|
const mysql_schema_util_1 = require("./schema/mysql.schema.util");
|
|
8
8
|
const MAX_PACKET_SIZE = 1024 * 1024; // 1Mb
|
|
9
9
|
const MAX_ROW_SIZE = 800 * 1024; // 1Mb - margin
|
|
10
|
+
/**
|
|
11
|
+
* Returns `null` if it detects that 0 rows will be returned,
|
|
12
|
+
* e.g when `IN ()` (empty array) is used.
|
|
13
|
+
*/
|
|
10
14
|
function dbQueryToSQLSelect(q) {
|
|
11
15
|
const tokens = selectTokens(q);
|
|
12
16
|
// filters
|
|
13
|
-
|
|
17
|
+
const whereTokens = getWhereTokens(q);
|
|
18
|
+
if (!whereTokens)
|
|
19
|
+
return null;
|
|
20
|
+
tokens.push(...whereTokens);
|
|
14
21
|
// order
|
|
15
22
|
tokens.push(...groupOrderTokens(q));
|
|
16
23
|
// offset/limit
|
|
@@ -18,10 +25,16 @@ function dbQueryToSQLSelect(q) {
|
|
|
18
25
|
return tokens.join(' ');
|
|
19
26
|
}
|
|
20
27
|
exports.dbQueryToSQLSelect = dbQueryToSQLSelect;
|
|
28
|
+
/**
|
|
29
|
+
* Returns null in "0 rows" case.
|
|
30
|
+
*/
|
|
21
31
|
function dbQueryToSQLDelete(q) {
|
|
22
32
|
const tokens = [`DELETE FROM`, mysql.escapeId(q.table)];
|
|
23
33
|
// filters
|
|
24
|
-
|
|
34
|
+
const whereTokens = getWhereTokens(q);
|
|
35
|
+
if (!whereTokens)
|
|
36
|
+
return null;
|
|
37
|
+
tokens.push(...whereTokens);
|
|
25
38
|
// offset/limit
|
|
26
39
|
tokens.push(...offsetLimitTokens(q));
|
|
27
40
|
return tokens.join(' ');
|
|
@@ -106,6 +119,9 @@ function insertSQLSetSingle(table, record) {
|
|
|
106
119
|
exports.insertSQLSetSingle = insertSQLSetSingle;
|
|
107
120
|
function dbQueryToSQLUpdate(q, record) {
|
|
108
121
|
// var sql = mysql.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]);
|
|
122
|
+
const whereTokens = getWhereTokens(q);
|
|
123
|
+
if (!whereTokens)
|
|
124
|
+
return null;
|
|
109
125
|
const tokens = [
|
|
110
126
|
`UPDATE`,
|
|
111
127
|
mysql.escapeId(q.table),
|
|
@@ -113,7 +129,7 @@ function dbQueryToSQLUpdate(q, record) {
|
|
|
113
129
|
Object.keys(record)
|
|
114
130
|
.map(f => mysql.escapeId((0, mysql_schema_util_1.mapNameToMySQL)(f)) + ' = ?')
|
|
115
131
|
.join(', '),
|
|
116
|
-
...whereTokens
|
|
132
|
+
...whereTokens,
|
|
117
133
|
];
|
|
118
134
|
return mysql.format(tokens.join(' '), Object.values(record));
|
|
119
135
|
}
|
|
@@ -156,10 +172,14 @@ function groupOrderTokens(q) {
|
|
|
156
172
|
const OP_MAP = {
|
|
157
173
|
'==': '=',
|
|
158
174
|
};
|
|
159
|
-
|
|
175
|
+
/**
|
|
176
|
+
* Returns `null` for "guaranteed 0 rows" cases.
|
|
177
|
+
*/
|
|
178
|
+
function getWhereTokens(q) {
|
|
160
179
|
if (!q._filters.length)
|
|
161
180
|
return [];
|
|
162
|
-
|
|
181
|
+
let returnNull = false;
|
|
182
|
+
const tokens = [
|
|
163
183
|
`WHERE`,
|
|
164
184
|
q._filters
|
|
165
185
|
.map(f => {
|
|
@@ -172,6 +192,8 @@ function whereTokens(q) {
|
|
|
172
192
|
}
|
|
173
193
|
if (Array.isArray(f.val)) {
|
|
174
194
|
// special case for arrays
|
|
195
|
+
if (!f.val.length)
|
|
196
|
+
returnNull = true;
|
|
175
197
|
return `${mysql.escapeId((0, mysql_schema_util_1.mapNameToMySQL)(f.name))} IN (${mysql.escape(f.val)})`;
|
|
176
198
|
}
|
|
177
199
|
return [
|
|
@@ -182,4 +204,7 @@ function whereTokens(q) {
|
|
|
182
204
|
})
|
|
183
205
|
.join(' AND '),
|
|
184
206
|
];
|
|
207
|
+
if (returnNull)
|
|
208
|
+
return null;
|
|
209
|
+
return tokens;
|
|
185
210
|
}
|
package/package.json
CHANGED
package/src/mysql.db.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Transform } from 'stream'
|
|
1
|
+
import { Readable, Transform } from 'stream'
|
|
2
2
|
import { promisify } from 'util'
|
|
3
3
|
import {
|
|
4
4
|
BaseCommonDB,
|
|
@@ -199,6 +199,12 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
199
199
|
_opt: MysqlDBOptions = {},
|
|
200
200
|
): Promise<RunQueryResult<OUT>> {
|
|
201
201
|
const sql = dbQueryToSQLSelect(q)
|
|
202
|
+
if (!sql) {
|
|
203
|
+
return {
|
|
204
|
+
rows: [],
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
202
208
|
const rows = (await this.runSQL<ROW[]>({ sql })).map(
|
|
203
209
|
row => _mapKeys(_filterUndefinedValues(row, true), k => mapNameFromMySQL(k)) as any,
|
|
204
210
|
)
|
|
@@ -254,6 +260,9 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
254
260
|
_opt: MysqlDBOptions = {},
|
|
255
261
|
): ReadableTyped<OUT> {
|
|
256
262
|
const sql = dbQueryToSQLSelect(q)
|
|
263
|
+
if (!sql) {
|
|
264
|
+
return Readable.from([])
|
|
265
|
+
}
|
|
257
266
|
|
|
258
267
|
if (this.cfg.logSQL) this.cfg.logger.log(`stream: ${sql}`)
|
|
259
268
|
|
|
@@ -323,8 +332,10 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
323
332
|
): Promise<number> {
|
|
324
333
|
if (!ids.length) return 0
|
|
325
334
|
const sql = dbQueryToSQLDelete(new DBQuery(table).filterEq('id', ids))
|
|
326
|
-
|
|
327
|
-
|
|
335
|
+
if (!sql) return 0
|
|
336
|
+
|
|
337
|
+
const { affectedRows } = await this.runSQL<OkPacket>({ sql })
|
|
338
|
+
return affectedRows
|
|
328
339
|
}
|
|
329
340
|
|
|
330
341
|
override async deleteByQuery<ROW extends ObjectWithId>(
|
|
@@ -332,8 +343,9 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
332
343
|
_opt?: CommonDBOptions,
|
|
333
344
|
): Promise<number> {
|
|
334
345
|
const sql = dbQueryToSQLDelete(q)
|
|
335
|
-
|
|
336
|
-
|
|
346
|
+
if (!sql) return 0
|
|
347
|
+
const { affectedRows } = await this.runSQL<OkPacket>({ sql })
|
|
348
|
+
return affectedRows
|
|
337
349
|
}
|
|
338
350
|
|
|
339
351
|
/**
|
package/src/query.util.ts
CHANGED
|
@@ -9,11 +9,17 @@ import { mapNameToMySQL } from './schema/mysql.schema.util'
|
|
|
9
9
|
const MAX_PACKET_SIZE = 1024 * 1024 // 1Mb
|
|
10
10
|
const MAX_ROW_SIZE = 800 * 1024 // 1Mb - margin
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Returns `null` if it detects that 0 rows will be returned,
|
|
14
|
+
* e.g when `IN ()` (empty array) is used.
|
|
15
|
+
*/
|
|
16
|
+
export function dbQueryToSQLSelect(q: DBQuery<any>): string | null {
|
|
13
17
|
const tokens = selectTokens(q)
|
|
14
18
|
|
|
15
19
|
// filters
|
|
16
|
-
|
|
20
|
+
const whereTokens = getWhereTokens(q)
|
|
21
|
+
if (!whereTokens) return null
|
|
22
|
+
tokens.push(...whereTokens)
|
|
17
23
|
|
|
18
24
|
// order
|
|
19
25
|
tokens.push(...groupOrderTokens(q))
|
|
@@ -24,11 +30,16 @@ export function dbQueryToSQLSelect(q: DBQuery<any>): string {
|
|
|
24
30
|
return tokens.join(' ')
|
|
25
31
|
}
|
|
26
32
|
|
|
27
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Returns null in "0 rows" case.
|
|
35
|
+
*/
|
|
36
|
+
export function dbQueryToSQLDelete(q: DBQuery<any>): string | null {
|
|
28
37
|
const tokens = [`DELETE FROM`, mysql.escapeId(q.table)]
|
|
29
38
|
|
|
30
39
|
// filters
|
|
31
|
-
|
|
40
|
+
const whereTokens = getWhereTokens(q)
|
|
41
|
+
if (!whereTokens) return null
|
|
42
|
+
tokens.push(...whereTokens)
|
|
32
43
|
|
|
33
44
|
// offset/limit
|
|
34
45
|
tokens.push(...offsetLimitTokens(q))
|
|
@@ -132,8 +143,11 @@ export function insertSQLSetSingle(table: string, record: Record<any, any>): Que
|
|
|
132
143
|
}
|
|
133
144
|
}
|
|
134
145
|
|
|
135
|
-
export function dbQueryToSQLUpdate(q: DBQuery<any>, record: Record<any, any>): string {
|
|
146
|
+
export function dbQueryToSQLUpdate(q: DBQuery<any>, record: Record<any, any>): string | null {
|
|
136
147
|
// var sql = mysql.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]);
|
|
148
|
+
const whereTokens = getWhereTokens(q)
|
|
149
|
+
if (!whereTokens) return null
|
|
150
|
+
|
|
137
151
|
const tokens = [
|
|
138
152
|
`UPDATE`,
|
|
139
153
|
mysql.escapeId(q.table),
|
|
@@ -141,7 +155,7 @@ export function dbQueryToSQLUpdate(q: DBQuery<any>, record: Record<any, any>): s
|
|
|
141
155
|
Object.keys(record)
|
|
142
156
|
.map(f => mysql.escapeId(mapNameToMySQL(f)) + ' = ?')
|
|
143
157
|
.join(', '),
|
|
144
|
-
...whereTokens
|
|
158
|
+
...whereTokens,
|
|
145
159
|
]
|
|
146
160
|
|
|
147
161
|
return mysql.format(tokens.join(' '), Object.values(record))
|
|
@@ -200,10 +214,15 @@ const OP_MAP: Partial<Record<DBQueryFilterOperator, string>> = {
|
|
|
200
214
|
'==': '=',
|
|
201
215
|
}
|
|
202
216
|
|
|
203
|
-
|
|
217
|
+
/**
|
|
218
|
+
* Returns `null` for "guaranteed 0 rows" cases.
|
|
219
|
+
*/
|
|
220
|
+
function getWhereTokens(q: DBQuery): string[] | null {
|
|
204
221
|
if (!q._filters.length) return []
|
|
205
222
|
|
|
206
|
-
|
|
223
|
+
let returnNull = false
|
|
224
|
+
|
|
225
|
+
const tokens = [
|
|
207
226
|
`WHERE`,
|
|
208
227
|
q._filters
|
|
209
228
|
.map(f => {
|
|
@@ -218,6 +237,8 @@ function whereTokens(q: DBQuery): string[] {
|
|
|
218
237
|
|
|
219
238
|
if (Array.isArray(f.val)) {
|
|
220
239
|
// special case for arrays
|
|
240
|
+
if (!f.val.length) returnNull = true
|
|
241
|
+
|
|
221
242
|
return `${mysql.escapeId(mapNameToMySQL(f.name as string))} IN (${mysql.escape(f.val)})`
|
|
222
243
|
}
|
|
223
244
|
|
|
@@ -229,4 +250,8 @@ function whereTokens(q: DBQuery): string[] {
|
|
|
229
250
|
})
|
|
230
251
|
.join(' AND '),
|
|
231
252
|
]
|
|
253
|
+
|
|
254
|
+
if (returnNull) return null
|
|
255
|
+
|
|
256
|
+
return tokens
|
|
232
257
|
}
|