@naturalcycles/mysql-lib 3.8.0 → 3.9.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/dist/mysql.db.d.ts +12 -6
- package/dist/mysql.db.js +30 -24
- package/dist/query.util.d.ts +2 -1
- package/dist/query.util.js +5 -5
- package/dist/schema/mysql.schema.util.d.ts +2 -2
- package/dist/schema/mysql.schema.util.js +3 -3
- package/package.json +2 -5
- package/readme.md +27 -6
- package/src/mysql.db.ts +53 -35
- package/src/query.util.ts +14 -13
- package/src/schema/mysql.schema.util.ts +4 -2
- package/CHANGELOG.md +0 -198
package/dist/mysql.db.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { BaseCommonDB,
|
|
2
|
-
import { JsonSchemaObject, JsonSchemaRootObject } from '@naturalcycles/js-lib';
|
|
1
|
+
import { BaseCommonDB, CommonDB, CommonDBCreateOptions, CommonDBOptions, CommonDBSaveOptions, DBQuery, RunQueryResult } from '@naturalcycles/db-lib';
|
|
2
|
+
import { AnyObjectWithId, CommonLogger, JsonSchemaObject, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib';
|
|
3
3
|
import { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
4
4
|
import { Connection, Pool, PoolConfig, PoolConnection, QueryOptions } from 'mysql';
|
|
5
5
|
export interface MysqlDBOptions extends CommonDBOptions {
|
|
6
6
|
}
|
|
7
|
-
export interface MysqlDBSaveOptions extends CommonDBSaveOptions {
|
|
7
|
+
export interface MysqlDBSaveOptions<ROW extends ObjectWithId = AnyObjectWithId> extends CommonDBSaveOptions<ROW> {
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* @default false / undefined
|
|
@@ -18,10 +18,16 @@ export interface MysqlDBCfg extends PoolConfig {
|
|
|
18
18
|
* If true - will emit logs of connection events.
|
|
19
19
|
*/
|
|
20
20
|
debugConnections?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Default to `console`
|
|
23
|
+
*/
|
|
24
|
+
logger?: CommonLogger;
|
|
21
25
|
}
|
|
22
26
|
export declare class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
23
27
|
constructor(cfg?: MysqlDBCfg);
|
|
24
|
-
cfg: MysqlDBCfg
|
|
28
|
+
cfg: MysqlDBCfg & {
|
|
29
|
+
logger: CommonLogger;
|
|
30
|
+
};
|
|
25
31
|
ping(): Promise<void>;
|
|
26
32
|
pool(): Pool;
|
|
27
33
|
close(): Promise<void>;
|
|
@@ -39,7 +45,7 @@ export declare class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
39
45
|
runSQL<RESULT>(q: QueryOptions): Promise<RESULT>;
|
|
40
46
|
runQueryCount<ROW extends ObjectWithId>(q: DBQuery<ROW>, _opt?: CommonDBOptions): Promise<number>;
|
|
41
47
|
streamQuery<ROW extends ObjectWithId, OUT = ROW>(q: DBQuery<ROW>, _opt?: MysqlDBOptions): ReadableTyped<OUT>;
|
|
42
|
-
saveBatch<ROW extends
|
|
48
|
+
saveBatch<ROW extends ObjectWithId>(table: string, _rows: ROW[], _opt?: MysqlDBSaveOptions<ROW>): Promise<void>;
|
|
43
49
|
/**
|
|
44
50
|
* Limitation: always returns [], regardless of which rows are actually deleted
|
|
45
51
|
*/
|
|
@@ -52,7 +58,7 @@ export declare class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
52
58
|
/**
|
|
53
59
|
* dropIfExists=true needed as a safety check
|
|
54
60
|
*/
|
|
55
|
-
createTable(table: string, schema: JsonSchemaObject
|
|
61
|
+
createTable<ROW extends ObjectWithId>(table: string, schema: JsonSchemaObject<ROW>, opt?: CommonDBCreateOptions): Promise<void>;
|
|
56
62
|
getTables(): Promise<string[]>;
|
|
57
63
|
getTableSchema<ROW extends ObjectWithId>(table: string): Promise<JsonSchemaRootObject<ROW>>;
|
|
58
64
|
}
|
package/dist/mysql.db.js
CHANGED
|
@@ -6,12 +6,10 @@ const stream_1 = require("stream");
|
|
|
6
6
|
const util_1 = require("util");
|
|
7
7
|
const db_lib_1 = require("@naturalcycles/db-lib");
|
|
8
8
|
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
9
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
10
9
|
const colors_1 = require("@naturalcycles/nodejs-lib/dist/colors");
|
|
11
10
|
const mysql = require("mysql");
|
|
12
11
|
const query_util_1 = require("./query.util");
|
|
13
12
|
const mysql_schema_util_1 = require("./schema/mysql.schema.util");
|
|
14
|
-
const log = (0, 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) => {
|
|
@@ -44,6 +42,7 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
44
42
|
// password: MYSQL_PW,
|
|
45
43
|
// database: MYSQL_DB,
|
|
46
44
|
...cfg,
|
|
45
|
+
logger: (0, js_lib_1.commonLoggerPrefix)(cfg.logger || console, '[mysql]'),
|
|
47
46
|
};
|
|
48
47
|
}
|
|
49
48
|
async ping() {
|
|
@@ -52,31 +51,32 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
52
51
|
}
|
|
53
52
|
pool() {
|
|
54
53
|
const pool = mysql.createPool(this.cfg);
|
|
55
|
-
const { host, database } = this.cfg;
|
|
56
|
-
log(`connected to ${(0, colors_1.white)(host + '/' + database)}`);
|
|
54
|
+
const { host, database, logger } = this.cfg;
|
|
55
|
+
logger.log(`connected to ${(0, colors_1.white)(host + '/' + database)}`);
|
|
57
56
|
if (this.cfg.debugConnections) {
|
|
58
57
|
pool.on('acquire', con => {
|
|
59
|
-
log(`acquire(${con.threadId})`);
|
|
58
|
+
logger.log(`acquire(${con.threadId})`);
|
|
60
59
|
});
|
|
61
60
|
pool.on('connection', con => {
|
|
62
|
-
log(`connection(${con.threadId})`);
|
|
61
|
+
logger.log(`connection(${con.threadId})`);
|
|
63
62
|
});
|
|
64
63
|
pool.on('enqueue', () => {
|
|
65
|
-
log(`enqueue`);
|
|
64
|
+
logger.log(`enqueue`);
|
|
66
65
|
});
|
|
67
66
|
pool.on('release', con => {
|
|
68
|
-
log(`release(${con.threadId})`);
|
|
67
|
+
logger.log(`release(${con.threadId})`);
|
|
69
68
|
});
|
|
70
69
|
}
|
|
71
70
|
pool.on('error', err => {
|
|
72
|
-
|
|
71
|
+
logger.error(err);
|
|
73
72
|
});
|
|
74
73
|
return pool;
|
|
75
74
|
}
|
|
76
75
|
async close() {
|
|
77
76
|
const pool = this.pool();
|
|
78
77
|
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
79
|
-
await (0, util_1.promisify)(pool.end.bind(pool));
|
|
78
|
+
await (0, util_1.promisify)(pool.end.bind(pool))();
|
|
79
|
+
this.cfg.logger.log('closed');
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
82
|
* Be careful to always call `con.release()` when you get connection with this method.
|
|
@@ -94,14 +94,14 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
94
94
|
await (0, util_1.promisify)(con.connect.bind(con))();
|
|
95
95
|
const { threadId } = con;
|
|
96
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`));
|
|
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
102
|
}
|
|
103
103
|
con.on('error', err => {
|
|
104
|
-
|
|
104
|
+
this.cfg.logger.error(`createSingleConnection(${threadId}).error`, err);
|
|
105
105
|
});
|
|
106
106
|
return con;
|
|
107
107
|
}
|
|
@@ -116,14 +116,20 @@ 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
|
-
const rows = await this.runSQL({ sql });
|
|
119
|
+
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
|
+
// edge case where 0 fields are selected
|
|
121
|
+
if (q._selectedFieldNames?.length === 0) {
|
|
122
|
+
return {
|
|
123
|
+
rows: rows.map(_ => ({})),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
120
126
|
return {
|
|
121
|
-
rows
|
|
127
|
+
rows,
|
|
122
128
|
};
|
|
123
129
|
}
|
|
124
130
|
async runSQL(q) {
|
|
125
131
|
if (this.cfg.logSQL)
|
|
126
|
-
log(q.sql, q.values);
|
|
132
|
+
this.cfg.logger.log(...[q.sql, q.values].filter(Boolean));
|
|
127
133
|
return await new Promise((resolve, reject) => {
|
|
128
134
|
this.pool().query(q, (err, res) => {
|
|
129
135
|
if (err)
|
|
@@ -139,7 +145,7 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
139
145
|
streamQuery(q, _opt = {}) {
|
|
140
146
|
const sql = (0, query_util_1.dbQueryToSQLSelect)(q);
|
|
141
147
|
if (this.cfg.logSQL)
|
|
142
|
-
log(`stream: ${sql}`);
|
|
148
|
+
this.cfg.logger.log(`stream: ${sql}`);
|
|
143
149
|
// return this.streamSQL(sql, opt)
|
|
144
150
|
return this.pool()
|
|
145
151
|
.query(sql)
|
|
@@ -147,7 +153,7 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
147
153
|
.pipe(new stream_1.Transform({
|
|
148
154
|
objectMode: true,
|
|
149
155
|
transform(row, _encoding, cb) {
|
|
150
|
-
cb(null, (0, js_lib_1.
|
|
156
|
+
cb(null, (0, js_lib_1._filterUndefinedValues)(row, true));
|
|
151
157
|
},
|
|
152
158
|
}));
|
|
153
159
|
}
|
|
@@ -156,11 +162,11 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
156
162
|
if (!_rows.length)
|
|
157
163
|
return;
|
|
158
164
|
// Stringify object values
|
|
159
|
-
const rows = _rows.map(row => (0, js_lib_1._mapValues)(row, v => {
|
|
165
|
+
const rows = _rows.map(row => (0, js_lib_1._mapValues)(row, (_k, v) => {
|
|
160
166
|
return v && typeof v === 'object' && !Buffer.isBuffer(v) ? JSON.stringify(v) : v;
|
|
161
167
|
}));
|
|
162
168
|
// inserts are split into multiple sentenses to respect the max_packet_size (1Mb usually)
|
|
163
|
-
const sqls = (0, query_util_1.insertSQL)(table, rows);
|
|
169
|
+
const sqls = (0, query_util_1.insertSQL)(table, rows, 'REPLACE', this.cfg.logger);
|
|
164
170
|
for await (const sql of sqls) {
|
|
165
171
|
await this.runSQL({ sql });
|
|
166
172
|
}
|
|
@@ -205,7 +211,7 @@ class MysqlDB extends db_lib_1.BaseCommonDB {
|
|
|
205
211
|
const stats = await this.runSQL({
|
|
206
212
|
sql: `describe ${mysql.escapeId(table)}`,
|
|
207
213
|
});
|
|
208
|
-
return (0, mysql_schema_util_1.mysqlTableStatsToJsonSchemaField)(table, stats);
|
|
214
|
+
return (0, mysql_schema_util_1.mysqlTableStatsToJsonSchemaField)(table, stats, this.cfg.logger);
|
|
209
215
|
}
|
|
210
216
|
}
|
|
211
217
|
(0, tslib_1.__decorate)([
|
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
4
|
export declare function dbQueryToSQLSelect(q: DBQuery<any>): string;
|
|
4
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,
|
|
9
|
+
export declare function insertSQL(table: string, rows: Record<any, any>[], verb?: 'INSERT' | 'REPLACE', logger?: CommonLogger): string[];
|
|
9
10
|
export declare function insertSQLSingle(table: string, record: Record<any, any>): string;
|
|
10
11
|
export declare function insertSQLSetSingle(table: string, record: Record<any, any>): QueryOptions;
|
|
11
12
|
export declare function dbQueryToSQLUpdate(q: DBQuery<any>, record: Record<any, any>): string;
|
package/dist/query.util.js
CHANGED
|
@@ -30,12 +30,12 @@ exports.dbQueryToSQLDelete = dbQueryToSQLDelete;
|
|
|
30
30
|
/**
|
|
31
31
|
* Returns array of sql statements to respect the max sql size.
|
|
32
32
|
*/
|
|
33
|
-
function insertSQL(table,
|
|
33
|
+
function insertSQL(table, rows, verb = 'INSERT', logger = console) {
|
|
34
34
|
// INSERT INTO table_name (column1, column2, column3, ...)
|
|
35
35
|
// VALUES (value1, value2, value3, ...);
|
|
36
36
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
37
|
-
const fieldSet =
|
|
38
|
-
Object.keys(
|
|
37
|
+
const fieldSet = rows.reduce((set, row) => {
|
|
38
|
+
Object.keys(row).forEach(field => set.add(field));
|
|
39
39
|
return set;
|
|
40
40
|
}, new Set());
|
|
41
41
|
const fields = [...fieldSet];
|
|
@@ -46,7 +46,7 @@ function insertSQL(table, records, verb = 'INSERT') {
|
|
|
46
46
|
`(` + [...fields].map(f => mysql.escapeId((0, mysql_schema_util_1.mapNameToMySQL)(f))).join(',') + `)`,
|
|
47
47
|
`VALUES\n`,
|
|
48
48
|
].join(' ');
|
|
49
|
-
const valueRows =
|
|
49
|
+
const valueRows = rows.map(rec => {
|
|
50
50
|
return `(` + fields.map(k => mysql.escape(rec[k])).join(',') + `)`;
|
|
51
51
|
});
|
|
52
52
|
const full = start + valueRows.join(',\n');
|
|
@@ -71,7 +71,7 @@ function insertSQL(table, records, verb = 'INSERT') {
|
|
|
71
71
|
if (sql) {
|
|
72
72
|
sqls.push(sql); // last one
|
|
73
73
|
}
|
|
74
|
-
|
|
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`);
|
|
75
75
|
return sqls;
|
|
76
76
|
// todo: handle "upsert" later
|
|
77
77
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { JsonSchemaObject, JsonSchemaRootObject } from '@naturalcycles/js-lib';
|
|
1
|
+
import { CommonLogger, JsonSchemaObject, JsonSchemaRootObject } from '@naturalcycles/js-lib';
|
|
2
2
|
export interface MySQLTableStats {
|
|
3
3
|
Field: string;
|
|
4
4
|
Type: string;
|
|
@@ -14,7 +14,7 @@ export interface MySQLSchemaOptions {
|
|
|
14
14
|
* It currently skips nullability and declares everything as "DEFAULT NULL".
|
|
15
15
|
*/
|
|
16
16
|
export declare function jsonSchemaToMySQLDDL(table: string, schema: JsonSchemaObject<any>, opt?: MySQLSchemaOptions): string;
|
|
17
|
-
export declare function mysqlTableStatsToJsonSchemaField<T = any>(table: string, stats: MySQLTableStats[]): JsonSchemaRootObject<T>;
|
|
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
|
*
|
|
@@ -56,7 +56,7 @@ function jsonSchemaToMySQLDDL(table, schema, opt = {}) {
|
|
|
56
56
|
return lines.join('\n');
|
|
57
57
|
}
|
|
58
58
|
exports.jsonSchemaToMySQLDDL = jsonSchemaToMySQLDDL;
|
|
59
|
-
function mysqlTableStatsToJsonSchemaField(table, stats) {
|
|
59
|
+
function mysqlTableStatsToJsonSchemaField(table, stats, logger) {
|
|
60
60
|
const s = {
|
|
61
61
|
$id: `${table}.schema.json`,
|
|
62
62
|
type: 'object',
|
|
@@ -80,14 +80,14 @@ function mysqlTableStatsToJsonSchemaField(table, stats) {
|
|
|
80
80
|
else if (t.startsWith('tinyint') || t.includes('(1)')) {
|
|
81
81
|
s.properties[name] = { type: 'boolean' };
|
|
82
82
|
}
|
|
83
|
-
else if (t.startsWith('int(')) {
|
|
83
|
+
else if (t === 'int' || t.startsWith('int(')) {
|
|
84
84
|
s.properties[name] = { type: 'integer' };
|
|
85
85
|
}
|
|
86
86
|
else if (t.startsWith('float')) {
|
|
87
87
|
s.properties[name] = { type: 'number' };
|
|
88
88
|
}
|
|
89
89
|
else {
|
|
90
|
-
|
|
90
|
+
logger.log(s);
|
|
91
91
|
throw new Error(`Unknown mysql field type ${name} ${stat.Type}`);
|
|
92
92
|
}
|
|
93
93
|
});
|
package/package.json
CHANGED
|
@@ -3,9 +3,6 @@
|
|
|
3
3
|
"scripts": {
|
|
4
4
|
"prepare": "husky install"
|
|
5
5
|
},
|
|
6
|
-
"peerDependencies": {
|
|
7
|
-
"@naturalcycles/db-lib": ">=7.0.0"
|
|
8
|
-
},
|
|
9
6
|
"dependencies": {
|
|
10
7
|
"@naturalcycles/db-lib": "^8.16.2",
|
|
11
8
|
"@naturalcycles/js-lib": "^14.47.0",
|
|
@@ -15,7 +12,7 @@
|
|
|
15
12
|
},
|
|
16
13
|
"devDependencies": {
|
|
17
14
|
"@naturalcycles/dev-lib": "^12.7.5",
|
|
18
|
-
"@types/node": "^
|
|
15
|
+
"@types/node": "^17.0.5",
|
|
19
16
|
"dotenv": "^10.0.0",
|
|
20
17
|
"jest": "^27.2.4"
|
|
21
18
|
},
|
|
@@ -39,7 +36,7 @@
|
|
|
39
36
|
"engines": {
|
|
40
37
|
"node": ">=14.15.0"
|
|
41
38
|
},
|
|
42
|
-
"version": "3.
|
|
39
|
+
"version": "3.9.2",
|
|
43
40
|
"description": "MySQL client implementing CommonDB interface",
|
|
44
41
|
"keywords": [
|
|
45
42
|
"mysql",
|
package/readme.md
CHANGED
|
@@ -3,12 +3,33 @@
|
|
|
3
3
|
> MySQL client implementing CommonDB interface
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@naturalcycles/mysql-lib)
|
|
6
|
-
[](https://circleci.com/gh/NaturalCycles/mysql-lib)
|
|
7
6
|
[](https://github.com/prettier/prettier)
|
|
8
7
|
|
|
9
|
-
#
|
|
8
|
+
# Quick start
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
todo
|
|
11
|
+
|
|
12
|
+
# Develop
|
|
13
|
+
|
|
14
|
+
Install MySQL server+client on Mac:
|
|
15
|
+
|
|
16
|
+
```shell
|
|
17
|
+
|
|
18
|
+
brew install mysql
|
|
19
|
+
|
|
20
|
+
# start
|
|
21
|
+
|
|
22
|
+
mysql.server start
|
|
23
|
+
|
|
24
|
+
# secure
|
|
25
|
+
|
|
26
|
+
mysql_secure_installation
|
|
27
|
+
|
|
28
|
+
# connect
|
|
29
|
+
|
|
30
|
+
mysql -uroot
|
|
31
|
+
|
|
32
|
+
# Default options are read from the following files in the given order:
|
|
33
|
+
# /etc/my.cnf /etc/mysql/my.cnf /opt/homebrew/etc/my.cnf ~/.my.cnf
|
|
34
|
+
|
|
35
|
+
```
|
package/src/mysql.db.ts
CHANGED
|
@@ -2,24 +2,26 @@ import { Transform } from 'stream'
|
|
|
2
2
|
import { promisify } from 'util'
|
|
3
3
|
import {
|
|
4
4
|
BaseCommonDB,
|
|
5
|
-
BaseDBEntity,
|
|
6
5
|
CommonDB,
|
|
7
6
|
CommonDBCreateOptions,
|
|
8
7
|
CommonDBOptions,
|
|
9
8
|
CommonDBSaveOptions,
|
|
10
9
|
DBQuery,
|
|
11
|
-
ObjectWithId,
|
|
12
10
|
RunQueryResult,
|
|
13
11
|
} from '@naturalcycles/db-lib'
|
|
14
12
|
import {
|
|
15
|
-
|
|
13
|
+
_filterUndefinedValues,
|
|
16
14
|
_mapKeys,
|
|
17
15
|
_mapValues,
|
|
18
16
|
_Memo,
|
|
17
|
+
AnyObjectWithId,
|
|
18
|
+
CommonLogger,
|
|
19
|
+
commonLoggerPrefix,
|
|
19
20
|
JsonSchemaObject,
|
|
20
21
|
JsonSchemaRootObject,
|
|
22
|
+
ObjectWithId,
|
|
21
23
|
} from '@naturalcycles/js-lib'
|
|
22
|
-
import {
|
|
24
|
+
import { ReadableTyped } from '@naturalcycles/nodejs-lib'
|
|
23
25
|
import { white } from '@naturalcycles/nodejs-lib/dist/colors'
|
|
24
26
|
import { Connection, Pool, PoolConfig, PoolConnection, QueryOptions, TypeCast } from 'mysql'
|
|
25
27
|
import * as mysql from 'mysql'
|
|
@@ -32,7 +34,8 @@ import {
|
|
|
32
34
|
} from './schema/mysql.schema.util'
|
|
33
35
|
|
|
34
36
|
export interface MysqlDBOptions extends CommonDBOptions {}
|
|
35
|
-
export interface MysqlDBSaveOptions extends
|
|
37
|
+
export interface MysqlDBSaveOptions<ROW extends ObjectWithId = AnyObjectWithId>
|
|
38
|
+
extends CommonDBSaveOptions<ROW> {}
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
41
|
* @default false / undefined
|
|
@@ -47,9 +50,12 @@ export interface MysqlDBCfg extends PoolConfig {
|
|
|
47
50
|
* If true - will emit logs of connection events.
|
|
48
51
|
*/
|
|
49
52
|
debugConnections?: boolean
|
|
50
|
-
}
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Default to `console`
|
|
56
|
+
*/
|
|
57
|
+
logger?: CommonLogger
|
|
58
|
+
}
|
|
53
59
|
|
|
54
60
|
const BOOLEAN_TYPES = new Set(['TINY', 'TINYINT', 'INT'])
|
|
55
61
|
const BOOLEAN_BIT_TYPES = new Set(['BIT'])
|
|
@@ -85,10 +91,11 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
85
91
|
// password: MYSQL_PW,
|
|
86
92
|
// database: MYSQL_DB,
|
|
87
93
|
...cfg,
|
|
94
|
+
logger: commonLoggerPrefix(cfg.logger || console, '[mysql]'),
|
|
88
95
|
}
|
|
89
96
|
}
|
|
90
97
|
|
|
91
|
-
cfg
|
|
98
|
+
cfg: MysqlDBCfg & { logger: CommonLogger }
|
|
92
99
|
|
|
93
100
|
override async ping(): Promise<void> {
|
|
94
101
|
const con = await this.getConnection()
|
|
@@ -98,29 +105,29 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
98
105
|
@_Memo()
|
|
99
106
|
pool(): Pool {
|
|
100
107
|
const pool = mysql.createPool(this.cfg)
|
|
101
|
-
const { host, database } = this.cfg
|
|
102
|
-
log(`connected to ${white(host + '/' + database)}`)
|
|
108
|
+
const { host, database, logger } = this.cfg
|
|
109
|
+
logger.log(`connected to ${white(host + '/' + database)}`)
|
|
103
110
|
|
|
104
111
|
if (this.cfg.debugConnections) {
|
|
105
112
|
pool.on('acquire', con => {
|
|
106
|
-
log(`acquire(${con.threadId})`)
|
|
113
|
+
logger.log(`acquire(${con.threadId})`)
|
|
107
114
|
})
|
|
108
115
|
|
|
109
116
|
pool.on('connection', con => {
|
|
110
|
-
log(`connection(${con.threadId})`)
|
|
117
|
+
logger.log(`connection(${con.threadId})`)
|
|
111
118
|
})
|
|
112
119
|
|
|
113
120
|
pool.on('enqueue', () => {
|
|
114
|
-
log(`enqueue`)
|
|
121
|
+
logger.log(`enqueue`)
|
|
115
122
|
})
|
|
116
123
|
|
|
117
124
|
pool.on('release', con => {
|
|
118
|
-
log(`release(${con.threadId})`)
|
|
125
|
+
logger.log(`release(${con.threadId})`)
|
|
119
126
|
})
|
|
120
127
|
}
|
|
121
128
|
|
|
122
129
|
pool.on('error', err => {
|
|
123
|
-
|
|
130
|
+
logger.error(err)
|
|
124
131
|
})
|
|
125
132
|
|
|
126
133
|
return pool
|
|
@@ -129,7 +136,8 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
129
136
|
async close(): Promise<void> {
|
|
130
137
|
const pool = this.pool()
|
|
131
138
|
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
132
|
-
await promisify(pool.end.bind(pool))
|
|
139
|
+
await promisify(pool.end.bind(pool))()
|
|
140
|
+
this.cfg.logger.log('closed')
|
|
133
141
|
}
|
|
134
142
|
|
|
135
143
|
/**
|
|
@@ -150,16 +158,16 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
150
158
|
const { threadId } = con
|
|
151
159
|
|
|
152
160
|
if (this.cfg.debugConnections) {
|
|
153
|
-
log(`createSingleConnection(${threadId})`)
|
|
161
|
+
this.cfg.logger.log(`createSingleConnection(${threadId})`)
|
|
154
162
|
|
|
155
|
-
con.on('connect', () => log(`createSingleConnection(${threadId}).connect`))
|
|
156
|
-
con.on('drain', () => log(`createSingleConnection(${threadId}).drain`))
|
|
157
|
-
con.on('enqueue', () => log(`createSingleConnection(${threadId}).enqueue`))
|
|
158
|
-
con.on('end', () => log(`createSingleConnection(${threadId}).end`))
|
|
163
|
+
con.on('connect', () => this.cfg.logger.log(`createSingleConnection(${threadId}).connect`))
|
|
164
|
+
con.on('drain', () => this.cfg.logger.log(`createSingleConnection(${threadId}).drain`))
|
|
165
|
+
con.on('enqueue', () => this.cfg.logger.log(`createSingleConnection(${threadId}).enqueue`))
|
|
166
|
+
con.on('end', () => this.cfg.logger.log(`createSingleConnection(${threadId}).end`))
|
|
159
167
|
}
|
|
160
168
|
|
|
161
169
|
con.on('error', err => {
|
|
162
|
-
|
|
170
|
+
this.cfg.logger.error(`createSingleConnection(${threadId}).error`, err)
|
|
163
171
|
})
|
|
164
172
|
|
|
165
173
|
return con
|
|
@@ -183,14 +191,24 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
183
191
|
_opt: MysqlDBOptions = {},
|
|
184
192
|
): Promise<RunQueryResult<OUT>> {
|
|
185
193
|
const sql = dbQueryToSQLSelect(q)
|
|
186
|
-
const rows = await this.runSQL<ROW[]>({ sql })
|
|
194
|
+
const rows = (await this.runSQL<ROW[]>({ sql })).map(
|
|
195
|
+
row => _mapKeys(_filterUndefinedValues(row, true), k => mapNameFromMySQL(k)) as any,
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
// edge case where 0 fields are selected
|
|
199
|
+
if (q._selectedFieldNames?.length === 0) {
|
|
200
|
+
return {
|
|
201
|
+
rows: rows.map(_ => ({} as any)),
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
187
205
|
return {
|
|
188
|
-
rows
|
|
206
|
+
rows,
|
|
189
207
|
}
|
|
190
208
|
}
|
|
191
209
|
|
|
192
210
|
async runSQL<RESULT>(q: QueryOptions): Promise<RESULT> {
|
|
193
|
-
if (this.cfg.logSQL) log(q.sql, q.values)
|
|
211
|
+
if (this.cfg.logSQL) this.cfg.logger.log(...[q.sql, q.values].filter(Boolean))
|
|
194
212
|
|
|
195
213
|
return await new Promise<RESULT>((resolve, reject) => {
|
|
196
214
|
this.pool().query(q, (err, res) => {
|
|
@@ -204,7 +222,7 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
204
222
|
q: DBQuery<ROW>,
|
|
205
223
|
_opt?: CommonDBOptions,
|
|
206
224
|
): Promise<number> {
|
|
207
|
-
const { rows } = await this.runQuery(q.select(['count(*) as _count']))
|
|
225
|
+
const { rows } = await this.runQuery(q.select(['count(*) as _count' as any]))
|
|
208
226
|
return (rows[0] as any)._count
|
|
209
227
|
}
|
|
210
228
|
|
|
@@ -214,7 +232,7 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
214
232
|
): ReadableTyped<OUT> {
|
|
215
233
|
const sql = dbQueryToSQLSelect(q)
|
|
216
234
|
|
|
217
|
-
if (this.cfg.logSQL) log(`stream: ${sql}`)
|
|
235
|
+
if (this.cfg.logSQL) this.cfg.logger.log(`stream: ${sql}`)
|
|
218
236
|
|
|
219
237
|
// return this.streamSQL(sql, opt)
|
|
220
238
|
return this.pool()
|
|
@@ -224,29 +242,29 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
224
242
|
new Transform({
|
|
225
243
|
objectMode: true,
|
|
226
244
|
transform(row, _encoding, cb) {
|
|
227
|
-
cb(null,
|
|
245
|
+
cb(null, _filterUndefinedValues(row, true))
|
|
228
246
|
},
|
|
229
247
|
}),
|
|
230
248
|
)
|
|
231
249
|
}
|
|
232
250
|
|
|
233
251
|
// SAVE
|
|
234
|
-
override async saveBatch<ROW extends
|
|
252
|
+
override async saveBatch<ROW extends ObjectWithId>(
|
|
235
253
|
table: string,
|
|
236
254
|
_rows: ROW[],
|
|
237
|
-
_opt?: MysqlDBSaveOptions
|
|
255
|
+
_opt?: MysqlDBSaveOptions<ROW>,
|
|
238
256
|
): Promise<void> {
|
|
239
257
|
if (!_rows.length) return
|
|
240
258
|
|
|
241
259
|
// Stringify object values
|
|
242
260
|
const rows = _rows.map(row =>
|
|
243
|
-
_mapValues(row, v => {
|
|
261
|
+
_mapValues(row, (_k, v) => {
|
|
244
262
|
return v && typeof v === 'object' && !Buffer.isBuffer(v) ? JSON.stringify(v) : v
|
|
245
263
|
}),
|
|
246
264
|
)
|
|
247
265
|
|
|
248
266
|
// inserts are split into multiple sentenses to respect the max_packet_size (1Mb usually)
|
|
249
|
-
const sqls = insertSQL(table, rows)
|
|
267
|
+
const sqls = insertSQL(table, rows, 'REPLACE', this.cfg.logger)
|
|
250
268
|
|
|
251
269
|
for await (const sql of sqls) {
|
|
252
270
|
await this.runSQL({ sql })
|
|
@@ -283,9 +301,9 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
283
301
|
/**
|
|
284
302
|
* dropIfExists=true needed as a safety check
|
|
285
303
|
*/
|
|
286
|
-
override async createTable(
|
|
304
|
+
override async createTable<ROW extends ObjectWithId>(
|
|
287
305
|
table: string,
|
|
288
|
-
schema: JsonSchemaObject
|
|
306
|
+
schema: JsonSchemaObject<ROW>,
|
|
289
307
|
opt: CommonDBCreateOptions = {},
|
|
290
308
|
): Promise<void> {
|
|
291
309
|
if (opt.dropIfExists) await this.dropTable(table)
|
|
@@ -307,6 +325,6 @@ export class MysqlDB extends BaseCommonDB implements CommonDB {
|
|
|
307
325
|
sql: `describe ${mysql.escapeId(table)}`,
|
|
308
326
|
})
|
|
309
327
|
|
|
310
|
-
return mysqlTableStatsToJsonSchemaField<ROW>(table, stats)
|
|
328
|
+
return mysqlTableStatsToJsonSchemaField<ROW>(table, stats, this.cfg.logger)
|
|
311
329
|
}
|
|
312
330
|
}
|
package/src/query.util.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DBQuery } from '@naturalcycles/db-lib'
|
|
2
2
|
import { DBQueryFilterOperator } from '@naturalcycles/db-lib/src/query/dbQuery'
|
|
3
|
-
import { _hb } from '@naturalcycles/js-lib'
|
|
3
|
+
import { _hb, CommonLogger } from '@naturalcycles/js-lib'
|
|
4
4
|
import { white, yellow } from '@naturalcycles/nodejs-lib/dist/colors'
|
|
5
5
|
import { QueryOptions } from 'mysql'
|
|
6
6
|
import * as mysql from 'mysql'
|
|
@@ -41,15 +41,16 @@ export function dbQueryToSQLDelete(q: DBQuery<any>): string {
|
|
|
41
41
|
*/
|
|
42
42
|
export function insertSQL(
|
|
43
43
|
table: string,
|
|
44
|
-
|
|
44
|
+
rows: Record<any, any>[],
|
|
45
45
|
verb: 'INSERT' | 'REPLACE' = 'INSERT',
|
|
46
|
+
logger: CommonLogger = console,
|
|
46
47
|
): string[] {
|
|
47
48
|
// INSERT INTO table_name (column1, column2, column3, ...)
|
|
48
49
|
// VALUES (value1, value2, value3, ...);
|
|
49
50
|
|
|
50
51
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
51
|
-
const fieldSet =
|
|
52
|
-
Object.keys(
|
|
52
|
+
const fieldSet = rows.reduce((set: Set<string>, row) => {
|
|
53
|
+
Object.keys(row).forEach(field => set.add(field))
|
|
53
54
|
return set
|
|
54
55
|
}, new Set<string>())
|
|
55
56
|
const fields = [...fieldSet]
|
|
@@ -62,7 +63,7 @@ export function insertSQL(
|
|
|
62
63
|
`VALUES\n`,
|
|
63
64
|
].join(' ')
|
|
64
65
|
|
|
65
|
-
const valueRows =
|
|
66
|
+
const valueRows = rows.map(rec => {
|
|
66
67
|
return `(` + fields.map(k => mysql.escape(rec[k])).join(',') + `)`
|
|
67
68
|
})
|
|
68
69
|
|
|
@@ -90,7 +91,7 @@ export function insertSQL(
|
|
|
90
91
|
sqls.push(sql) // last one
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
logger.log(
|
|
94
95
|
`${white(table)} large sql query (${yellow(_hb(full.length))}) was split into ${yellow(
|
|
95
96
|
sqls.length,
|
|
96
97
|
)} chunks`,
|
|
@@ -146,11 +147,11 @@ export function dbQueryToSQLUpdate(q: DBQuery<any>, record: Record<any, any>): s
|
|
|
146
147
|
return mysql.format(tokens.join(' '), Object.values(record))
|
|
147
148
|
}
|
|
148
149
|
|
|
149
|
-
function selectTokens(q: DBQuery
|
|
150
|
+
function selectTokens(q: DBQuery): string[] {
|
|
150
151
|
let fields = ['*']
|
|
151
152
|
|
|
152
153
|
if (q._selectedFieldNames) {
|
|
153
|
-
fields = q._selectedFieldNames.length ? q._selectedFieldNames : ['id']
|
|
154
|
+
fields = q._selectedFieldNames.length ? (q._selectedFieldNames as string[]) : ['id']
|
|
154
155
|
}
|
|
155
156
|
|
|
156
157
|
// We don't do `escapeId` cause it'll ruin e.g SELECT `count *` FROM ...
|
|
@@ -172,7 +173,7 @@ function offsetLimitTokens(q: DBQuery<any>): string[] {
|
|
|
172
173
|
return tokens
|
|
173
174
|
}
|
|
174
175
|
|
|
175
|
-
function orderTokens(q: DBQuery
|
|
176
|
+
function orderTokens(q: DBQuery): string[] {
|
|
176
177
|
if (!q._orders.length) return []
|
|
177
178
|
return [
|
|
178
179
|
`ORDER BY`,
|
|
@@ -184,7 +185,7 @@ const OP_MAP: Partial<Record<DBQueryFilterOperator, string>> = {
|
|
|
184
185
|
'==': '=',
|
|
185
186
|
}
|
|
186
187
|
|
|
187
|
-
function whereTokens(q: DBQuery
|
|
188
|
+
function whereTokens(q: DBQuery): string[] {
|
|
188
189
|
if (!q._filters.length) return []
|
|
189
190
|
|
|
190
191
|
return [
|
|
@@ -195,18 +196,18 @@ function whereTokens(q: DBQuery<any>): string[] {
|
|
|
195
196
|
// special treatment
|
|
196
197
|
|
|
197
198
|
return [
|
|
198
|
-
mysql.escapeId(mapNameToMySQL(f.name)),
|
|
199
|
+
mysql.escapeId(mapNameToMySQL(f.name as string)),
|
|
199
200
|
f.op === '==' ? 'IS NULL' : 'IS NOT NULL',
|
|
200
201
|
].join(' ')
|
|
201
202
|
}
|
|
202
203
|
|
|
203
204
|
if (Array.isArray(f.val)) {
|
|
204
205
|
// special case for arrays
|
|
205
|
-
return `${mysql.escapeId(mapNameToMySQL(f.name))} IN (${mysql.escape(f.val)})`
|
|
206
|
+
return `${mysql.escapeId(mapNameToMySQL(f.name as string))} IN (${mysql.escape(f.val)})`
|
|
206
207
|
}
|
|
207
208
|
|
|
208
209
|
return [
|
|
209
|
-
mysql.escapeId(mapNameToMySQL(f.name)),
|
|
210
|
+
mysql.escapeId(mapNameToMySQL(f.name as string)),
|
|
210
211
|
OP_MAP[f.op] || f.op,
|
|
211
212
|
mysql.escape(f.val),
|
|
212
213
|
].join(' ')
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CommonLogger,
|
|
2
3
|
JsonSchemaBoolean,
|
|
3
4
|
JsonSchemaNumber,
|
|
4
5
|
JsonSchemaObject,
|
|
@@ -81,6 +82,7 @@ export function jsonSchemaToMySQLDDL(
|
|
|
81
82
|
export function mysqlTableStatsToJsonSchemaField<T = any>(
|
|
82
83
|
table: string,
|
|
83
84
|
stats: MySQLTableStats[],
|
|
85
|
+
logger: CommonLogger,
|
|
84
86
|
): JsonSchemaRootObject<T> {
|
|
85
87
|
const s: JsonSchemaRootObject<T> = {
|
|
86
88
|
$id: `${table}.schema.json`,
|
|
@@ -104,12 +106,12 @@ export function mysqlTableStatsToJsonSchemaField<T = any>(
|
|
|
104
106
|
s.properties[name] = { instanceof: 'Buffer' }
|
|
105
107
|
} else if (t.startsWith('tinyint') || t.includes('(1)')) {
|
|
106
108
|
s.properties[name] = { type: 'boolean' } as JsonSchemaBoolean
|
|
107
|
-
} else if (t.startsWith('int(')) {
|
|
109
|
+
} else if (t === 'int' || t.startsWith('int(')) {
|
|
108
110
|
s.properties[name] = { type: 'integer' } as JsonSchemaNumber
|
|
109
111
|
} else if (t.startsWith('float')) {
|
|
110
112
|
s.properties[name] = { type: 'number' } as JsonSchemaNumber
|
|
111
113
|
} else {
|
|
112
|
-
|
|
114
|
+
logger.log(s)
|
|
113
115
|
throw new Error(`Unknown mysql field type ${name} ${stat.Type}`)
|
|
114
116
|
}
|
|
115
117
|
})
|
package/CHANGELOG.md
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
# [3.8.0](https://github.com/NaturalCycles/mysql-lib/compare/v3.7.1...v3.8.0) (2021-10-04)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
### Features
|
|
5
|
-
|
|
6
|
-
* modernize ([6e8f0a2](https://github.com/NaturalCycles/mysql-lib/commit/6e8f0a254a67902cbc185f034f58cd4f6885449d))
|
|
7
|
-
|
|
8
|
-
## [3.7.1](https://github.com/NaturalCycles/mysql-lib/compare/v3.7.0...v3.7.1) (2020-06-03)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
### Bug Fixes
|
|
12
|
-
|
|
13
|
-
* modernize ([517f695](https://github.com/NaturalCycles/mysql-lib/commit/517f6952feb15059730f4f7443a295bf596053fc))
|
|
14
|
-
|
|
15
|
-
# [3.7.0](https://github.com/NaturalCycles/mysql-lib/compare/v3.6.0...v3.7.0) (2020-04-08)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
### Features
|
|
19
|
-
|
|
20
|
-
* modernize ([e0e2890](https://github.com/NaturalCycles/mysql-lib/commit/e0e2890cb31e88fcbdae63c417d6cc5c6a52d4e8))
|
|
21
|
-
|
|
22
|
-
# [3.6.0](https://github.com/NaturalCycles/mysql-lib/compare/v3.5.2...v3.6.0) (2020-03-01)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
### Features
|
|
26
|
-
|
|
27
|
-
* deps ([008aa10](https://github.com/NaturalCycles/mysql-lib/commit/008aa10d059734d76c2354553a8dc35c8117b3b2))
|
|
28
|
-
|
|
29
|
-
## [3.5.2](https://github.com/NaturalCycles/mysql-lib/compare/v3.5.1...v3.5.2) (2019-11-20)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
### Bug Fixes
|
|
33
|
-
|
|
34
|
-
* BIT typecast to boolean correctly ([0bc815e](https://github.com/NaturalCycles/mysql-lib/commit/0bc815e025a33ab9fae5405c8b97dd53aae392ca))
|
|
35
|
-
|
|
36
|
-
## [3.5.1](https://github.com/NaturalCycles/mysql-lib/compare/v3.5.0...v3.5.1) (2019-11-20)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
### Bug Fixes
|
|
40
|
-
|
|
41
|
-
* correctly type-cast booleans with value=NULL ([e208b4c](https://github.com/NaturalCycles/mysql-lib/commit/e208b4ca16f700b6ed7bf95c872f68f934894992))
|
|
42
|
-
|
|
43
|
-
# [3.5.0](https://github.com/NaturalCycles/mysql-lib/compare/v3.4.0...v3.5.0) (2019-11-09)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
### Features
|
|
47
|
-
|
|
48
|
-
* implement getDBAdapter. Allow empty (default) configuration ([bcf12dc](https://github.com/NaturalCycles/mysql-lib/commit/bcf12dc9360f525749f9bb10965046b4c56d849a))
|
|
49
|
-
|
|
50
|
-
# [3.4.0](https://github.com/NaturalCycles/mysql-lib/compare/v3.3.1...v3.4.0) (2019-11-09)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
### Features
|
|
54
|
-
|
|
55
|
-
* auto JSON.stringify objects (and arrays) ([0d9aaed](https://github.com/NaturalCycles/mysql-lib/commit/0d9aaedf8f2920a51dacf13b6723eb98c61b34c3))
|
|
56
|
-
|
|
57
|
-
## [3.3.1](https://github.com/NaturalCycles/mysql-lib/compare/v3.3.0...v3.3.1) (2019-11-09)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
### Bug Fixes
|
|
61
|
-
|
|
62
|
-
* use LONGBLOB for binary columns ([ae4facc](https://github.com/NaturalCycles/mysql-lib/commit/ae4facc76bc03b8aafa5141199a98bef530f6913))
|
|
63
|
-
|
|
64
|
-
# [3.3.0](https://github.com/NaturalCycles/mysql-lib/compare/v3.2.1...v3.3.0) (2019-11-09)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
### Features
|
|
68
|
-
|
|
69
|
-
* mapNameToMySQL ([c4bf40c](https://github.com/NaturalCycles/mysql-lib/commit/c4bf40cd6aefaf78219a2588ec803cf74004bc07))
|
|
70
|
-
|
|
71
|
-
## [3.2.1](https://github.com/NaturalCycles/mysql-lib/compare/v3.2.0...v3.2.1) (2019-11-09)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
### Bug Fixes
|
|
75
|
-
|
|
76
|
-
* createTable() ([7983085](https://github.com/NaturalCycles/mysql-lib/commit/7983085017562a4e4a8f7dd38eb41ae6b9fc30ed))
|
|
77
|
-
|
|
78
|
-
# [3.2.0](https://github.com/NaturalCycles/mysql-lib/compare/v3.1.0...v3.2.0) (2019-11-09)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
### Bug Fixes
|
|
82
|
-
|
|
83
|
-
* emoji support ([1262fc4](https://github.com/NaturalCycles/mysql-lib/commit/1262fc4d9ad39c818833b5cfc31b3a65979cdea0))
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
### Features
|
|
87
|
-
|
|
88
|
-
* auto split long sql queries ([c7c780f](https://github.com/NaturalCycles/mysql-lib/commit/c7c780f295d7ded9f418509f3160a512ec54c7e7))
|
|
89
|
-
|
|
90
|
-
# [3.1.0](https://github.com/NaturalCycles/mysql-lib/compare/v3.0.0...v3.1.0) (2019-11-08)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
### Features
|
|
94
|
-
|
|
95
|
-
* commonSchemaToMySQLDDL ([09168c5](https://github.com/NaturalCycles/mysql-lib/commit/09168c563cbb629ca47121a1aac6a125dd23c144))
|
|
96
|
-
* implement getTables(), getTableSchema() ([20a7746](https://github.com/NaturalCycles/mysql-lib/commit/20a7746c8c4c88dfca8365d1e8d2decce3f47efa))
|
|
97
|
-
|
|
98
|
-
# [3.0.0](https://github.com/NaturalCycles/mysql-lib/compare/v2.0.2...v3.0.0) (2019-11-02)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
### Features
|
|
102
|
-
|
|
103
|
-
* adapt to db-lib@3 ([7d13f54](https://github.com/NaturalCycles/mysql-lib/commit/7d13f540c92dd59b014d1a502c1bff937fad567f))
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
### BREAKING CHANGES
|
|
107
|
-
|
|
108
|
-
* ^^^
|
|
109
|
-
|
|
110
|
-
## [2.0.2](https://github.com/NaturalCycles/mysql-lib/compare/v2.0.1...v2.0.2) (2019-10-20)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
### Bug Fixes
|
|
114
|
-
|
|
115
|
-
* adopt to db-lib ([6da7d78](https://github.com/NaturalCycles/mysql-lib/commit/6da7d78))
|
|
116
|
-
|
|
117
|
-
## [2.0.1](https://github.com/NaturalCycles/mysql-lib/compare/v2.0.0...v2.0.1) (2019-10-19)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
### Bug Fixes
|
|
121
|
-
|
|
122
|
-
* use Readable ([a0d09c1](https://github.com/NaturalCycles/mysql-lib/commit/a0d09c1))
|
|
123
|
-
|
|
124
|
-
# [2.0.0](https://github.com/NaturalCycles/mysql-lib/compare/v1.7.1...v2.0.0) (2019-10-18)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
### Features
|
|
128
|
-
|
|
129
|
-
* implement CommonDB 2.0 ([9de0e9f](https://github.com/NaturalCycles/mysql-lib/commit/9de0e9f))
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
### BREAKING CHANGES
|
|
133
|
-
|
|
134
|
-
* ^^^
|
|
135
|
-
|
|
136
|
-
## [1.7.1](https://github.com/NaturalCycles/mysql-lib/compare/v1.7.0...v1.7.1) (2019-10-18)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
### Bug Fixes
|
|
140
|
-
|
|
141
|
-
* pin @types/hapi__joi ([3e3cf5a](https://github.com/NaturalCycles/mysql-lib/commit/3e3cf5a))
|
|
142
|
-
|
|
143
|
-
# [1.7.0](https://github.com/NaturalCycles/mysql-lib/compare/v1.6.0...v1.7.0) (2019-09-30)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
### Features
|
|
147
|
-
|
|
148
|
-
* tiny change to use pool.query inst of getConnection() ([6ffe1b4](https://github.com/NaturalCycles/mysql-lib/commit/6ffe1b4))
|
|
149
|
-
|
|
150
|
-
# [1.6.0](https://github.com/NaturalCycles/mysql-lib/compare/v1.5.0...v1.6.0) (2019-09-30)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
### Features
|
|
154
|
-
|
|
155
|
-
* offset ([78710a1](https://github.com/NaturalCycles/mysql-lib/commit/78710a1))
|
|
156
|
-
|
|
157
|
-
# [1.5.0](https://github.com/NaturalCycles/mysql-lib/compare/v1.4.0...v1.5.0) (2019-09-30)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
### Features
|
|
161
|
-
|
|
162
|
-
* testing simpler streamSQL impl ([0887aa3](https://github.com/NaturalCycles/mysql-lib/commit/0887aa3))
|
|
163
|
-
|
|
164
|
-
# [1.4.0](https://github.com/NaturalCycles/mysql-lib/compare/v1.3.0...v1.4.0) (2019-09-30)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
### Features
|
|
168
|
-
|
|
169
|
-
* stream to use it's own separate connection ([43615f3](https://github.com/NaturalCycles/mysql-lib/commit/43615f3))
|
|
170
|
-
|
|
171
|
-
# [1.3.0](https://github.com/NaturalCycles/mysql-lib/compare/v1.2.0...v1.3.0) (2019-09-30)
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
### Features
|
|
175
|
-
|
|
176
|
-
* cfg.debugConnections ([70218ba](https://github.com/NaturalCycles/mysql-lib/commit/70218ba))
|
|
177
|
-
|
|
178
|
-
# [1.2.0](https://github.com/NaturalCycles/mysql-lib/compare/v1.1.0...v1.2.0) (2019-09-28)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
### Features
|
|
182
|
-
|
|
183
|
-
* add BIT cast to boolean ([899cce4](https://github.com/NaturalCycles/mysql-lib/commit/899cce4))
|
|
184
|
-
|
|
185
|
-
# [1.1.0](https://github.com/NaturalCycles/mysql-lib/compare/v1.0.0...v1.1.0) (2019-09-21)
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
### Features
|
|
189
|
-
|
|
190
|
-
* modernize, implement saveBatch ([5595b6a](https://github.com/NaturalCycles/mysql-lib/commit/5595b6a))
|
|
191
|
-
|
|
192
|
-
# 1.0.0 (2019-06-03)
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
### Features
|
|
196
|
-
|
|
197
|
-
* first version ([02620fb](https://github.com/NaturalCycles/mysql-lib/commit/02620fb))
|
|
198
|
-
* init project by create-module ([eee50b7](https://github.com/NaturalCycles/mysql-lib/commit/eee50b7))
|