@naturalcycles/mysql-lib 3.7.1 → 3.9.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/dbAdapter.js +0 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -3
- package/dist/mysql.db.d.ts +18 -11
- package/dist/mysql.db.js +175 -181
- package/dist/query.util.d.ts +7 -6
- package/dist/query.util.js +18 -11
- package/dist/schema/mysql.schema.util.d.ts +4 -3
- package/dist/schema/mysql.schema.util.js +72 -49
- package/package.json +12 -13
- package/src/index.ts +4 -9
- package/src/mysql.db.ts +77 -61
- package/src/query.util.ts +25 -14
- package/src/schema/mysql.schema.util.ts +80 -51
- package/CHANGELOG.md +0 -191
- package/dist/dbAdapter.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mysql.db.js.map +0 -1
- package/dist/query.util.js.map +0 -1
- package/dist/schema/mysql.schema.util.js.map +0 -1
package/dist/dbAdapter.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getDBAdapter } from './dbAdapter';
|
|
2
2
|
import { MysqlDB, MysqlDBCfg, MysqlDBOptions, MysqlDBSaveOptions } from './mysql.db';
|
|
3
|
-
import {
|
|
4
|
-
export {
|
|
3
|
+
import { jsonSchemaToMySQLDDL } from './schema/mysql.schema.util';
|
|
4
|
+
export type { MysqlDBCfg, MysqlDBOptions, MysqlDBSaveOptions };
|
|
5
|
+
export { MysqlDB, jsonSchemaToMySQLDDL, getDBAdapter };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDBAdapter = exports.
|
|
3
|
+
exports.getDBAdapter = exports.jsonSchemaToMySQLDDL = exports.MysqlDB = void 0;
|
|
4
4
|
const dbAdapter_1 = require("./dbAdapter");
|
|
5
5
|
Object.defineProperty(exports, "getDBAdapter", { enumerable: true, get: function () { return dbAdapter_1.getDBAdapter; } });
|
|
6
6
|
const mysql_db_1 = require("./mysql.db");
|
|
7
7
|
Object.defineProperty(exports, "MysqlDB", { enumerable: true, get: function () { return mysql_db_1.MysqlDB; } });
|
|
8
8
|
const mysql_schema_util_1 = require("./schema/mysql.schema.util");
|
|
9
|
-
Object.defineProperty(exports, "
|
|
10
|
-
//# sourceMappingURL=index.js.map
|
|
9
|
+
Object.defineProperty(exports, "jsonSchemaToMySQLDDL", { enumerable: true, get: function () { return mysql_schema_util_1.jsonSchemaToMySQLDDL; } });
|
package/dist/mysql.db.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { BaseCommonDB,
|
|
1
|
+
import { BaseCommonDB, CommonDB, CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, DBQuery, RunQueryResult } from '@naturalcycles/db-lib';
|
|
2
|
+
import { AnyObjectWithId, CommonLogger, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib';
|
|
2
3
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
3
4
|
import { Connection, Pool, PoolConfig, PoolConnection, QueryOptions } from 'mysql';
|
|
4
5
|
export interface MysqlDBOptions extends CommonDBOptions {
|
|
5
6
|
}
|
|
6
|
-
export interface MysqlDBSaveOptions extends CommonDBSaveOptions {
|
|
7
|
+
export interface MysqlDBSaveOptions<ROW extends ObjectWithId = AnyObjectWithId> extends CommonDBSaveOptions<ROW> {
|
|
7
8
|
}
|
|
8
9
|
/**
|
|
9
10
|
* @default false / undefined
|
|
@@ -17,10 +18,16 @@ export interface MysqlDBCfg extends PoolConfig {
|
|
|
17
18
|
* If true - will emit logs of connection events.
|
|
18
19
|
*/
|
|
19
20
|
debugConnections?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Default to `console`
|
|
23
|
+
*/
|
|
24
|
+
logger?: CommonLogger;
|
|
20
25
|
}
|
|
21
26
|
export declare class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
22
27
|
constructor(cfg?: MysqlDBCfg);
|
|
23
|
-
cfg: MysqlDBCfg
|
|
28
|
+
cfg: MysqlDBCfg & {
|
|
29
|
+
logger: CommonLogger;
|
|
30
|
+
};
|
|
24
31
|
ping(): Promise<void>;
|
|
25
32
|
pool(): Pool;
|
|
26
33
|
close(): Promise<void>;
|
|
@@ -34,16 +41,16 @@ export declare class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
34
41
|
*/
|
|
35
42
|
createSingleConnection(): Promise<Connection>;
|
|
36
43
|
getByIds<ROW extends ObjectWithId>(table: string, ids: string[], opt?: MysqlDBOptions): Promise<ROW[]>;
|
|
37
|
-
runQuery<ROW extends ObjectWithId, OUT = ROW>(q: DBQuery<ROW>,
|
|
44
|
+
runQuery<ROW extends ObjectWithId, OUT = ROW>(q: DBQuery<ROW>, _opt?: MysqlDBOptions): Promise<RunQueryResult<OUT>>;
|
|
38
45
|
runSQL<RESULT>(q: QueryOptions): Promise<RESULT>;
|
|
39
|
-
runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>,
|
|
40
|
-
streamQuery<ROW extends ObjectWithId, OUT = ROW>(q: DBQuery<ROW>,
|
|
41
|
-
saveBatch<ROW extends
|
|
46
|
+
runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
|
|
47
|
+
streamQuery<ROW extends ObjectWithId, OUT = ROW>(q: DBQuery<ROW>, _opt?: MysqlDBOptions): ReadableTyped<OUT>;
|
|
48
|
+
saveBatch<ROW extends ObjectWithId>(table: string, _rows: ROW[], _opt?: MysqlDBSaveOptions<ROW>): Promise<void>;
|
|
42
49
|
/**
|
|
43
50
|
* Limitation: always returns [], regardless of which rows are actually deleted
|
|
44
51
|
*/
|
|
45
|
-
deleteByIds(table: string, ids: string[],
|
|
46
|
-
deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>,
|
|
52
|
+
deleteByIds(table: string, ids: string[], _opt?: MysqlDBOptions): Promise<number>;
|
|
53
|
+
deleteByQuery<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
|
|
47
54
|
/**
|
|
48
55
|
* Use with caution!
|
|
49
56
|
*/
|
|
@@ -51,7 +58,7 @@ export declare class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
51
58
|
/**
|
|
52
59
|
* dropIfExists=true needed as a safety check
|
|
53
60
|
*/
|
|
54
|
-
createTable(
|
|
61
|
+
createTable<ROW extends ObjectWithId>(table: string, schema: JsonSchemaObject<ROW>, opt?: CommonDBCreateOptions): Promise<void>;
|
|
55
62
|
getTables(): Promise<string[]>;
|
|
56
|
-
getTableSchema<ROW extends ObjectWithId>(table: string): Promise<
|
|
63
|
+
getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
|
|
57
64
|
}
|
package/dist/mysql.db.js
CHANGED
|
@@ -2,16 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MysqlDB = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const stream_1 = require("stream");
|
|
6
|
+
const util_1 = require("util");
|
|
5
7
|
const db_lib_1 = require("@naturalcycles/db-lib");
|
|
6
8
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
7
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
8
9
|
const colors_1 = require("@naturalcycles/nodejs-lib/dist/colors");
|
|
9
10
|
const mysql = require("mysql");
|
|
10
|
-
const stream_1 = require("stream");
|
|
11
|
-
const util_1 = require("util");
|
|
12
11
|
const query_util_1 = require("./query.util");
|
|
13
12
|
const mysql_schema_util_1 = require("./schema/mysql.schema.util");
|
|
14
|
-
const log = nodejs_lib_1.Debug('nc:mysql-lib');
|
|
15
13
|
const BOOLEAN_TYPES = new Set(['TINY', 'TINYINT', 'INT']);
|
|
16
14
|
const BOOLEAN_BIT_TYPES = new Set(['BIT']);
|
|
17
15
|
const typeCast = (field, next) => {
|
|
@@ -33,188 +31,184 @@ const typeCast = (field, next) => {
|
|
|
33
31
|
}
|
|
34
32
|
return next();
|
|
35
33
|
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
});
|
|
62
|
-
pool.on('connection', con => {
|
|
63
|
-
log(`connection(${con.threadId})`);
|
|
64
|
-
});
|
|
65
|
-
pool.on('enqueue', () => {
|
|
66
|
-
log(`enqueue`);
|
|
67
|
-
});
|
|
68
|
-
pool.on('release', con => {
|
|
69
|
-
log(`release(${con.threadId})`);
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
pool.on('error', err => {
|
|
73
|
-
log.error(`error`, err);
|
|
34
|
+
class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
35
|
+
constructor(cfg = {}) {
|
|
36
|
+
super();
|
|
37
|
+
this.cfg = {
|
|
38
|
+
typeCast,
|
|
39
|
+
// charset: 'utf8mb4', // for emoji support
|
|
40
|
+
// host: 'localhost',
|
|
41
|
+
// user: MYSQL_USER,
|
|
42
|
+
// password: MYSQL_PW,
|
|
43
|
+
// database: MYSQL_DB,
|
|
44
|
+
...cfg,
|
|
45
|
+
logger: (0, js_lib_1.commonLoggerPrefix)(cfg.logger || console, '[mysql]'),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async ping() {
|
|
49
|
+
const con = await this.getConnection();
|
|
50
|
+
con.release();
|
|
51
|
+
}
|
|
52
|
+
pool() {
|
|
53
|
+
const pool = mysql.createPool(this.cfg);
|
|
54
|
+
const { host, database, logger } = this.cfg;
|
|
55
|
+
logger.log(`connected to ${(0, colors_1.white)(host + '/' + database)}`);
|
|
56
|
+
if (this.cfg.debugConnections) {
|
|
57
|
+
pool.on('acquire', con => {
|
|
58
|
+
logger.log(`acquire(${con.threadId})`);
|
|
74
59
|
});
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
async close() {
|
|
78
|
-
const pool = this.pool();
|
|
79
|
-
await util_1.promisify(pool.end.bind(pool));
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Be careful to always call `con.release()` when you get connection with this method.
|
|
83
|
-
*/
|
|
84
|
-
async getConnection() {
|
|
85
|
-
const pool = this.pool();
|
|
86
|
-
return util_1.promisify(pool.getConnection.bind(pool))();
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Manually create a single (not pool) connection.
|
|
90
|
-
* Be careful to manage this connection yourself (open, release, etc).
|
|
91
|
-
*/
|
|
92
|
-
async createSingleConnection() {
|
|
93
|
-
const con = mysql.createConnection(this.cfg);
|
|
94
|
-
await util_1.promisify(con.connect.bind(con))();
|
|
95
|
-
const { threadId } = con;
|
|
96
|
-
if (this.cfg.debugConnections) {
|
|
97
|
-
log(`createSingleConnection(${threadId})`);
|
|
98
|
-
con.on('connect', () => log(`createSingleConnection(${threadId}).connect`));
|
|
99
|
-
con.on('drain', () => log(`createSingleConnection(${threadId}).drain`));
|
|
100
|
-
con.on('enqueue', () => log(`createSingleConnection(${threadId}).enqueue`));
|
|
101
|
-
con.on('end', () => log(`createSingleConnection(${threadId}).end`));
|
|
102
|
-
}
|
|
103
|
-
con.on('error', err => {
|
|
104
|
-
log.error(`createSingleConnection(${threadId}).error`, err);
|
|
60
|
+
pool.on('connection', con => {
|
|
61
|
+
logger.log(`connection(${con.threadId})`);
|
|
105
62
|
});
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return [];
|
|
112
|
-
const q = new db_lib_1.DBQuery(table).filterEq('id', ids);
|
|
113
|
-
const { rows } = await this.runQuery(q, opt);
|
|
114
|
-
return rows.map(r => js_lib_1._mapKeys(r, (_v, k) => mysql_schema_util_1.mapNameFromMySQL(k)));
|
|
115
|
-
}
|
|
116
|
-
// QUERY
|
|
117
|
-
async runQuery(q, opt = {}) {
|
|
118
|
-
const sql = query_util_1.dbQueryToSQLSelect(q);
|
|
119
|
-
const rows = await this.runSQL({ sql });
|
|
120
|
-
return {
|
|
121
|
-
rows: rows.map(r => js_lib_1._mapKeys(js_lib_1._filterUndefinedValues(r, true), (_v, k) => mysql_schema_util_1.mapNameFromMySQL(k))),
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
async runSQL(q) {
|
|
125
|
-
if (this.cfg.logSQL)
|
|
126
|
-
log(q.sql, q.values);
|
|
127
|
-
return new Promise(async (resolve, reject) => {
|
|
128
|
-
this.pool().query(q, (err, res) => {
|
|
129
|
-
if (err)
|
|
130
|
-
return reject(err);
|
|
131
|
-
resolve(res);
|
|
132
|
-
});
|
|
63
|
+
pool.on('enqueue', () => {
|
|
64
|
+
logger.log(`enqueue`);
|
|
65
|
+
});
|
|
66
|
+
pool.on('release', con => {
|
|
67
|
+
logger.log(`release(${con.threadId})`);
|
|
133
68
|
});
|
|
134
69
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
await this.runSQL({ sql });
|
|
198
|
-
}
|
|
199
|
-
async getTables() {
|
|
200
|
-
return (await this.runSQL({ sql: `show tables` }))
|
|
201
|
-
.map(r => Object.values(r)[0])
|
|
202
|
-
.filter(Boolean);
|
|
203
|
-
}
|
|
204
|
-
async getTableSchema(table) {
|
|
205
|
-
const statsArray = await this.runSQL({
|
|
206
|
-
sql: `describe ${mysql.escapeId(table)}`,
|
|
70
|
+
pool.on('error', err => {
|
|
71
|
+
logger.error(err);
|
|
72
|
+
});
|
|
73
|
+
return pool;
|
|
74
|
+
}
|
|
75
|
+
async close() {
|
|
76
|
+
const pool = this.pool();
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
78
|
+
await (0, util_1.promisify)(pool.end.bind(pool));
|
|
79
|
+
this.cfg.logger.log('closed');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Be careful to always call `con.release()` when you get connection with this method.
|
|
83
|
+
*/
|
|
84
|
+
async getConnection() {
|
|
85
|
+
const pool = this.pool();
|
|
86
|
+
return await (0, util_1.promisify)(pool.getConnection.bind(pool))();
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Manually create a single (not pool) connection.
|
|
90
|
+
* Be careful to manage this connection yourself (open, release, etc).
|
|
91
|
+
*/
|
|
92
|
+
async createSingleConnection() {
|
|
93
|
+
const con = mysql.createConnection(this.cfg);
|
|
94
|
+
await (0, util_1.promisify)(con.connect.bind(con))();
|
|
95
|
+
const { threadId } = con;
|
|
96
|
+
if (this.cfg.debugConnections) {
|
|
97
|
+
this.cfg.logger.log(`createSingleConnection(${threadId})`);
|
|
98
|
+
con.on('connect', () => this.cfg.logger.log(`createSingleConnection(${threadId}).connect`));
|
|
99
|
+
con.on('drain', () => this.cfg.logger.log(`createSingleConnection(${threadId}).drain`));
|
|
100
|
+
con.on('enqueue', () => this.cfg.logger.log(`createSingleConnection(${threadId}).enqueue`));
|
|
101
|
+
con.on('end', () => this.cfg.logger.log(`createSingleConnection(${threadId}).end`));
|
|
102
|
+
}
|
|
103
|
+
con.on('error', err => {
|
|
104
|
+
this.cfg.logger.error(`createSingleConnection(${threadId}).error`, err);
|
|
105
|
+
});
|
|
106
|
+
return con;
|
|
107
|
+
}
|
|
108
|
+
// GET
|
|
109
|
+
async getByIds(table, ids, opt = {}) {
|
|
110
|
+
if (!ids.length)
|
|
111
|
+
return [];
|
|
112
|
+
const q = new db_lib_1.DBQuery(table).filterEq('id', ids);
|
|
113
|
+
const { rows } = await this.runQuery(q, opt);
|
|
114
|
+
return rows.map(r => (0, js_lib_1._mapKeys)(r, k => (0, mysql_schema_util_1.mapNameFromMySQL)(k)));
|
|
115
|
+
}
|
|
116
|
+
// QUERY
|
|
117
|
+
async runQuery(q, _opt = {}) {
|
|
118
|
+
const sql = (0, query_util_1.dbQueryToSQLSelect)(q);
|
|
119
|
+
const rows = await this.runSQL({ sql });
|
|
120
|
+
return {
|
|
121
|
+
rows: rows.map(r => (0, js_lib_1._mapKeys)((0, js_lib_1._filterNullishValues)(r, true), k => (0, mysql_schema_util_1.mapNameFromMySQL)(k))),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
async runSQL(q) {
|
|
125
|
+
if (this.cfg.logSQL)
|
|
126
|
+
this.cfg.logger.log(q.sql, q.values);
|
|
127
|
+
return await new Promise((resolve, reject) => {
|
|
128
|
+
this.pool().query(q, (err, res) => {
|
|
129
|
+
if (err)
|
|
130
|
+
return reject(err);
|
|
131
|
+
resolve(res);
|
|
207
132
|
});
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
async runQueryCount(q, _opt) {
|
|
136
|
+
const { rows } = await this.runQuery(q.select(['count(*) as _count']));
|
|
137
|
+
return rows[0]._count;
|
|
138
|
+
}
|
|
139
|
+
streamQuery(q, _opt = {}) {
|
|
140
|
+
const sql = (0, query_util_1.dbQueryToSQLSelect)(q);
|
|
141
|
+
if (this.cfg.logSQL)
|
|
142
|
+
this.cfg.logger.log(`stream: ${sql}`);
|
|
143
|
+
// return this.streamSQL(sql, opt)
|
|
144
|
+
return this.pool()
|
|
145
|
+
.query(sql)
|
|
146
|
+
.stream()
|
|
147
|
+
.pipe(new stream_1.Transform({
|
|
148
|
+
objectMode: true,
|
|
149
|
+
transform(row, _encoding, cb) {
|
|
150
|
+
cb(null, (0, js_lib_1._filterNullishValues)(row, true));
|
|
151
|
+
},
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
// SAVE
|
|
155
|
+
async saveBatch(table, _rows, _opt) {
|
|
156
|
+
if (!_rows.length)
|
|
157
|
+
return;
|
|
158
|
+
// Stringify object values
|
|
159
|
+
const rows = _rows.map(row => (0, js_lib_1._mapValues)(row, v => {
|
|
160
|
+
return v && typeof v === 'object' && !Buffer.isBuffer(v) ? JSON.stringify(v) : v;
|
|
161
|
+
}));
|
|
162
|
+
// inserts are split into multiple sentenses to respect the max_packet_size (1Mb usually)
|
|
163
|
+
const sqls = (0, query_util_1.insertSQL)(table, rows, 'INSERT', this.cfg.logger);
|
|
164
|
+
for await (const sql of sqls) {
|
|
165
|
+
await this.runSQL({ sql });
|
|
212
166
|
}
|
|
213
167
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
168
|
+
// DELETE
|
|
169
|
+
/**
|
|
170
|
+
* Limitation: always returns [], regardless of which rows are actually deleted
|
|
171
|
+
*/
|
|
172
|
+
async deleteByIds(table, ids, _opt) {
|
|
173
|
+
if (!ids.length)
|
|
174
|
+
return 0;
|
|
175
|
+
const sql = (0, query_util_1.dbQueryToSQLDelete)(new db_lib_1.DBQuery(table).filterEq('id', ids));
|
|
176
|
+
const res = await this.runSQL({ sql });
|
|
177
|
+
return res.affectedRows;
|
|
178
|
+
}
|
|
179
|
+
async deleteByQuery(q, _opt) {
|
|
180
|
+
const sql = (0, query_util_1.dbQueryToSQLDelete)(q);
|
|
181
|
+
const res = await this.runSQL({ sql });
|
|
182
|
+
return res.affectedRows;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Use with caution!
|
|
186
|
+
*/
|
|
187
|
+
async dropTable(table) {
|
|
188
|
+
await this.runSQL({ sql: `DROP TABLE IF EXISTS ${table}` });
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* dropIfExists=true needed as a safety check
|
|
192
|
+
*/
|
|
193
|
+
async createTable(table, schema, opt = {}) {
|
|
194
|
+
if (opt.dropIfExists)
|
|
195
|
+
await this.dropTable(table);
|
|
196
|
+
const sql = (0, mysql_schema_util_1.jsonSchemaToMySQLDDL)(table, schema);
|
|
197
|
+
await this.runSQL({ sql });
|
|
198
|
+
}
|
|
199
|
+
async getTables() {
|
|
200
|
+
return (await this.runSQL({ sql: `show tables` }))
|
|
201
|
+
.map(r => Object.values(r)[0])
|
|
202
|
+
.filter(Boolean);
|
|
203
|
+
}
|
|
204
|
+
async getTableSchema(table) {
|
|
205
|
+
const stats = await this.runSQL({
|
|
206
|
+
sql: `describe ${mysql.escapeId(table)}`,
|
|
207
|
+
});
|
|
208
|
+
return (0, mysql_schema_util_1.mysqlTableStatsToJsonSchemaField)(table, stats, this.cfg.logger);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
(0, tslib_1.__decorate)([
|
|
212
|
+
(0, js_lib_1._Memo)()
|
|
213
|
+
], MysqlDB.prototype, "pool", null);
|
|
219
214
|
exports.MysqlDB = MysqlDB;
|
|
220
|
-
//# sourceMappingURL=mysql.db.js.map
|
package/dist/query.util.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { DBQuery } from '@naturalcycles/db-lib';
|
|
2
|
+
import { CommonLogger } from '@naturalcycles/js-lib';
|
|
2
3
|
import { QueryOptions } from 'mysql';
|
|
3
|
-
export declare function dbQueryToSQLSelect(q: DBQuery): string;
|
|
4
|
-
export declare function dbQueryToSQLDelete(q: DBQuery): string;
|
|
4
|
+
export declare function dbQueryToSQLSelect(q: DBQuery<any>): string;
|
|
5
|
+
export declare function dbQueryToSQLDelete(q: DBQuery<any>): string;
|
|
5
6
|
/**
|
|
6
7
|
* Returns array of sql statements to respect the max sql size.
|
|
7
8
|
*/
|
|
8
|
-
export declare function insertSQL(table: string, records:
|
|
9
|
-
export declare function insertSQLSingle(table: string, record:
|
|
10
|
-
export declare function insertSQLSetSingle(table: string, record:
|
|
11
|
-
export declare function dbQueryToSQLUpdate(q: DBQuery
|
|
9
|
+
export declare function insertSQL(table: string, records: Record<any, any>[], verb?: 'INSERT' | 'REPLACE', logger?: CommonLogger): string[];
|
|
10
|
+
export declare function insertSQLSingle(table: string, record: Record<any, any>): string;
|
|
11
|
+
export declare function insertSQLSetSingle(table: string, record: Record<any, any>): QueryOptions;
|
|
12
|
+
export declare function dbQueryToSQLUpdate(q: DBQuery<any>, record: Record<any, any>): string;
|
package/dist/query.util.js
CHANGED
|
@@ -30,9 +30,10 @@ exports.dbQueryToSQLDelete = dbQueryToSQLDelete;
|
|
|
30
30
|
/**
|
|
31
31
|
* Returns array of sql statements to respect the max sql size.
|
|
32
32
|
*/
|
|
33
|
-
function insertSQL(table, records, verb = 'INSERT') {
|
|
33
|
+
function insertSQL(table, records, verb = 'INSERT', logger = console) {
|
|
34
34
|
// INSERT INTO table_name (column1, column2, column3, ...)
|
|
35
35
|
// VALUES (value1, value2, value3, ...);
|
|
36
|
+
// eslint-disable-next-line unicorn/no-array-reduce
|
|
36
37
|
const fieldSet = records.reduce((set, rec) => {
|
|
37
38
|
Object.keys(rec).forEach(field => set.add(field));
|
|
38
39
|
return set;
|
|
@@ -42,7 +43,7 @@ function insertSQL(table, records, verb = 'INSERT') {
|
|
|
42
43
|
verb,
|
|
43
44
|
`INTO`,
|
|
44
45
|
mysql.escapeId(table),
|
|
45
|
-
`(` + [...fields].map(f => mysql.escapeId(mysql_schema_util_1.mapNameToMySQL(f))).join(',') + `)`,
|
|
46
|
+
`(` + [...fields].map(f => mysql.escapeId((0, mysql_schema_util_1.mapNameToMySQL)(f))).join(',') + `)`,
|
|
46
47
|
`VALUES\n`,
|
|
47
48
|
].join(' ');
|
|
48
49
|
const valueRows = records.map(rec => {
|
|
@@ -70,7 +71,7 @@ function insertSQL(table, records, verb = 'INSERT') {
|
|
|
70
71
|
if (sql) {
|
|
71
72
|
sqls.push(sql); // last one
|
|
72
73
|
}
|
|
73
|
-
|
|
74
|
+
logger.log(`${(0, colors_1.white)(table)} large sql query (${(0, colors_1.yellow)((0, js_lib_1._hb)(full.length))}) was split into ${(0, colors_1.yellow)(sqls.length)} chunks`);
|
|
74
75
|
return sqls;
|
|
75
76
|
// todo: handle "upsert" later
|
|
76
77
|
}
|
|
@@ -83,7 +84,7 @@ function insertSQLSingle(table, record) {
|
|
|
83
84
|
mysql.escapeId(table),
|
|
84
85
|
`(` +
|
|
85
86
|
Object.keys(record)
|
|
86
|
-
.map(f => mysql.escapeId(mysql_schema_util_1.mapNameToMySQL(f)))
|
|
87
|
+
.map(f => mysql.escapeId((0, mysql_schema_util_1.mapNameToMySQL)(f)))
|
|
87
88
|
.join(',') +
|
|
88
89
|
`)`,
|
|
89
90
|
`\nVALUES`,
|
|
@@ -110,7 +111,7 @@ function dbQueryToSQLUpdate(q, record) {
|
|
|
110
111
|
mysql.escapeId(q.table),
|
|
111
112
|
`SET`,
|
|
112
113
|
Object.keys(record)
|
|
113
|
-
.map(f => mysql.escapeId(mysql_schema_util_1.mapNameToMySQL(f)) + ' = ?')
|
|
114
|
+
.map(f => mysql.escapeId((0, mysql_schema_util_1.mapNameToMySQL)(f)) + ' = ?')
|
|
114
115
|
.join(', '),
|
|
115
116
|
...whereTokens(q),
|
|
116
117
|
];
|
|
@@ -123,7 +124,7 @@ function selectTokens(q) {
|
|
|
123
124
|
fields = q._selectedFieldNames.length ? q._selectedFieldNames : ['id'];
|
|
124
125
|
}
|
|
125
126
|
// We don't do `escapeId` cause it'll ruin e.g SELECT `count *` FROM ...
|
|
126
|
-
return [`SELECT`, fields.map(f => mysql_schema_util_1.mapNameToMySQL(f)).join(', '), `FROM`, mysql.escapeId(q.table)];
|
|
127
|
+
return [`SELECT`, fields.map(f => (0, mysql_schema_util_1.mapNameToMySQL)(f)).join(', '), `FROM`, mysql.escapeId(q.table)];
|
|
127
128
|
}
|
|
128
129
|
function offsetLimitTokens(q) {
|
|
129
130
|
const tokens = [];
|
|
@@ -144,6 +145,9 @@ function orderTokens(q) {
|
|
|
144
145
|
q._orders.map(o => `\`${o.name}\` ${o.descending ? 'DESC' : 'ASC'}`).join(', '),
|
|
145
146
|
];
|
|
146
147
|
}
|
|
148
|
+
const OP_MAP = {
|
|
149
|
+
'==': '=',
|
|
150
|
+
};
|
|
147
151
|
function whereTokens(q) {
|
|
148
152
|
if (!q._filters.length)
|
|
149
153
|
return [];
|
|
@@ -154,17 +158,20 @@ function whereTokens(q) {
|
|
|
154
158
|
if (f.val === null || f.val === undefined) {
|
|
155
159
|
// special treatment
|
|
156
160
|
return [
|
|
157
|
-
mysql.escapeId(mysql_schema_util_1.mapNameToMySQL(f.name)),
|
|
158
|
-
f.op === '
|
|
161
|
+
mysql.escapeId((0, mysql_schema_util_1.mapNameToMySQL)(f.name)),
|
|
162
|
+
f.op === '==' ? 'IS NULL' : 'IS NOT NULL',
|
|
159
163
|
].join(' ');
|
|
160
164
|
}
|
|
161
165
|
if (Array.isArray(f.val)) {
|
|
162
166
|
// special case for arrays
|
|
163
|
-
return `${mysql.escapeId(mysql_schema_util_1.mapNameToMySQL(f.name))} IN (${mysql.escape(f.val)})`;
|
|
167
|
+
return `${mysql.escapeId((0, mysql_schema_util_1.mapNameToMySQL)(f.name))} IN (${mysql.escape(f.val)})`;
|
|
164
168
|
}
|
|
165
|
-
return [
|
|
169
|
+
return [
|
|
170
|
+
mysql.escapeId((0, mysql_schema_util_1.mapNameToMySQL)(f.name)),
|
|
171
|
+
OP_MAP[f.op] || f.op,
|
|
172
|
+
mysql.escape(f.val),
|
|
173
|
+
].join(' ');
|
|
166
174
|
})
|
|
167
175
|
.join(' AND '),
|
|
168
176
|
];
|
|
169
177
|
}
|
|
170
|
-
//# sourceMappingURL=query.util.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CommonLogger, JsonSchemaObject, JsonSchemaRootObject } from '@naturalcycles/js-lib';
|
|
2
2
|
export interface MySQLTableStats {
|
|
3
3
|
Field: string;
|
|
4
4
|
Type: string;
|
|
@@ -13,10 +13,11 @@ export interface MySQLSchemaOptions {
|
|
|
13
13
|
/**
|
|
14
14
|
* It currently skips nullability and declares everything as "DEFAULT NULL".
|
|
15
15
|
*/
|
|
16
|
-
export declare function
|
|
17
|
-
export declare function
|
|
16
|
+
export declare function jsonSchemaToMySQLDDL(table: string, schema: JsonSchemaObject<any>, opt?: MySQLSchemaOptions): string;
|
|
17
|
+
export declare function mysqlTableStatsToJsonSchemaField<T = any>(table: string, stats: MySQLTableStats[], logger: CommonLogger): JsonSchemaRootObject<T>;
|
|
18
18
|
/**
|
|
19
19
|
* Because MySQL doesn't support `.` in field names and escapes them as tableName + fieldName.
|
|
20
|
+
*
|
|
20
21
|
* @param name
|
|
21
22
|
*/
|
|
22
23
|
export declare function mapNameToMySQL(name: string): string;
|