@powersync/service-module-mysql 0.0.0-dev-20241101083236 → 0.0.0-dev-20241111122558
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/CHANGELOG.md +11 -8
- package/dev/config/sync_rules.yaml +2 -4
- package/dist/api/MySQLRouteAPIAdapter.js +9 -8
- package/dist/api/MySQLRouteAPIAdapter.js.map +1 -1
- package/dist/common/ReplicatedGTID.js +1 -1
- package/dist/common/check-source-configuration.d.ts +0 -1
- package/dist/common/check-source-configuration.js +6 -8
- package/dist/common/check-source-configuration.js.map +1 -1
- package/dist/common/get-replication-columns.js +1 -1
- package/dist/common/mysql-to-sqlite.d.ts +17 -1
- package/dist/common/mysql-to-sqlite.js +133 -8
- package/dist/common/mysql-to-sqlite.js.map +1 -1
- package/dist/common/read-executed-gtid.js +4 -10
- package/dist/common/read-executed-gtid.js.map +1 -1
- package/dist/replication/BinLogStream.js +25 -21
- package/dist/replication/BinLogStream.js.map +1 -1
- package/dist/replication/MySQLConnectionManager.d.ts +2 -2
- package/dist/replication/MySQLConnectionManager.js +1 -1
- package/dist/utils/mysql-utils.d.ts +30 -0
- package/dist/utils/mysql-utils.js +70 -0
- package/dist/utils/mysql-utils.js.map +1 -0
- package/package.json +7 -6
- package/src/api/MySQLRouteAPIAdapter.ts +11 -9
- package/src/common/ReplicatedGTID.ts +1 -1
- package/src/common/check-source-configuration.ts +9 -10
- package/src/common/get-replication-columns.ts +1 -1
- package/src/common/mysql-to-sqlite.ts +147 -8
- package/src/common/read-executed-gtid.ts +5 -12
- package/src/replication/BinLogStream.ts +29 -21
- package/src/replication/MySQLConnectionManager.ts +3 -3
- package/src/utils/{mysql_utils.ts → mysql-utils.ts} +36 -5
- package/test/src/BinLogStream.test.ts +306 -0
- package/test/src/BinlogStreamUtils.ts +157 -0
- package/test/src/env.ts +1 -1
- package/test/src/mysql-to-sqlite.test.ts +322 -0
- package/test/src/mysql-utils.test.ts +17 -0
- package/test/src/util.ts +11 -17
- package/test/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/mysql_utils.d.ts +0 -17
- package/dist/utils/mysql_utils.js +0 -43
- package/dist/utils/mysql_utils.js.map +0 -1
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { SqliteRow } from '@powersync/service-sync-rules';
|
|
2
|
+
import { afterAll, describe, expect, test } from 'vitest';
|
|
3
|
+
import { clearTestDb, TEST_CONNECTION_OPTIONS } from './util.js';
|
|
4
|
+
import { eventIsWriteMutation, eventIsXid } from '@module/replication/zongji/zongji-utils.js';
|
|
5
|
+
import * as common from '@module/common/common-index.js';
|
|
6
|
+
import ZongJi, { BinLogEvent } from '@powersync/mysql-zongji';
|
|
7
|
+
import { MySQLConnectionManager } from '@module/replication/MySQLConnectionManager.js';
|
|
8
|
+
import { toColumnDescriptors } from '@module/common/common-index.js';
|
|
9
|
+
|
|
10
|
+
describe('MySQL Data Types', () => {
|
|
11
|
+
const connectionManager = new MySQLConnectionManager(TEST_CONNECTION_OPTIONS, {});
|
|
12
|
+
|
|
13
|
+
afterAll(async () => {
|
|
14
|
+
await connectionManager.end();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
async function setupTable() {
|
|
18
|
+
const connection = await connectionManager.getConnection();
|
|
19
|
+
await clearTestDb(connection);
|
|
20
|
+
await connection.query(`CREATE TABLE test_data (
|
|
21
|
+
tinyint_col TINYINT,
|
|
22
|
+
smallint_col SMALLINT,
|
|
23
|
+
mediumint_col MEDIUMINT,
|
|
24
|
+
int_col INT,
|
|
25
|
+
integer_col INTEGER,
|
|
26
|
+
bigint_col BIGINT,
|
|
27
|
+
float_col FLOAT,
|
|
28
|
+
double_col DOUBLE,
|
|
29
|
+
decimal_col DECIMAL(10,2),
|
|
30
|
+
numeric_col NUMERIC(10,2),
|
|
31
|
+
bit_col BIT(8),
|
|
32
|
+
boolean_col BOOLEAN,
|
|
33
|
+
serial_col SERIAL,
|
|
34
|
+
|
|
35
|
+
date_col DATE,
|
|
36
|
+
datetime_col DATETIME(3),
|
|
37
|
+
timestamp_col TIMESTAMP(3),
|
|
38
|
+
time_col TIME,
|
|
39
|
+
year_col YEAR,
|
|
40
|
+
|
|
41
|
+
char_col CHAR(10),
|
|
42
|
+
varchar_col VARCHAR(255),
|
|
43
|
+
binary_col BINARY(16),
|
|
44
|
+
varbinary_col VARBINARY(256),
|
|
45
|
+
tinyblob_col TINYBLOB,
|
|
46
|
+
blob_col BLOB,
|
|
47
|
+
mediumblob_col MEDIUMBLOB,
|
|
48
|
+
longblob_col LONGBLOB,
|
|
49
|
+
tinytext_col TINYTEXT,
|
|
50
|
+
text_col TEXT,
|
|
51
|
+
mediumtext_col MEDIUMTEXT,
|
|
52
|
+
longtext_col LONGTEXT,
|
|
53
|
+
enum_col ENUM('value1', 'value2', 'value3'),
|
|
54
|
+
set_col SET('value1', 'value2', 'value3'),
|
|
55
|
+
|
|
56
|
+
json_col JSON,
|
|
57
|
+
|
|
58
|
+
geometry_col GEOMETRY,
|
|
59
|
+
point_col POINT,
|
|
60
|
+
linestring_col LINESTRING,
|
|
61
|
+
polygon_col POLYGON,
|
|
62
|
+
multipoint_col MULTIPOINT,
|
|
63
|
+
multilinestring_col MULTILINESTRING,
|
|
64
|
+
multipolygon_col MULTIPOLYGON,
|
|
65
|
+
geometrycollection_col GEOMETRYCOLLECTION
|
|
66
|
+
)`);
|
|
67
|
+
|
|
68
|
+
connection.release();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
test('Number types mappings', async () => {
|
|
72
|
+
await setupTable();
|
|
73
|
+
await connectionManager.query(`
|
|
74
|
+
INSERT INTO test_data (
|
|
75
|
+
tinyint_col,
|
|
76
|
+
smallint_col,
|
|
77
|
+
mediumint_col,
|
|
78
|
+
int_col,
|
|
79
|
+
integer_col,
|
|
80
|
+
bigint_col,
|
|
81
|
+
double_col,
|
|
82
|
+
decimal_col,
|
|
83
|
+
numeric_col,
|
|
84
|
+
bit_col,
|
|
85
|
+
boolean_col
|
|
86
|
+
-- serial_col is auto-incremented and can be left out
|
|
87
|
+
) VALUES (
|
|
88
|
+
127, -- TINYINT maximum value
|
|
89
|
+
32767, -- SMALLINT maximum value
|
|
90
|
+
8388607, -- MEDIUMINT maximum value
|
|
91
|
+
2147483647, -- INT maximum value
|
|
92
|
+
2147483647, -- INTEGER maximum value
|
|
93
|
+
9223372036854775807, -- BIGINT maximum value
|
|
94
|
+
3.1415926535, -- DOUBLE example
|
|
95
|
+
12345.67, -- DECIMAL(10,2) example
|
|
96
|
+
12345.67, -- NUMERIC(10,2) example
|
|
97
|
+
b'10101010', -- BIT(8) example in binary notation
|
|
98
|
+
TRUE -- BOOLEAN value (alias for TINYINT(1))
|
|
99
|
+
-- serial_col is auto-incremented
|
|
100
|
+
)`);
|
|
101
|
+
|
|
102
|
+
const databaseRows = await getDatabaseRows(connectionManager, 'test_data');
|
|
103
|
+
const replicatedRows = await getReplicatedRows();
|
|
104
|
+
|
|
105
|
+
const expectedResult = {
|
|
106
|
+
tinyint_col: 127n,
|
|
107
|
+
smallint_col: 32767n,
|
|
108
|
+
mediumint_col: 8388607n,
|
|
109
|
+
int_col: 2147483647n,
|
|
110
|
+
integer_col: 2147483647n,
|
|
111
|
+
bigint_col: 9223372036854775807n,
|
|
112
|
+
double_col: 3.1415926535,
|
|
113
|
+
decimal_col: 12345.67,
|
|
114
|
+
numeric_col: 12345.67,
|
|
115
|
+
bit_col: new Uint8Array([0b10101010]).valueOf(),
|
|
116
|
+
boolean_col: 1n,
|
|
117
|
+
serial_col: 1n
|
|
118
|
+
};
|
|
119
|
+
expect(databaseRows[0]).toMatchObject(expectedResult);
|
|
120
|
+
expect(replicatedRows[0]).toMatchObject(expectedResult);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test('Float type mapping', async () => {
|
|
124
|
+
await setupTable();
|
|
125
|
+
const expectedFloatValue = 3.14;
|
|
126
|
+
await connectionManager.query(`INSERT INTO test_data (float_col) VALUES (${expectedFloatValue})`);
|
|
127
|
+
|
|
128
|
+
const databaseRows = await getDatabaseRows(connectionManager, 'test_data');
|
|
129
|
+
const replicatedRows = await getReplicatedRows();
|
|
130
|
+
|
|
131
|
+
const allowedPrecision = 0.0001;
|
|
132
|
+
|
|
133
|
+
const actualFloatValueDB = databaseRows[0].float_col;
|
|
134
|
+
let difference = Math.abs((actualFloatValueDB as number) - expectedFloatValue);
|
|
135
|
+
expect(difference).toBeLessThan(allowedPrecision);
|
|
136
|
+
|
|
137
|
+
const actualFloatValueReplicated = replicatedRows[0].float_col;
|
|
138
|
+
difference = Math.abs((actualFloatValueReplicated as number) - expectedFloatValue);
|
|
139
|
+
expect(difference).toBeLessThan(allowedPrecision);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test('Character types mappings', async () => {
|
|
143
|
+
await setupTable();
|
|
144
|
+
await connectionManager.query(`
|
|
145
|
+
INSERT INTO test_data (
|
|
146
|
+
char_col,
|
|
147
|
+
varchar_col,
|
|
148
|
+
binary_col,
|
|
149
|
+
varbinary_col,
|
|
150
|
+
tinyblob_col,
|
|
151
|
+
blob_col,
|
|
152
|
+
mediumblob_col,
|
|
153
|
+
longblob_col,
|
|
154
|
+
tinytext_col,
|
|
155
|
+
text_col,
|
|
156
|
+
mediumtext_col,
|
|
157
|
+
longtext_col,
|
|
158
|
+
enum_col
|
|
159
|
+
) VALUES (
|
|
160
|
+
'CharData', -- CHAR(10) with padding spaces
|
|
161
|
+
'Variable character data',-- VARCHAR(255)
|
|
162
|
+
'ShortBin', -- BINARY(16)
|
|
163
|
+
'VariableBinaryData', -- VARBINARY(256)
|
|
164
|
+
'TinyBlobData', -- TINYBLOB
|
|
165
|
+
'BlobData', -- BLOB
|
|
166
|
+
'MediumBlobData', -- MEDIUMBLOB
|
|
167
|
+
'LongBlobData', -- LONGBLOB
|
|
168
|
+
'TinyTextData', -- TINYTEXT
|
|
169
|
+
'TextData', -- TEXT
|
|
170
|
+
'MediumTextData', -- MEDIUMTEXT
|
|
171
|
+
'LongTextData', -- LONGTEXT
|
|
172
|
+
'value1' -- ENUM('value1', 'value2', 'value3')
|
|
173
|
+
);`);
|
|
174
|
+
|
|
175
|
+
const databaseRows = await getDatabaseRows(connectionManager, 'test_data');
|
|
176
|
+
const replicatedRows = await getReplicatedRows();
|
|
177
|
+
const expectedResult = {
|
|
178
|
+
char_col: 'CharData',
|
|
179
|
+
varchar_col: 'Variable character data',
|
|
180
|
+
binary_col: new Uint8Array([83, 104, 111, 114, 116, 66, 105, 110, 0, 0, 0, 0, 0, 0, 0, 0]), // Pad with 0
|
|
181
|
+
varbinary_col: new Uint8Array([
|
|
182
|
+
0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x44, 0x61, 0x74, 0x61
|
|
183
|
+
]),
|
|
184
|
+
tinyblob_col: new Uint8Array([0x54, 0x69, 0x6e, 0x79, 0x42, 0x6c, 0x6f, 0x62, 0x44, 0x61, 0x74, 0x61]),
|
|
185
|
+
blob_col: new Uint8Array([0x42, 0x6c, 0x6f, 0x62, 0x44, 0x61, 0x74, 0x61]),
|
|
186
|
+
mediumblob_col: new Uint8Array([
|
|
187
|
+
0x4d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x42, 0x6c, 0x6f, 0x62, 0x44, 0x61, 0x74, 0x61
|
|
188
|
+
]),
|
|
189
|
+
longblob_col: new Uint8Array([0x4c, 0x6f, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x62, 0x44, 0x61, 0x74, 0x61]),
|
|
190
|
+
tinytext_col: 'TinyTextData',
|
|
191
|
+
text_col: 'TextData',
|
|
192
|
+
mediumtext_col: 'MediumTextData',
|
|
193
|
+
longtext_col: 'LongTextData',
|
|
194
|
+
enum_col: 'value1'
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
expect(databaseRows[0]).toMatchObject(expectedResult);
|
|
198
|
+
expect(replicatedRows[0]).toMatchObject(expectedResult);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test('Date types mappings', async () => {
|
|
202
|
+
await setupTable();
|
|
203
|
+
await connectionManager.query(`
|
|
204
|
+
INSERT INTO test_data(date_col, datetime_col, timestamp_col, time_col, year_col)
|
|
205
|
+
VALUES('2023-03-06', '2023-03-06 15:47', '2023-03-06 15:47', '15:47:00', '2023');
|
|
206
|
+
`);
|
|
207
|
+
|
|
208
|
+
const databaseRows = await getDatabaseRows(connectionManager, 'test_data');
|
|
209
|
+
const replicatedRows = await getReplicatedRows();
|
|
210
|
+
const expectedResult = {
|
|
211
|
+
date_col: '2023-03-06',
|
|
212
|
+
datetime_col: '2023-03-06T15:47:00.000Z',
|
|
213
|
+
timestamp_col: '2023-03-06T15:47:00.000Z',
|
|
214
|
+
time_col: '15:47:00',
|
|
215
|
+
year_col: 2023
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
expect(databaseRows[0]).toMatchObject(expectedResult);
|
|
219
|
+
expect(replicatedRows[0]).toMatchObject(expectedResult);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test('Date types edge cases mappings', async () => {
|
|
223
|
+
await setupTable();
|
|
224
|
+
|
|
225
|
+
await connectionManager.query(`INSERT INTO test_data(timestamp_col) VALUES('1970-01-01 00:00:01')`);
|
|
226
|
+
await connectionManager.query(`INSERT INTO test_data(timestamp_col) VALUES('2038-01-19 03:14:07.499')`);
|
|
227
|
+
await connectionManager.query(`INSERT INTO test_data(datetime_col) VALUES('1000-01-01 00:00:00')`);
|
|
228
|
+
await connectionManager.query(`INSERT INTO test_data(datetime_col) VALUES('9999-12-31 23:59:59.499')`);
|
|
229
|
+
|
|
230
|
+
const databaseRows = await getDatabaseRows(connectionManager, 'test_data');
|
|
231
|
+
const replicatedRows = await getReplicatedRows(4);
|
|
232
|
+
const expectedResults = [
|
|
233
|
+
{ timestamp_col: '1970-01-01T00:00:01.000Z' },
|
|
234
|
+
{ timestamp_col: '2038-01-19T03:14:07.499Z' },
|
|
235
|
+
{ datetime_col: '1000-01-01T00:00:00.000Z' },
|
|
236
|
+
{ datetime_col: '9999-12-31T23:59:59.499Z' }
|
|
237
|
+
];
|
|
238
|
+
|
|
239
|
+
for (let i = 0; i < expectedResults.length; i++) {
|
|
240
|
+
expect(databaseRows[i]).toMatchObject(expectedResults[i]);
|
|
241
|
+
expect(replicatedRows[i]).toMatchObject(expectedResults[i]);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test('Json types mappings', async () => {
|
|
246
|
+
await setupTable();
|
|
247
|
+
|
|
248
|
+
const expectedJSON = { name: 'John Doe', age: 30, married: true };
|
|
249
|
+
const expectedSet = ['value1', 'value3'];
|
|
250
|
+
|
|
251
|
+
// For convenience, we map the SET data type to a JSON Array
|
|
252
|
+
await connectionManager.query(
|
|
253
|
+
`INSERT INTO test_data (json_col, set_col) VALUES ('${JSON.stringify(expectedJSON)}', '${expectedSet.join(',')}')`
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
const databaseRows = await getDatabaseRows(connectionManager, 'test_data');
|
|
257
|
+
const replicatedRows = await getReplicatedRows();
|
|
258
|
+
|
|
259
|
+
const actualDBJSONValue = JSON.parse(databaseRows[0].json_col as string);
|
|
260
|
+
const actualReplicatedJSONValue = JSON.parse(replicatedRows[0].json_col as string);
|
|
261
|
+
expect(actualDBJSONValue).toEqual(expectedJSON);
|
|
262
|
+
expect(actualReplicatedJSONValue).toEqual(expectedJSON);
|
|
263
|
+
|
|
264
|
+
const actualDBSetValue = JSON.parse(databaseRows[0].set_col as string);
|
|
265
|
+
const actualReplicatedSetValue = JSON.parse(replicatedRows[0].set_col as string);
|
|
266
|
+
expect(actualDBSetValue).toEqual(expectedSet);
|
|
267
|
+
expect(actualReplicatedSetValue).toEqual(expectedSet);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
async function getDatabaseRows(connection: MySQLConnectionManager, tableName: string): Promise<SqliteRow[]> {
|
|
272
|
+
const [results, fields] = await connection.query(`SELECT * FROM ${tableName}`);
|
|
273
|
+
const columns = toColumnDescriptors(fields);
|
|
274
|
+
return results.map((row) => common.toSQLiteRow(row, columns));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Return all the inserts from the first transaction in the binlog stream.
|
|
279
|
+
*/
|
|
280
|
+
async function getReplicatedRows(expectedTransactionsCount?: number): Promise<SqliteRow[]> {
|
|
281
|
+
let transformed: SqliteRow[] = [];
|
|
282
|
+
const zongji = new ZongJi({
|
|
283
|
+
host: TEST_CONNECTION_OPTIONS.hostname,
|
|
284
|
+
user: TEST_CONNECTION_OPTIONS.username,
|
|
285
|
+
password: TEST_CONNECTION_OPTIONS.password,
|
|
286
|
+
timeZone: 'Z' // Ensure no auto timezone manipulation of the dates occur
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
const completionPromise = new Promise<SqliteRow[]>((resolve, reject) => {
|
|
290
|
+
zongji.on('binlog', (evt: BinLogEvent) => {
|
|
291
|
+
try {
|
|
292
|
+
if (eventIsWriteMutation(evt)) {
|
|
293
|
+
const tableMapEntry = evt.tableMap[evt.tableId];
|
|
294
|
+
const columns = toColumnDescriptors(tableMapEntry);
|
|
295
|
+
const records = evt.rows.map((row: Record<string, any>) => common.toSQLiteRow(row, columns));
|
|
296
|
+
transformed.push(...records);
|
|
297
|
+
} else if (eventIsXid(evt)) {
|
|
298
|
+
if (expectedTransactionsCount !== undefined) {
|
|
299
|
+
expectedTransactionsCount--;
|
|
300
|
+
if (expectedTransactionsCount == 0) {
|
|
301
|
+
zongji.stop();
|
|
302
|
+
resolve(transformed);
|
|
303
|
+
}
|
|
304
|
+
} else {
|
|
305
|
+
zongji.stop();
|
|
306
|
+
resolve(transformed);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
} catch (e) {
|
|
310
|
+
reject(e);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
zongji.start({
|
|
316
|
+
includeEvents: ['tablemap', 'writerows', 'xid'],
|
|
317
|
+
filename: 'mysql-bin.000001',
|
|
318
|
+
position: 0
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
return completionPromise;
|
|
322
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { isVersionAtLeast } from '@module/utils/mysql-utils.js';
|
|
3
|
+
|
|
4
|
+
describe('MySQL Utility Tests', () => {
|
|
5
|
+
test('Minimum version checking ', () => {
|
|
6
|
+
const newerVersion = '8.4.0';
|
|
7
|
+
const olderVersion = '5.7';
|
|
8
|
+
const sameVersion = '8.0';
|
|
9
|
+
// Improperly formatted semantic versions should be handled gracefully if possible
|
|
10
|
+
const improperSemver = '5.7.42-0ubuntu0.18.04.1-log';
|
|
11
|
+
|
|
12
|
+
expect(isVersionAtLeast(newerVersion, '8.0')).toBeTruthy();
|
|
13
|
+
expect(isVersionAtLeast(sameVersion, '8.0')).toBeTruthy();
|
|
14
|
+
expect(isVersionAtLeast(olderVersion, '8.0')).toBeFalsy();
|
|
15
|
+
expect(isVersionAtLeast(improperSemver, '5.7')).toBeTruthy();
|
|
16
|
+
});
|
|
17
|
+
});
|
package/test/src/util.ts
CHANGED
|
@@ -3,9 +3,14 @@ import { BucketStorageFactory, Metrics, MongoBucketStorage } from '@powersync/se
|
|
|
3
3
|
import { env } from './env.js';
|
|
4
4
|
import mysqlPromise from 'mysql2/promise';
|
|
5
5
|
import { connectMongo } from '@core-tests/util.js';
|
|
6
|
-
import { getMySQLVersion } from '@module/
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import { getMySQLVersion, isVersionAtLeast } from '@module/utils/mysql-utils.js';
|
|
7
|
+
|
|
8
|
+
export const TEST_URI = env.MYSQL_TEST_URI;
|
|
9
|
+
|
|
10
|
+
export const TEST_CONNECTION_OPTIONS = types.normalizeConnectionConfig({
|
|
11
|
+
type: 'mysql',
|
|
12
|
+
uri: TEST_URI
|
|
13
|
+
});
|
|
9
14
|
|
|
10
15
|
// The metrics need to be initialized before they can be used
|
|
11
16
|
await Metrics.initialise({
|
|
@@ -15,13 +20,6 @@ await Metrics.initialise({
|
|
|
15
20
|
});
|
|
16
21
|
Metrics.getInstance().resetCounters();
|
|
17
22
|
|
|
18
|
-
export const TEST_URI = env.MYSQL_TEST_URI;
|
|
19
|
-
|
|
20
|
-
export const TEST_CONNECTION_OPTIONS = types.normalizeConnectionConfig({
|
|
21
|
-
type: 'mysql',
|
|
22
|
-
uri: TEST_URI
|
|
23
|
-
});
|
|
24
|
-
|
|
25
23
|
export type StorageFactory = () => Promise<BucketStorageFactory>;
|
|
26
24
|
|
|
27
25
|
export const INITIALIZED_MONGO_STORAGE_FACTORY: StorageFactory = async () => {
|
|
@@ -37,19 +35,15 @@ export const INITIALIZED_MONGO_STORAGE_FACTORY: StorageFactory = async () => {
|
|
|
37
35
|
return new MongoBucketStorage(db, { slot_name_prefix: 'test_' });
|
|
38
36
|
};
|
|
39
37
|
|
|
40
|
-
export async function
|
|
38
|
+
export async function clearTestDb(connection: mysqlPromise.Connection) {
|
|
41
39
|
const version = await getMySQLVersion(connection);
|
|
42
|
-
if (
|
|
40
|
+
if (isVersionAtLeast(version, '8.4.0')) {
|
|
43
41
|
await connection.query('RESET BINARY LOGS AND GTIDS');
|
|
44
42
|
} else {
|
|
45
43
|
await connection.query('RESET MASTER');
|
|
46
44
|
}
|
|
47
45
|
|
|
48
|
-
|
|
49
|
-
//
|
|
50
|
-
// await connection.query(`CREATE DATABASE IF NOT EXISTS ${TEST_CONNECTION_OPTIONS.database}`);
|
|
51
|
-
|
|
52
|
-
const [result] = await connection.query<RowDataPacket[]>(
|
|
46
|
+
const [result] = await connection.query<mysqlPromise.RowDataPacket[]>(
|
|
53
47
|
`SELECT TABLE_NAME FROM information_schema.tables
|
|
54
48
|
WHERE TABLE_SCHEMA = '${TEST_CONNECTION_OPTIONS.database}'`
|
|
55
49
|
);
|