@naturalcycles/mysql-lib 3.16.3 → 4.0.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/index.d.ts +3 -3
- package/dist/index.js +3 -8
- package/dist/mysql.db.d.ts +5 -4
- package/dist/mysql.db.js +47 -50
- package/dist/mysqlKeyValueDB.d.ts +5 -4
- package/dist/mysqlKeyValueDB.js +15 -17
- package/dist/query.util.d.ts +3 -3
- package/dist/query.util.js +18 -27
- package/dist/schema/mysql.schema.util.d.ts +1 -1
- package/dist/schema/mysql.schema.util.js +5 -12
- package/package.json +9 -6
- package/src/index.ts +3 -3
- package/src/mysql.db.ts +19 -14
- package/src/mysqlKeyValueDB.ts +9 -7
- package/src/query.util.ts +5 -4
- package/src/schema/mysql.schema.util.ts +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './mysql.db';
|
|
2
|
-
export * from './mysqlKeyValueDB';
|
|
3
|
-
export { jsonSchemaToMySQLDDL } from './schema/mysql.schema.util';
|
|
1
|
+
export * from './mysql.db.js';
|
|
2
|
+
export * from './mysqlKeyValueDB.js';
|
|
3
|
+
export { jsonSchemaToMySQLDDL } from './schema/mysql.schema.util.js';
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
tslib_1.__exportStar(require("./mysql.db"), exports);
|
|
6
|
-
tslib_1.__exportStar(require("./mysqlKeyValueDB"), exports);
|
|
7
|
-
var mysql_schema_util_1 = require("./schema/mysql.schema.util");
|
|
8
|
-
Object.defineProperty(exports, "jsonSchemaToMySQLDDL", { enumerable: true, get: function () { return mysql_schema_util_1.jsonSchemaToMySQLDDL; } });
|
|
1
|
+
export * from './mysql.db.js';
|
|
2
|
+
export * from './mysqlKeyValueDB.js';
|
|
3
|
+
export { jsonSchemaToMySQLDDL } from './schema/mysql.schema.util.js';
|
package/dist/mysql.db.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import type { CommonDB, CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, CommonDBSupport, RunQueryResult } from '@naturalcycles/db-lib';
|
|
2
|
+
import { BaseCommonDB, CommonDBType, DBQuery } from '@naturalcycles/db-lib';
|
|
3
|
+
import type { CommonLogger, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib';
|
|
4
|
+
import type { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
5
|
+
import type { Connection, Pool, PoolConfig, PoolConnection, QueryOptions } from 'mysql';
|
|
5
6
|
export interface MysqlDBOptions extends CommonDBOptions {
|
|
6
7
|
}
|
|
7
8
|
export interface MysqlDBSaveOptions<ROW extends ObjectWithId> extends CommonDBSaveOptions<ROW> {
|
package/dist/mysql.db.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const mysql = tslib_1.__importStar(require("mysql"));
|
|
11
|
-
const query_util_1 = require("./query.util");
|
|
12
|
-
const mysql_schema_util_1 = require("./schema/mysql.schema.util");
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { Readable, Transform } from 'node:stream';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
import { BaseCommonDB, commonDBFullSupport, CommonDBType, DBQuery } from '@naturalcycles/db-lib';
|
|
5
|
+
import { _assert, _filterUndefinedValues, _mapKeys, _mapValues, _Memo, _omit, commonLoggerPrefix, } from '@naturalcycles/js-lib';
|
|
6
|
+
import { white } from '@naturalcycles/nodejs-lib';
|
|
7
|
+
import * as mysql from 'mysql';
|
|
8
|
+
import { dbQueryToSQLDelete, dbQueryToSQLSelect, dbQueryToSQLUpdate, insertSQL, } from './query.util.js';
|
|
9
|
+
import { jsonSchemaToMySQLDDL, mapNameFromMySQL, mysqlTableStatsToJsonSchemaField, } from './schema/mysql.schema.util.js';
|
|
13
10
|
const BOOLEAN_TYPES = new Set(['TINY', 'TINYINT', 'INT']);
|
|
14
11
|
const BOOLEAN_BIT_TYPES = new Set(['BIT']);
|
|
15
12
|
const typeCast = (field, next) => {
|
|
@@ -31,16 +28,16 @@ const typeCast = (field, next) => {
|
|
|
31
28
|
}
|
|
32
29
|
return next();
|
|
33
30
|
};
|
|
34
|
-
class MysqlDB extends
|
|
31
|
+
export class MysqlDB extends BaseCommonDB {
|
|
32
|
+
dbType = CommonDBType.relational;
|
|
33
|
+
support = {
|
|
34
|
+
...commonDBFullSupport,
|
|
35
|
+
updateSaveMethod: false, // todo: can be implemented
|
|
36
|
+
transactions: false, // todo: can be implemented
|
|
37
|
+
increment: false, // todo: can be implemented
|
|
38
|
+
};
|
|
35
39
|
constructor(cfg = {}) {
|
|
36
40
|
super();
|
|
37
|
-
this.dbType = db_lib_1.CommonDBType.relational;
|
|
38
|
-
this.support = {
|
|
39
|
-
...db_lib_1.commonDBFullSupport,
|
|
40
|
-
updateSaveMethod: false, // todo: can be implemented
|
|
41
|
-
transactions: false, // todo: can be implemented
|
|
42
|
-
increment: false, // todo: can be implemented
|
|
43
|
-
};
|
|
44
41
|
this.cfg = {
|
|
45
42
|
typeCast,
|
|
46
43
|
// charset: 'utf8mb4', // for emoji support
|
|
@@ -49,9 +46,10 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
49
46
|
// password: MYSQL_PW,
|
|
50
47
|
// database: MYSQL_DB,
|
|
51
48
|
...cfg,
|
|
52
|
-
logger:
|
|
49
|
+
logger: commonLoggerPrefix(cfg.logger || console, '[mysql]'),
|
|
53
50
|
};
|
|
54
51
|
}
|
|
52
|
+
cfg;
|
|
55
53
|
async ping() {
|
|
56
54
|
const con = await this.getConnection();
|
|
57
55
|
con.release();
|
|
@@ -59,7 +57,7 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
59
57
|
pool() {
|
|
60
58
|
const pool = mysql.createPool(this.cfg);
|
|
61
59
|
const { host, database, logger } = this.cfg;
|
|
62
|
-
logger.log(`connected to ${
|
|
60
|
+
logger.log(`connected to ${white(host + '/' + database)}`);
|
|
63
61
|
if (this.cfg.debugConnections) {
|
|
64
62
|
pool.on('acquire', con => {
|
|
65
63
|
logger.log(`acquire(${con.threadId})`);
|
|
@@ -81,7 +79,7 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
81
79
|
}
|
|
82
80
|
async close() {
|
|
83
81
|
const pool = this.pool();
|
|
84
|
-
await
|
|
82
|
+
await promisify(pool.end.bind(pool))();
|
|
85
83
|
this.cfg.logger.log('closed');
|
|
86
84
|
}
|
|
87
85
|
/**
|
|
@@ -89,7 +87,7 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
89
87
|
*/
|
|
90
88
|
async getConnection() {
|
|
91
89
|
const pool = this.pool();
|
|
92
|
-
return await
|
|
90
|
+
return await promisify(pool.getConnection.bind(pool))();
|
|
93
91
|
}
|
|
94
92
|
/**
|
|
95
93
|
* Manually create a single (not pool) connection.
|
|
@@ -97,7 +95,7 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
97
95
|
*/
|
|
98
96
|
async createSingleConnection() {
|
|
99
97
|
const con = mysql.createConnection(this.cfg);
|
|
100
|
-
await
|
|
98
|
+
await promisify(con.connect.bind(con))();
|
|
101
99
|
const { threadId } = con;
|
|
102
100
|
if (this.cfg.debugConnections) {
|
|
103
101
|
this.cfg.logger.log(`createSingleConnection(${threadId})`);
|
|
@@ -115,19 +113,19 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
115
113
|
async getByIds(table, ids, opt = {}) {
|
|
116
114
|
if (!ids.length)
|
|
117
115
|
return [];
|
|
118
|
-
const q = new
|
|
116
|
+
const q = new DBQuery(table).filterEq('id', ids);
|
|
119
117
|
const { rows } = await this.runQuery(q, opt);
|
|
120
|
-
return rows.map(r =>
|
|
118
|
+
return rows.map(r => _mapKeys(r, k => mapNameFromMySQL(k)));
|
|
121
119
|
}
|
|
122
120
|
// QUERY
|
|
123
121
|
async runQuery(q, _opt = {}) {
|
|
124
|
-
const sql =
|
|
122
|
+
const sql = dbQueryToSQLSelect(q);
|
|
125
123
|
if (!sql) {
|
|
126
124
|
return {
|
|
127
125
|
rows: [],
|
|
128
126
|
};
|
|
129
127
|
}
|
|
130
|
-
const rows = (await this.runSQL({ sql })).map(row =>
|
|
128
|
+
const rows = (await this.runSQL({ sql })).map(row => _mapKeys(_filterUndefinedValues(row, true), k => mapNameFromMySQL(k)));
|
|
131
129
|
// edge case where 0 fields are selected
|
|
132
130
|
if (q._selectedFieldNames?.length === 0) {
|
|
133
131
|
return {
|
|
@@ -167,9 +165,9 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
167
165
|
return rows[0]._count;
|
|
168
166
|
}
|
|
169
167
|
streamQuery(q, _opt = {}) {
|
|
170
|
-
const sql =
|
|
168
|
+
const sql = dbQueryToSQLSelect(q);
|
|
171
169
|
if (!sql) {
|
|
172
|
-
return
|
|
170
|
+
return Readable.from([]);
|
|
173
171
|
}
|
|
174
172
|
if (this.cfg.logSQL)
|
|
175
173
|
this.cfg.logger.log(`stream: ${sql}`);
|
|
@@ -180,10 +178,10 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
180
178
|
return this.pool()
|
|
181
179
|
.query(sql)
|
|
182
180
|
.stream()
|
|
183
|
-
.pipe(new
|
|
181
|
+
.pipe(new Transform({
|
|
184
182
|
objectMode: true,
|
|
185
183
|
transform(row, _encoding, cb) {
|
|
186
|
-
cb(null,
|
|
184
|
+
cb(null, _filterUndefinedValues(row, true));
|
|
187
185
|
},
|
|
188
186
|
}));
|
|
189
187
|
}
|
|
@@ -192,10 +190,10 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
192
190
|
if (!rowsInput.length)
|
|
193
191
|
return;
|
|
194
192
|
// Stringify object values
|
|
195
|
-
const rows = rowsInput.map(row =>
|
|
193
|
+
const rows = rowsInput.map(row => _mapValues(row, (_k, v) => {
|
|
196
194
|
if (v && typeof v === 'object' && !Buffer.isBuffer(v)) {
|
|
197
195
|
// This is to avoid implicit Date stringification and mismatch: it gets saved as Date, but loaded as String
|
|
198
|
-
|
|
196
|
+
_assert(!(v instanceof Date), 'mysql-lib does not support Date values, please stringify them before passing');
|
|
199
197
|
return JSON.stringify(v);
|
|
200
198
|
}
|
|
201
199
|
return v;
|
|
@@ -207,12 +205,12 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
207
205
|
i++;
|
|
208
206
|
if (row.id) {
|
|
209
207
|
// Update already existing
|
|
210
|
-
const query = new
|
|
211
|
-
await this.patchByQuery(query,
|
|
208
|
+
const query = new DBQuery(table).filterEq('id', row.id);
|
|
209
|
+
await this.patchByQuery(query, _omit(row, ['id']));
|
|
212
210
|
}
|
|
213
211
|
else {
|
|
214
212
|
// Create new
|
|
215
|
-
const sql =
|
|
213
|
+
const sql = insertSQL(table, [row], 'INSERT', this.cfg.logger)[0];
|
|
216
214
|
const { insertId } = await this.runSQL({ sql });
|
|
217
215
|
// Mutate the input row with insertIt
|
|
218
216
|
rowsInput[i].id = insertId; // this is because we no longer support number ids in CommonDB
|
|
@@ -224,15 +222,15 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
224
222
|
// TODO: This fails if a combination of entities with id and without id are parsed
|
|
225
223
|
for (const row of rows) {
|
|
226
224
|
// Update already existing
|
|
227
|
-
|
|
228
|
-
const query = new
|
|
229
|
-
await this.patchByQuery(query,
|
|
225
|
+
_assert(row.id, 'id is required for updating');
|
|
226
|
+
const query = new DBQuery(table).filterEq('id', row.id);
|
|
227
|
+
await this.patchByQuery(query, _omit(row, ['id']));
|
|
230
228
|
}
|
|
231
229
|
return;
|
|
232
230
|
}
|
|
233
231
|
const verb = opt.saveMethod === 'insert' ? 'INSERT' : 'REPLACE';
|
|
234
232
|
// inserts are split into multiple sentenses to respect the max_packet_size (1Mb usually)
|
|
235
|
-
const sqls =
|
|
233
|
+
const sqls = insertSQL(table, rows, verb, this.cfg.logger);
|
|
236
234
|
for (const sql of sqls) {
|
|
237
235
|
await this.runSQL({ sql });
|
|
238
236
|
}
|
|
@@ -244,14 +242,14 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
244
242
|
async deleteByIds(table, ids, _opt) {
|
|
245
243
|
if (!ids.length)
|
|
246
244
|
return 0;
|
|
247
|
-
const sql =
|
|
245
|
+
const sql = dbQueryToSQLDelete(new DBQuery(table).filterEq('id', ids));
|
|
248
246
|
if (!sql)
|
|
249
247
|
return 0;
|
|
250
248
|
const { affectedRows } = await this.runSQL({ sql });
|
|
251
249
|
return affectedRows;
|
|
252
250
|
}
|
|
253
251
|
async deleteByQuery(q, _opt) {
|
|
254
|
-
const sql =
|
|
252
|
+
const sql = dbQueryToSQLDelete(q);
|
|
255
253
|
if (!sql)
|
|
256
254
|
return 0;
|
|
257
255
|
const { affectedRows } = await this.runSQL({ sql });
|
|
@@ -269,7 +267,7 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
269
267
|
async createTable(table, schema, opt = {}) {
|
|
270
268
|
if (opt.dropIfExists)
|
|
271
269
|
await this.dropTable(table);
|
|
272
|
-
const sql =
|
|
270
|
+
const sql = jsonSchemaToMySQLDDL(table, schema);
|
|
273
271
|
await this.runSQL({ sql });
|
|
274
272
|
}
|
|
275
273
|
async getTables() {
|
|
@@ -281,17 +279,16 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
281
279
|
const stats = await this.runSQL({
|
|
282
280
|
sql: `describe ${mysql.escapeId(table)}`,
|
|
283
281
|
});
|
|
284
|
-
return
|
|
282
|
+
return mysqlTableStatsToJsonSchemaField(table, stats, this.cfg.logger);
|
|
285
283
|
}
|
|
286
284
|
async patchByQuery(q, patch) {
|
|
287
|
-
const sql =
|
|
285
|
+
const sql = dbQueryToSQLUpdate(q, patch);
|
|
288
286
|
if (!sql)
|
|
289
287
|
return 0;
|
|
290
288
|
const { affectedRows } = await this.runSQL({ sql });
|
|
291
289
|
return affectedRows;
|
|
292
290
|
}
|
|
293
291
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
(0, js_lib_1._Memo)()
|
|
292
|
+
__decorate([
|
|
293
|
+
_Memo()
|
|
297
294
|
], MysqlDB.prototype, "pool", null);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { CommonDBCreateOptions, CommonKeyValueDB, KeyValueDBTuple } from '@naturalcycles/db-lib';
|
|
2
|
-
import { IncrementTuple } from '@naturalcycles/db-lib/dist/kv/commonKeyValueDB';
|
|
3
|
-
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
4
|
-
import {
|
|
1
|
+
import type { CommonDBCreateOptions, CommonKeyValueDB, KeyValueDBTuple } from '@naturalcycles/db-lib';
|
|
2
|
+
import type { IncrementTuple } from '@naturalcycles/db-lib/dist/kv/commonKeyValueDB.js';
|
|
3
|
+
import type { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
4
|
+
import type { MysqlDBCfg } from './mysql.db.js';
|
|
5
|
+
import { MysqlDB } from './mysql.db.js';
|
|
5
6
|
export declare class MySQLKeyValueDB implements CommonKeyValueDB {
|
|
6
7
|
cfg: MysqlDBCfg;
|
|
7
8
|
constructor(cfg: MysqlDBCfg);
|
package/dist/mysqlKeyValueDB.js
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const mysql_db_1 = require("./mysql.db");
|
|
8
|
-
class MySQLKeyValueDB {
|
|
1
|
+
import { Transform } from 'node:stream';
|
|
2
|
+
import { commonKeyValueDBFullSupport } from '@naturalcycles/db-lib';
|
|
3
|
+
import { AppError, pMap } from '@naturalcycles/js-lib';
|
|
4
|
+
import { MysqlDB } from './mysql.db.js';
|
|
5
|
+
export class MySQLKeyValueDB {
|
|
6
|
+
cfg;
|
|
9
7
|
constructor(cfg) {
|
|
10
8
|
this.cfg = cfg;
|
|
11
|
-
this.
|
|
12
|
-
...db_lib_1.commonKeyValueDBFullSupport,
|
|
13
|
-
increment: false,
|
|
14
|
-
};
|
|
15
|
-
this.db = new mysql_db_1.MysqlDB(this.cfg);
|
|
9
|
+
this.db = new MysqlDB(this.cfg);
|
|
16
10
|
}
|
|
11
|
+
db;
|
|
12
|
+
support = {
|
|
13
|
+
...commonKeyValueDBFullSupport,
|
|
14
|
+
increment: false,
|
|
15
|
+
};
|
|
17
16
|
async ping() {
|
|
18
17
|
await this.db.ping();
|
|
19
18
|
}
|
|
@@ -56,7 +55,7 @@ class MySQLKeyValueDB {
|
|
|
56
55
|
values: [id, buf],
|
|
57
56
|
};
|
|
58
57
|
});
|
|
59
|
-
await
|
|
58
|
+
await pMap(statements, async (statement) => {
|
|
60
59
|
if (this.cfg.debug)
|
|
61
60
|
this.db.cfg.logger.log(statement.sql);
|
|
62
61
|
await this.db.runSQL(statement);
|
|
@@ -74,7 +73,7 @@ class MySQLKeyValueDB {
|
|
|
74
73
|
.pool()
|
|
75
74
|
.query(sql)
|
|
76
75
|
.stream()
|
|
77
|
-
.pipe(new
|
|
76
|
+
.pipe(new Transform({
|
|
78
77
|
objectMode: true,
|
|
79
78
|
transform(row, _encoding, cb) {
|
|
80
79
|
cb(null, row.id);
|
|
@@ -114,7 +113,6 @@ class MySQLKeyValueDB {
|
|
|
114
113
|
return rows[0].cnt;
|
|
115
114
|
}
|
|
116
115
|
async incrementBatch(_table, _entries) {
|
|
117
|
-
throw new
|
|
116
|
+
throw new AppError('MySQLKeyValueDB.incrementBatch() is not implemented');
|
|
118
117
|
}
|
|
119
118
|
}
|
|
120
|
-
exports.MySQLKeyValueDB = MySQLKeyValueDB;
|
package/dist/query.util.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DBQuery } from '@naturalcycles/db-lib';
|
|
2
|
-
import { CommonLogger } from '@naturalcycles/js-lib';
|
|
3
|
-
import { QueryOptions } from 'mysql';
|
|
1
|
+
import type { DBQuery } from '@naturalcycles/db-lib';
|
|
2
|
+
import type { CommonLogger } from '@naturalcycles/js-lib';
|
|
3
|
+
import type { QueryOptions } from 'mysql';
|
|
4
4
|
/**
|
|
5
5
|
* Returns `null` if it detects that 0 rows will be returned,
|
|
6
6
|
* e.g when `IN ()` (empty array) is used.
|
package/dist/query.util.js
CHANGED
|
@@ -1,23 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.insertSQL = insertSQL;
|
|
6
|
-
exports.insertSQLSingle = insertSQLSingle;
|
|
7
|
-
exports.insertSQLSetSingle = insertSQLSetSingle;
|
|
8
|
-
exports.dbQueryToSQLUpdate = dbQueryToSQLUpdate;
|
|
9
|
-
const tslib_1 = require("tslib");
|
|
10
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
11
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
12
|
-
const mysql = tslib_1.__importStar(require("mysql"));
|
|
13
|
-
const mysql_schema_util_1 = require("./schema/mysql.schema.util");
|
|
1
|
+
import { _hb } from '@naturalcycles/js-lib';
|
|
2
|
+
import { white, yellow } from '@naturalcycles/nodejs-lib';
|
|
3
|
+
import * as mysql from 'mysql';
|
|
4
|
+
import { mapNameToMySQL } from './schema/mysql.schema.util.js';
|
|
14
5
|
const MAX_PACKET_SIZE = 1024 * 1024; // 1Mb
|
|
15
6
|
const MAX_ROW_SIZE = 800 * 1024; // 1Mb - margin
|
|
16
7
|
/**
|
|
17
8
|
* Returns `null` if it detects that 0 rows will be returned,
|
|
18
9
|
* e.g when `IN ()` (empty array) is used.
|
|
19
10
|
*/
|
|
20
|
-
function dbQueryToSQLSelect(q) {
|
|
11
|
+
export function dbQueryToSQLSelect(q) {
|
|
21
12
|
const tokens = selectTokens(q);
|
|
22
13
|
// filters
|
|
23
14
|
const whereTokens = getWhereTokens(q);
|
|
@@ -33,7 +24,7 @@ function dbQueryToSQLSelect(q) {
|
|
|
33
24
|
/**
|
|
34
25
|
* Returns null in "0 rows" case.
|
|
35
26
|
*/
|
|
36
|
-
function dbQueryToSQLDelete(q) {
|
|
27
|
+
export function dbQueryToSQLDelete(q) {
|
|
37
28
|
const tokens = [`DELETE FROM`, mysql.escapeId(q.table)];
|
|
38
29
|
// filters
|
|
39
30
|
const whereTokens = getWhereTokens(q);
|
|
@@ -47,7 +38,7 @@ function dbQueryToSQLDelete(q) {
|
|
|
47
38
|
/**
|
|
48
39
|
* Returns array of sql statements to respect the max sql size.
|
|
49
40
|
*/
|
|
50
|
-
function insertSQL(table, rows, verb = 'INSERT', logger = console) {
|
|
41
|
+
export function insertSQL(table, rows, verb = 'INSERT', logger = console) {
|
|
51
42
|
// INSERT INTO table_name (column1, column2, column3, ...)
|
|
52
43
|
// VALUES (value1, value2, value3, ...);
|
|
53
44
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
@@ -60,7 +51,7 @@ function insertSQL(table, rows, verb = 'INSERT', logger = console) {
|
|
|
60
51
|
verb,
|
|
61
52
|
`INTO`,
|
|
62
53
|
mysql.escapeId(table),
|
|
63
|
-
`(` + [...fields].map(f => mysql.escapeId(
|
|
54
|
+
`(` + [...fields].map(f => mysql.escapeId(mapNameToMySQL(f))).join(',') + `)`,
|
|
64
55
|
`VALUES\n`,
|
|
65
56
|
].join(' ');
|
|
66
57
|
const valueRows = rows.map(rec => {
|
|
@@ -88,11 +79,11 @@ function insertSQL(table, rows, verb = 'INSERT', logger = console) {
|
|
|
88
79
|
if (sql) {
|
|
89
80
|
sqls.push(sql); // last one
|
|
90
81
|
}
|
|
91
|
-
logger.log(`${
|
|
82
|
+
logger.log(`${white(table)} large sql query (${yellow(_hb(full.length))}) was split into ${yellow(sqls.length)} chunks`);
|
|
92
83
|
return sqls;
|
|
93
84
|
// todo: handle "upsert" later
|
|
94
85
|
}
|
|
95
|
-
function insertSQLSingle(table, record) {
|
|
86
|
+
export function insertSQLSingle(table, record) {
|
|
96
87
|
// INSERT INTO table_name (column1, column2, column3, ...)
|
|
97
88
|
// VALUES (value1, value2, value3, ...);
|
|
98
89
|
const tokens = [
|
|
@@ -100,7 +91,7 @@ function insertSQLSingle(table, record) {
|
|
|
100
91
|
mysql.escapeId(table),
|
|
101
92
|
`(` +
|
|
102
93
|
Object.keys(record)
|
|
103
|
-
.map(f => mysql.escapeId(
|
|
94
|
+
.map(f => mysql.escapeId(mapNameToMySQL(f)))
|
|
104
95
|
.join(',') +
|
|
105
96
|
`)`,
|
|
106
97
|
`\nVALUES`,
|
|
@@ -112,13 +103,13 @@ function insertSQLSingle(table, record) {
|
|
|
112
103
|
];
|
|
113
104
|
return tokens.join(' ');
|
|
114
105
|
}
|
|
115
|
-
function insertSQLSetSingle(table, record) {
|
|
106
|
+
export function insertSQLSetSingle(table, record) {
|
|
116
107
|
return {
|
|
117
108
|
sql: `INSERT INTO ${mysql.escapeId(table)} SET ?`,
|
|
118
109
|
values: [record],
|
|
119
110
|
};
|
|
120
111
|
}
|
|
121
|
-
function dbQueryToSQLUpdate(q, patch) {
|
|
112
|
+
export function dbQueryToSQLUpdate(q, patch) {
|
|
122
113
|
// var sql = mysql.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]);
|
|
123
114
|
const whereTokens = getWhereTokens(q);
|
|
124
115
|
if (!whereTokens)
|
|
@@ -128,7 +119,7 @@ function dbQueryToSQLUpdate(q, patch) {
|
|
|
128
119
|
mysql.escapeId(q.table),
|
|
129
120
|
`SET`,
|
|
130
121
|
Object.keys(patch)
|
|
131
|
-
.map(f => mysql.escapeId(
|
|
122
|
+
.map(f => mysql.escapeId(mapNameToMySQL(f)) + ' = ?')
|
|
132
123
|
.join(', '),
|
|
133
124
|
...whereTokens,
|
|
134
125
|
];
|
|
@@ -143,7 +134,7 @@ function selectTokens(q) {
|
|
|
143
134
|
return [
|
|
144
135
|
`SELECT`,
|
|
145
136
|
q._distinct && 'DISTINCT',
|
|
146
|
-
fields.map(f =>
|
|
137
|
+
fields.map(f => mapNameToMySQL(f)).join(', '),
|
|
147
138
|
`FROM`,
|
|
148
139
|
mysql.escapeId(q.table),
|
|
149
140
|
].filter(Boolean);
|
|
@@ -186,7 +177,7 @@ function getWhereTokens(q) {
|
|
|
186
177
|
if (f.val === null || f.val === undefined) {
|
|
187
178
|
// special treatment
|
|
188
179
|
return [
|
|
189
|
-
mysql.escapeId(
|
|
180
|
+
mysql.escapeId(mapNameToMySQL(f.name)),
|
|
190
181
|
f.op === '==' ? 'IS NULL' : 'IS NOT NULL',
|
|
191
182
|
].join(' ');
|
|
192
183
|
}
|
|
@@ -194,10 +185,10 @@ function getWhereTokens(q) {
|
|
|
194
185
|
// special case for arrays
|
|
195
186
|
if (!f.val.length)
|
|
196
187
|
returnNull = true;
|
|
197
|
-
return `${mysql.escapeId(
|
|
188
|
+
return `${mysql.escapeId(mapNameToMySQL(f.name))} IN (${mysql.escape(f.val)})`;
|
|
198
189
|
}
|
|
199
190
|
return [
|
|
200
|
-
mysql.escapeId(
|
|
191
|
+
mysql.escapeId(mapNameToMySQL(f.name)),
|
|
201
192
|
OP_MAP[f.op] || f.op,
|
|
202
193
|
mysql.escape(f.val),
|
|
203
194
|
].join(' ');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnyObject, CommonLogger, JsonSchemaObject, JsonSchemaRootObject } from '@naturalcycles/js-lib';
|
|
1
|
+
import type { AnyObject, CommonLogger, JsonSchemaObject, JsonSchemaRootObject } from '@naturalcycles/js-lib';
|
|
2
2
|
export interface MySQLTableStats {
|
|
3
3
|
Field: string;
|
|
4
4
|
Type: string;
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.jsonSchemaToMySQLDDL = jsonSchemaToMySQLDDL;
|
|
4
|
-
exports.mysqlTableStatsToJsonSchemaField = mysqlTableStatsToJsonSchemaField;
|
|
5
|
-
exports.mapNameToMySQL = mapNameToMySQL;
|
|
6
|
-
exports.mapNameFromMySQL = mapNameFromMySQL;
|
|
7
|
-
const tslib_1 = require("tslib");
|
|
8
|
-
const mysql = tslib_1.__importStar(require("mysql"));
|
|
1
|
+
import * as mysql from 'mysql';
|
|
9
2
|
/**
|
|
10
3
|
* It currently skips nullability and declares everything as "DEFAULT NULL".
|
|
11
4
|
*/
|
|
12
|
-
function jsonSchemaToMySQLDDL(table, schema, opt = {}) {
|
|
5
|
+
export function jsonSchemaToMySQLDDL(table, schema, opt = {}) {
|
|
13
6
|
const { engine = 'InnoDB' } = opt;
|
|
14
7
|
const lines = [`CREATE TABLE ${mysql.escapeId(table)} (`];
|
|
15
8
|
const innerLines = Object.entries(schema.properties).map(([k, s]) => {
|
|
@@ -59,7 +52,7 @@ function jsonSchemaToMySQLDDL(table, schema, opt = {}) {
|
|
|
59
52
|
lines.push(`) ENGINE=${engine}`);
|
|
60
53
|
return lines.join('\n');
|
|
61
54
|
}
|
|
62
|
-
function mysqlTableStatsToJsonSchemaField(table, stats, logger) {
|
|
55
|
+
export function mysqlTableStatsToJsonSchemaField(table, stats, logger) {
|
|
63
56
|
const s = {
|
|
64
57
|
$id: `${table}.schema.json`,
|
|
65
58
|
type: 'object',
|
|
@@ -101,9 +94,9 @@ function mysqlTableStatsToJsonSchemaField(table, stats, logger) {
|
|
|
101
94
|
*
|
|
102
95
|
* @param name
|
|
103
96
|
*/
|
|
104
|
-
function mapNameToMySQL(name) {
|
|
97
|
+
export function mapNameToMySQL(name) {
|
|
105
98
|
return name.replaceAll('.', '_dot_');
|
|
106
99
|
}
|
|
107
|
-
function mapNameFromMySQL(name) {
|
|
100
|
+
export function mapNameFromMySQL(name) {
|
|
108
101
|
return name.replaceAll('_dot_', '.');
|
|
109
102
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/mysql-lib",
|
|
3
|
+
"type": "module",
|
|
3
4
|
"scripts": {
|
|
4
5
|
"prepare": "husky",
|
|
5
6
|
"build": "dev-lib build",
|
|
@@ -9,17 +10,19 @@
|
|
|
9
10
|
"lbt": "dev-lib lbt"
|
|
10
11
|
},
|
|
11
12
|
"dependencies": {
|
|
12
|
-
"@naturalcycles/db-lib": "^
|
|
13
|
-
"@naturalcycles/js-lib": "^
|
|
14
|
-
"@naturalcycles/nodejs-lib": "^
|
|
13
|
+
"@naturalcycles/db-lib": "^10",
|
|
14
|
+
"@naturalcycles/js-lib": "^15",
|
|
15
|
+
"@naturalcycles/nodejs-lib": "^14",
|
|
15
16
|
"@types/mysql": "^2",
|
|
16
17
|
"mysql": "^2"
|
|
17
18
|
},
|
|
18
19
|
"devDependencies": {
|
|
19
|
-
"@naturalcycles/dev-lib": "^
|
|
20
|
+
"@naturalcycles/dev-lib": "^18",
|
|
20
21
|
"@types/node": "^22",
|
|
22
|
+
"@vitest/coverage-v8": "^3",
|
|
21
23
|
"dotenv": "^16",
|
|
22
|
-
"
|
|
24
|
+
"tsx": "^4",
|
|
25
|
+
"vitest": "^3"
|
|
23
26
|
},
|
|
24
27
|
"files": [
|
|
25
28
|
"dist",
|
|
@@ -41,7 +44,7 @@
|
|
|
41
44
|
"engines": {
|
|
42
45
|
"node": ">=22.12.0"
|
|
43
46
|
},
|
|
44
|
-
"version": "
|
|
47
|
+
"version": "4.0.1",
|
|
45
48
|
"description": "MySQL client implementing CommonDB interface",
|
|
46
49
|
"keywords": [
|
|
47
50
|
"mysql",
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './mysql.db'
|
|
2
|
-
export * from './mysqlKeyValueDB'
|
|
3
|
-
export { jsonSchemaToMySQLDDL } from './schema/mysql.schema.util'
|
|
1
|
+
export * from './mysql.db.js'
|
|
2
|
+
export * from './mysqlKeyValueDB.js'
|
|
3
|
+
export { jsonSchemaToMySQLDDL } from './schema/mysql.schema.util.js'
|
package/src/mysql.db.ts
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { Readable, Transform } from 'node:stream'
|
|
2
2
|
import { promisify } from 'node:util'
|
|
3
|
-
import {
|
|
4
|
-
BaseCommonDB,
|
|
3
|
+
import type {
|
|
5
4
|
CommonDB,
|
|
6
5
|
CommonDBCreateOptions,
|
|
7
|
-
commonDBFullSupport,
|
|
8
6
|
CommonDBOptions,
|
|
9
7
|
CommonDBSaveOptions,
|
|
10
8
|
CommonDBSupport,
|
|
11
|
-
CommonDBType,
|
|
12
|
-
DBQuery,
|
|
13
9
|
RunQueryResult,
|
|
14
10
|
} from '@naturalcycles/db-lib'
|
|
11
|
+
import { BaseCommonDB, commonDBFullSupport, CommonDBType, DBQuery } from '@naturalcycles/db-lib'
|
|
12
|
+
import type {
|
|
13
|
+
CommonLogger,
|
|
14
|
+
JsonSchemaObject,
|
|
15
|
+
JsonSchemaRootObject,
|
|
16
|
+
ObjectWithId,
|
|
17
|
+
} from '@naturalcycles/js-lib'
|
|
15
18
|
import {
|
|
16
19
|
_assert,
|
|
17
20
|
_filterUndefinedValues,
|
|
@@ -19,14 +22,11 @@ import {
|
|
|
19
22
|
_mapValues,
|
|
20
23
|
_Memo,
|
|
21
24
|
_omit,
|
|
22
|
-
CommonLogger,
|
|
23
25
|
commonLoggerPrefix,
|
|
24
|
-
JsonSchemaObject,
|
|
25
|
-
JsonSchemaRootObject,
|
|
26
|
-
ObjectWithId,
|
|
27
26
|
} from '@naturalcycles/js-lib'
|
|
28
|
-
import { ReadableTyped
|
|
29
|
-
import {
|
|
27
|
+
import type { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
28
|
+
import { white } from '@naturalcycles/nodejs-lib'
|
|
29
|
+
import type {
|
|
30
30
|
Connection,
|
|
31
31
|
OkPacket,
|
|
32
32
|
Pool,
|
|
@@ -36,13 +36,18 @@ import {
|
|
|
36
36
|
TypeCast,
|
|
37
37
|
} from 'mysql'
|
|
38
38
|
import * as mysql from 'mysql'
|
|
39
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
dbQueryToSQLDelete,
|
|
41
|
+
dbQueryToSQLSelect,
|
|
42
|
+
dbQueryToSQLUpdate,
|
|
43
|
+
insertSQL,
|
|
44
|
+
} from './query.util.js'
|
|
45
|
+
import type { MySQLTableStats } from './schema/mysql.schema.util.js'
|
|
40
46
|
import {
|
|
41
47
|
jsonSchemaToMySQLDDL,
|
|
42
48
|
mapNameFromMySQL,
|
|
43
|
-
MySQLTableStats,
|
|
44
49
|
mysqlTableStatsToJsonSchemaField,
|
|
45
|
-
} from './schema/mysql.schema.util'
|
|
50
|
+
} from './schema/mysql.schema.util.js'
|
|
46
51
|
|
|
47
52
|
export interface MysqlDBOptions extends CommonDBOptions {}
|
|
48
53
|
export interface MysqlDBSaveOptions<ROW extends ObjectWithId> extends CommonDBSaveOptions<ROW> {}
|
package/src/mysqlKeyValueDB.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { Transform } from 'node:stream'
|
|
2
|
-
import {
|
|
2
|
+
import type {
|
|
3
3
|
CommonDBCreateOptions,
|
|
4
4
|
CommonKeyValueDB,
|
|
5
|
-
commonKeyValueDBFullSupport,
|
|
6
5
|
KeyValueDBTuple,
|
|
7
6
|
} from '@naturalcycles/db-lib'
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
7
|
+
import { commonKeyValueDBFullSupport } from '@naturalcycles/db-lib'
|
|
8
|
+
import type { IncrementTuple } from '@naturalcycles/db-lib/dist/kv/commonKeyValueDB.js'
|
|
9
|
+
import type { ObjectWithId } from '@naturalcycles/js-lib'
|
|
10
|
+
import { AppError, pMap } from '@naturalcycles/js-lib'
|
|
11
|
+
import type { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
12
|
+
import type { QueryOptions } from 'mysql'
|
|
13
|
+
import type { MysqlDBCfg } from './mysql.db.js'
|
|
14
|
+
import { MysqlDB } from './mysql.db.js'
|
|
13
15
|
|
|
14
16
|
interface KeyValueObject {
|
|
15
17
|
id: string
|
package/src/query.util.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { DBQuery, DBQueryFilterOperator } from '@naturalcycles/db-lib'
|
|
2
|
-
import {
|
|
1
|
+
import type { DBQuery, DBQueryFilterOperator } from '@naturalcycles/db-lib'
|
|
2
|
+
import type { AnyObjectWithId, CommonLogger } from '@naturalcycles/js-lib'
|
|
3
|
+
import { _hb } from '@naturalcycles/js-lib'
|
|
3
4
|
import { white, yellow } from '@naturalcycles/nodejs-lib'
|
|
4
|
-
import { QueryOptions } from 'mysql'
|
|
5
|
+
import type { QueryOptions } from 'mysql'
|
|
5
6
|
import * as mysql from 'mysql'
|
|
6
|
-
import { mapNameToMySQL } from './schema/mysql.schema.util'
|
|
7
|
+
import { mapNameToMySQL } from './schema/mysql.schema.util.js'
|
|
7
8
|
|
|
8
9
|
const MAX_PACKET_SIZE = 1024 * 1024 // 1Mb
|
|
9
10
|
const MAX_ROW_SIZE = 800 * 1024 // 1Mb - margin
|