@naturalcycles/mysql-lib 3.10.0 → 3.11.0
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.d.ts +6 -2
- package/dist/mysql.db.js +15 -3
- package/dist/mysqlKeyValueDB.d.ts +1 -1
- package/dist/mysqlKeyValueDB.js +2 -5
- package/dist/query.util.js +17 -9
- package/package.json +2 -2
- package/src/mysql.db.ts +16 -1
- package/src/mysqlKeyValueDB.ts +2 -9
- package/src/query.util.ts +23 -8
package/dist/mysql.db.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseCommonDB, CommonDB, CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, DBQuery, RunQueryResult } from '@naturalcycles/db-lib';
|
|
2
2
|
import { AnyObjectWithId, CommonLogger, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib';
|
|
3
3
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
4
|
-
import { Connection, Pool, PoolConfig, PoolConnection, QueryOptions
|
|
4
|
+
import { Connection, Pool, PoolConfig, PoolConnection, QueryOptions } from 'mysql';
|
|
5
5
|
export interface MysqlDBOptions extends CommonDBOptions {
|
|
6
6
|
}
|
|
7
7
|
export interface MysqlDBSaveOptions<ROW extends ObjectWithId = AnyObjectWithId> extends CommonDBSaveOptions<ROW> {
|
|
@@ -23,7 +23,6 @@ export interface MysqlDBCfg extends PoolConfig {
|
|
|
23
23
|
*/
|
|
24
24
|
logger?: CommonLogger;
|
|
25
25
|
}
|
|
26
|
-
export declare const typeCast: TypeCast;
|
|
27
26
|
export declare class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
28
27
|
constructor(cfg?: MysqlDBCfg);
|
|
29
28
|
cfg: MysqlDBCfg & {
|
|
@@ -44,6 +43,11 @@ export declare class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
44
43
|
getByIds<ROW extends ObjectWithId>(table: string, ids: string[], opt?: MysqlDBOptions): Promise<ROW[]>;
|
|
45
44
|
runQuery<ROW extends ObjectWithId, OUT = ROW>(q: DBQuery<ROW>, _opt?: MysqlDBOptions): Promise<RunQueryResult<OUT>>;
|
|
46
45
|
runSQL<RESULT>(q: QueryOptions): Promise<RESULT>;
|
|
46
|
+
/**
|
|
47
|
+
* Allows to run semicolon-separated "SQL file".
|
|
48
|
+
* E.g "ddl reset script".
|
|
49
|
+
*/
|
|
50
|
+
runSQLString(s: string): Promise<void>;
|
|
47
51
|
runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
|
|
48
52
|
streamQuery<ROW extends ObjectWithId, OUT = ROW>(q: DBQuery<ROW>, _opt?: MysqlDBOptions): ReadableTyped<OUT>;
|
|
49
53
|
saveBatch<ROW extends ObjectWithId>(table: string, _rows: ROW[], _opt?: MysqlDBSaveOptions<ROW>): Promise<void>;
|
package/dist/mysql.db.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MysqlDB =
|
|
3
|
+
exports.MysqlDB = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const stream_1 = require("stream");
|
|
6
6
|
const util_1 = require("util");
|
|
@@ -31,12 +31,11 @@ const typeCast = (field, next) => {
|
|
|
31
31
|
}
|
|
32
32
|
return next();
|
|
33
33
|
};
|
|
34
|
-
exports.typeCast = typeCast;
|
|
35
34
|
class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
36
35
|
constructor(cfg = {}) {
|
|
37
36
|
super();
|
|
38
37
|
this.cfg = {
|
|
39
|
-
typeCast
|
|
38
|
+
typeCast,
|
|
40
39
|
// charset: 'utf8mb4', // for emoji support
|
|
41
40
|
// host: 'localhost',
|
|
42
41
|
// user: MYSQL_USER,
|
|
@@ -139,6 +138,19 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
139
138
|
});
|
|
140
139
|
});
|
|
141
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Allows to run semicolon-separated "SQL file".
|
|
143
|
+
* E.g "ddl reset script".
|
|
144
|
+
*/
|
|
145
|
+
async runSQLString(s) {
|
|
146
|
+
const queries = s
|
|
147
|
+
.split(';')
|
|
148
|
+
.map(s => s.trim())
|
|
149
|
+
.filter(Boolean);
|
|
150
|
+
for await (const sql of queries) {
|
|
151
|
+
await this.runSQL({ sql });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
142
154
|
async runQueryCount(q, _opt) {
|
|
143
155
|
const { rows } = await this.runQuery(q.select(['count(*) as _count']));
|
|
144
156
|
return rows[0]._count;
|
|
@@ -3,8 +3,8 @@ import { CommonDBCreateOptions, CommonKeyValueDB, KeyValueDBTuple } from '@natur
|
|
|
3
3
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
4
4
|
import { MysqlDB, MysqlDBCfg } from './mysql.db';
|
|
5
5
|
export declare class MySQLKeyValueDB implements CommonKeyValueDB {
|
|
6
|
-
constructor(cfg?: MysqlDBCfg);
|
|
7
6
|
cfg: MysqlDBCfg;
|
|
7
|
+
constructor(cfg: MysqlDBCfg);
|
|
8
8
|
db: MysqlDB;
|
|
9
9
|
ping(): Promise<void>;
|
|
10
10
|
close(): Promise<void>;
|
package/dist/mysqlKeyValueDB.js
CHANGED
|
@@ -5,11 +5,8 @@ const stream_1 = require("stream");
|
|
|
5
5
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
6
|
const mysql_db_1 = require("./mysql.db");
|
|
7
7
|
class MySQLKeyValueDB {
|
|
8
|
-
constructor(cfg
|
|
9
|
-
this.cfg =
|
|
10
|
-
typeCast: mysql_db_1.typeCast,
|
|
11
|
-
...cfg,
|
|
12
|
-
};
|
|
8
|
+
constructor(cfg) {
|
|
9
|
+
this.cfg = cfg;
|
|
13
10
|
this.db = new mysql_db_1.MysqlDB(this.cfg);
|
|
14
11
|
}
|
|
15
12
|
async ping() {
|
package/dist/query.util.js
CHANGED
|
@@ -12,7 +12,7 @@ function dbQueryToSQLSelect(q) {
|
|
|
12
12
|
// filters
|
|
13
13
|
tokens.push(...whereTokens(q));
|
|
14
14
|
// order
|
|
15
|
-
tokens.push(...
|
|
15
|
+
tokens.push(...groupOrderTokens(q));
|
|
16
16
|
// offset/limit
|
|
17
17
|
tokens.push(...offsetLimitTokens(q));
|
|
18
18
|
return tokens.join(' ');
|
|
@@ -124,7 +124,13 @@ function selectTokens(q) {
|
|
|
124
124
|
fields = q._selectedFieldNames.length ? q._selectedFieldNames : ['id'];
|
|
125
125
|
}
|
|
126
126
|
// We don't do `escapeId` cause it'll ruin e.g SELECT `count *` FROM ...
|
|
127
|
-
return [
|
|
127
|
+
return [
|
|
128
|
+
`SELECT`,
|
|
129
|
+
q._distinct && 'DISTINCT',
|
|
130
|
+
fields.map(f => (0, mysql_schema_util_1.mapNameToMySQL)(f)).join(', '),
|
|
131
|
+
`FROM`,
|
|
132
|
+
mysql.escapeId(q.table),
|
|
133
|
+
].filter(Boolean);
|
|
128
134
|
}
|
|
129
135
|
function offsetLimitTokens(q) {
|
|
130
136
|
const tokens = [];
|
|
@@ -137,13 +143,15 @@ function offsetLimitTokens(q) {
|
|
|
137
143
|
}
|
|
138
144
|
return tokens;
|
|
139
145
|
}
|
|
140
|
-
function
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
function groupOrderTokens(q) {
|
|
147
|
+
const t = [];
|
|
148
|
+
if (q._groupByFieldNames?.length) {
|
|
149
|
+
t.push(`GROUP BY`, q._groupByFieldNames.map(c => `\`${c}\``).join(', '));
|
|
150
|
+
}
|
|
151
|
+
if (q._orders.length) {
|
|
152
|
+
t.push(`ORDER BY`, q._orders.map(o => `\`${o.name}\` ${o.descending ? 'DESC' : 'ASC'}`).join(', '));
|
|
153
|
+
}
|
|
154
|
+
return t;
|
|
147
155
|
}
|
|
148
156
|
const OP_MAP = {
|
|
149
157
|
'==': '=',
|
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@naturalcycles/dev-lib": "^12.7.5",
|
|
15
15
|
"@types/node": "^17.0.5",
|
|
16
|
-
"dotenv": "^
|
|
16
|
+
"dotenv": "^14.1.0",
|
|
17
17
|
"jest": "^27.2.4"
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=14.15.0"
|
|
38
38
|
},
|
|
39
|
-
"version": "3.
|
|
39
|
+
"version": "3.11.0",
|
|
40
40
|
"description": "MySQL client implementing CommonDB interface",
|
|
41
41
|
"keywords": [
|
|
42
42
|
"mysql",
|
package/src/mysql.db.ts
CHANGED
|
@@ -60,7 +60,7 @@ export interface MysqlDBCfg extends PoolConfig {
|
|
|
60
60
|
const BOOLEAN_TYPES = new Set(['TINY', 'TINYINT', 'INT'])
|
|
61
61
|
const BOOLEAN_BIT_TYPES = new Set(['BIT'])
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
const typeCast: TypeCast = (field, next) => {
|
|
64
64
|
// cast to boolean
|
|
65
65
|
if (field.length === 1) {
|
|
66
66
|
if (BOOLEAN_BIT_TYPES.has(field.type)) {
|
|
@@ -218,6 +218,21 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
218
218
|
})
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Allows to run semicolon-separated "SQL file".
|
|
223
|
+
* E.g "ddl reset script".
|
|
224
|
+
*/
|
|
225
|
+
async runSQLString(s: string): Promise<void> {
|
|
226
|
+
const queries = s
|
|
227
|
+
.split(';')
|
|
228
|
+
.map(s => s.trim())
|
|
229
|
+
.filter(Boolean)
|
|
230
|
+
|
|
231
|
+
for await (const sql of queries) {
|
|
232
|
+
await this.runSQL({ sql })
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
221
236
|
override async runQueryCount<ROW extends ObjectWithId>(
|
|
222
237
|
q: DBQuery<ROW>,
|
|
223
238
|
_opt?: CommonDBOptions,
|
package/src/mysqlKeyValueDB.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { CommonDBCreateOptions, CommonKeyValueDB, KeyValueDBTuple } from '@natur
|
|
|
3
3
|
import { pMap } from '@naturalcycles/js-lib'
|
|
4
4
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
5
5
|
import { QueryOptions } from 'mysql'
|
|
6
|
-
import { MysqlDB, MysqlDBCfg
|
|
6
|
+
import { MysqlDB, MysqlDBCfg } from './mysql.db'
|
|
7
7
|
|
|
8
8
|
interface KeyValueObject {
|
|
9
9
|
id: string
|
|
@@ -11,17 +11,10 @@ interface KeyValueObject {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export class MySQLKeyValueDB implements CommonKeyValueDB {
|
|
14
|
-
constructor(cfg: MysqlDBCfg
|
|
15
|
-
this.cfg = {
|
|
16
|
-
typeCast,
|
|
17
|
-
...cfg,
|
|
18
|
-
}
|
|
19
|
-
|
|
14
|
+
constructor(public cfg: MysqlDBCfg) {
|
|
20
15
|
this.db = new MysqlDB(this.cfg)
|
|
21
16
|
}
|
|
22
17
|
|
|
23
|
-
cfg: MysqlDBCfg
|
|
24
|
-
|
|
25
18
|
db: MysqlDB
|
|
26
19
|
|
|
27
20
|
async ping(): Promise<void> {
|
package/src/query.util.ts
CHANGED
|
@@ -16,7 +16,7 @@ export function dbQueryToSQLSelect(q: DBQuery<any>): string {
|
|
|
16
16
|
tokens.push(...whereTokens(q))
|
|
17
17
|
|
|
18
18
|
// order
|
|
19
|
-
tokens.push(...
|
|
19
|
+
tokens.push(...groupOrderTokens(q))
|
|
20
20
|
|
|
21
21
|
// offset/limit
|
|
22
22
|
tokens.push(...offsetLimitTokens(q))
|
|
@@ -155,7 +155,13 @@ function selectTokens(q: DBQuery): string[] {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
// We don't do `escapeId` cause it'll ruin e.g SELECT `count *` FROM ...
|
|
158
|
-
return [
|
|
158
|
+
return [
|
|
159
|
+
`SELECT`,
|
|
160
|
+
q._distinct && ('DISTINCT' as any),
|
|
161
|
+
fields.map(f => mapNameToMySQL(f)).join(', '),
|
|
162
|
+
`FROM`,
|
|
163
|
+
mysql.escapeId(q.table),
|
|
164
|
+
].filter(Boolean)
|
|
159
165
|
}
|
|
160
166
|
|
|
161
167
|
function offsetLimitTokens(q: DBQuery<any>): string[] {
|
|
@@ -173,12 +179,21 @@ function offsetLimitTokens(q: DBQuery<any>): string[] {
|
|
|
173
179
|
return tokens
|
|
174
180
|
}
|
|
175
181
|
|
|
176
|
-
function
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
q.
|
|
181
|
-
|
|
182
|
+
function groupOrderTokens(q: DBQuery): string[] {
|
|
183
|
+
const t: string[] = []
|
|
184
|
+
|
|
185
|
+
if (q._groupByFieldNames?.length) {
|
|
186
|
+
t.push(`GROUP BY`, q._groupByFieldNames.map(c => `\`${c}\``).join(', '))
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (q._orders.length) {
|
|
190
|
+
t.push(
|
|
191
|
+
`ORDER BY`,
|
|
192
|
+
q._orders.map(o => `\`${o.name}\` ${o.descending ? 'DESC' : 'ASC'}`).join(', '),
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return t
|
|
182
197
|
}
|
|
183
198
|
|
|
184
199
|
const OP_MAP: Partial<Record<DBQueryFilterOperator, string>> = {
|