@powersync/service-module-mysql 0.0.0-dev-20241107065634 → 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 +7 -5
- 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/read-executed-gtid.js +4 -8
- package/dist/common/read-executed-gtid.js.map +1 -1
- package/dist/replication/BinLogStream.js +1 -1
- package/dist/replication/MySQLConnectionManager.js +1 -1
- package/dist/utils/{mysql_utils.d.ts → mysql-utils.d.ts} +7 -0
- package/dist/utils/{mysql_utils.js → mysql-utils.js} +19 -1
- package/dist/utils/mysql-utils.js.map +1 -0
- package/package.json +5 -5
- 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/read-executed-gtid.ts +5 -9
- package/src/replication/BinLogStream.ts +1 -1
- package/src/replication/MySQLConnectionManager.ts +1 -1
- package/src/utils/{mysql_utils.ts → mysql-utils.ts} +22 -0
- package/test/src/BinLogStream.test.ts +25 -51
- package/test/src/mysql-utils.test.ts +17 -0
- package/test/src/util.ts +2 -7
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/mysql_utils.js.map +0 -1
- /package/test/src/{MysqlTypeMappings.test.ts → mysql-to-sqlite.test.ts} +0 -0
|
@@ -3,6 +3,7 @@ import { MONGO_STORAGE_FACTORY } from '@core-tests/util.js';
|
|
|
3
3
|
import { BucketStorageFactory, Metrics } from '@powersync/service-core';
|
|
4
4
|
import { describe, expect, test } from 'vitest';
|
|
5
5
|
import { binlogStreamTest } from './BinlogStreamUtils.js';
|
|
6
|
+
import { v4 as uuid } from 'uuid';
|
|
6
7
|
|
|
7
8
|
type StorageFactory = () => Promise<BucketStorageFactory>;
|
|
8
9
|
|
|
@@ -32,9 +33,7 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
32
33
|
data:
|
|
33
34
|
- SELECT id, description, num FROM "test_data"`);
|
|
34
35
|
|
|
35
|
-
await connectionManager.query(
|
|
36
|
-
`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY DEFAULT (UUID()), description TEXT, num BIGINT)`
|
|
37
|
-
);
|
|
36
|
+
await connectionManager.query(`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description TEXT, num BIGINT)`);
|
|
38
37
|
|
|
39
38
|
await context.replicateSnapshot();
|
|
40
39
|
|
|
@@ -44,11 +43,10 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
44
43
|
(await Metrics.getInstance().getMetricValueForTests('powersync_transactions_replicated_total')) ?? 0;
|
|
45
44
|
|
|
46
45
|
context.startStreaming();
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
`
|
|
46
|
+
const testId = uuid();
|
|
47
|
+
await connectionManager.query(
|
|
48
|
+
`INSERT INTO test_data(id, description, num) VALUES('${testId}', 'test1', 1152921504606846976)`
|
|
50
49
|
);
|
|
51
|
-
const testId = result.test_id;
|
|
52
50
|
const data = await context.getBucketData('global[]');
|
|
53
51
|
|
|
54
52
|
expect(data).toMatchObject([putOp('test_data', { id: testId, description: 'test1', num: 1152921504606846976n })]);
|
|
@@ -71,9 +69,7 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
71
69
|
- SELECT id, description FROM "test_DATA"
|
|
72
70
|
`);
|
|
73
71
|
|
|
74
|
-
await connectionManager.query(
|
|
75
|
-
`CREATE TABLE test_DATA (id CHAR(36) PRIMARY KEY DEFAULT (UUID()), description text)`
|
|
76
|
-
);
|
|
72
|
+
await connectionManager.query(`CREATE TABLE test_DATA (id CHAR(36) PRIMARY KEY, description text)`);
|
|
77
73
|
|
|
78
74
|
await context.replicateSnapshot();
|
|
79
75
|
|
|
@@ -84,11 +80,8 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
84
80
|
|
|
85
81
|
context.startStreaming();
|
|
86
82
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
`SELECT id AS test_id FROM test_DATA WHERE description = 'test1'`
|
|
90
|
-
);
|
|
91
|
-
const testId = result.test_id;
|
|
83
|
+
const testId = uuid();
|
|
84
|
+
await connectionManager.query(`INSERT INTO test_DATA(id, description) VALUES('${testId}','test1')`);
|
|
92
85
|
|
|
93
86
|
const data = await context.getBucketData('global[]');
|
|
94
87
|
|
|
@@ -144,24 +137,18 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
144
137
|
const { connectionManager } = context;
|
|
145
138
|
await context.updateSyncRules(BASIC_SYNC_RULES);
|
|
146
139
|
|
|
147
|
-
await connectionManager.query(
|
|
148
|
-
`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY DEFAULT (UUID()), description text)`
|
|
149
|
-
);
|
|
140
|
+
await connectionManager.query(`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description text)`);
|
|
150
141
|
|
|
151
142
|
await context.replicateSnapshot();
|
|
152
143
|
context.startStreaming();
|
|
153
144
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
`SELECT id AS test_id FROM test_data WHERE description = 'test1'`
|
|
157
|
-
);
|
|
158
|
-
const testId1 = result1.test_id;
|
|
145
|
+
const testId1 = uuid();
|
|
146
|
+
await connectionManager.query(`INSERT INTO test_data(id, description) VALUES('${testId1}','test1')`);
|
|
159
147
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
`
|
|
148
|
+
const testId2 = uuid();
|
|
149
|
+
await connectionManager.query(
|
|
150
|
+
`UPDATE test_data SET id = '${testId2}', description = 'test2a' WHERE id = '${testId1}'`
|
|
163
151
|
);
|
|
164
|
-
const testId2 = result2.test_id;
|
|
165
152
|
|
|
166
153
|
// This update may fail replicating with:
|
|
167
154
|
// Error: Update on missing record public.test_data:074a601e-fc78-4c33-a15d-f89fdd4af31d :: {"g":1,"t":"651e9fbe9fec6155895057ec","k":"1a0b34da-fb8c-5e6f-8421-d7a3c5d4df4f"}
|
|
@@ -192,15 +179,10 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
192
179
|
const { connectionManager } = context;
|
|
193
180
|
await context.updateSyncRules(BASIC_SYNC_RULES);
|
|
194
181
|
|
|
195
|
-
await connectionManager.query(
|
|
196
|
-
`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY DEFAULT (UUID()), description text)`
|
|
197
|
-
);
|
|
182
|
+
await connectionManager.query(`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description text)`);
|
|
198
183
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
`SELECT id AS test_id FROM test_data WHERE description = 'test1'`
|
|
202
|
-
);
|
|
203
|
-
const testId = result.test_id;
|
|
184
|
+
const testId = uuid();
|
|
185
|
+
await connectionManager.query(`INSERT INTO test_data(id, description) VALUES('${testId}','test1')`);
|
|
204
186
|
|
|
205
187
|
await context.replicateSnapshot();
|
|
206
188
|
|
|
@@ -221,16 +203,13 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
221
203
|
`);
|
|
222
204
|
|
|
223
205
|
await connectionManager.query(
|
|
224
|
-
`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY
|
|
206
|
+
`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description TEXT, date DATE, datetime DATETIME, timestamp TIMESTAMP)`
|
|
225
207
|
);
|
|
226
208
|
|
|
209
|
+
const testId = uuid();
|
|
227
210
|
await connectionManager.query(`
|
|
228
|
-
INSERT INTO test_data(description, date, datetime, timestamp) VALUES('testDates', '2023-03-06', '2023-03-06 15:47', '2023-03-06 15:47')
|
|
211
|
+
INSERT INTO test_data(id, description, date, datetime, timestamp) VALUES('${testId}','testDates', '2023-03-06', '2023-03-06 15:47', '2023-03-06 15:47')
|
|
229
212
|
`);
|
|
230
|
-
const [[result]] = await connectionManager.query(
|
|
231
|
-
`SELECT id AS test_id FROM test_data WHERE description = 'testDates'`
|
|
232
|
-
);
|
|
233
|
-
const testId = result.test_id;
|
|
234
213
|
|
|
235
214
|
await context.replicateSnapshot();
|
|
236
215
|
|
|
@@ -259,7 +238,7 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
259
238
|
`);
|
|
260
239
|
|
|
261
240
|
await connectionManager.query(
|
|
262
|
-
`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY
|
|
241
|
+
`CREATE TABLE test_data (id CHAR(36) PRIMARY KEY, description TEXT, date DATE, datetime DATETIME, timestamp TIMESTAMP)`
|
|
263
242
|
);
|
|
264
243
|
|
|
265
244
|
await context.replicateSnapshot();
|
|
@@ -271,13 +250,10 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
271
250
|
|
|
272
251
|
context.startStreaming();
|
|
273
252
|
|
|
253
|
+
const testId = uuid();
|
|
274
254
|
await connectionManager.query(`
|
|
275
|
-
INSERT INTO test_data(description, date, datetime, timestamp) VALUES('testDates', '2023-03-06', '2023-03-06 15:47', '2023-03-06 15:47')
|
|
255
|
+
INSERT INTO test_data(id, description, date, datetime, timestamp) VALUES('${testId}','testDates', '2023-03-06', '2023-03-06 15:47', '2023-03-06 15:47')
|
|
276
256
|
`);
|
|
277
|
-
const [[result]] = await connectionManager.query(
|
|
278
|
-
`SELECT id AS test_id FROM test_data WHERE description = 'testDates'`
|
|
279
|
-
);
|
|
280
|
-
const testId = result.test_id;
|
|
281
257
|
|
|
282
258
|
const data = await context.getBucketData('global[]');
|
|
283
259
|
expect(data).toMatchObject([
|
|
@@ -303,9 +279,7 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
303
279
|
const { connectionManager } = context;
|
|
304
280
|
await context.updateSyncRules(BASIC_SYNC_RULES);
|
|
305
281
|
|
|
306
|
-
await connectionManager.query(
|
|
307
|
-
`CREATE TABLE test_donotsync (id CHAR(36) PRIMARY KEY DEFAULT (UUID()), description text)`
|
|
308
|
-
);
|
|
282
|
+
await connectionManager.query(`CREATE TABLE test_donotsync (id CHAR(36) PRIMARY KEY, description text)`);
|
|
309
283
|
|
|
310
284
|
await context.replicateSnapshot();
|
|
311
285
|
|
|
@@ -316,7 +290,7 @@ function defineBinlogStreamTests(factory: StorageFactory) {
|
|
|
316
290
|
|
|
317
291
|
context.startStreaming();
|
|
318
292
|
|
|
319
|
-
await connectionManager.query(`INSERT INTO test_donotsync(description) VALUES('test1')`);
|
|
293
|
+
await connectionManager.query(`INSERT INTO test_donotsync(id, description) VALUES('${uuid()}','test1')`);
|
|
320
294
|
const data = await context.getBucketData('global[]');
|
|
321
295
|
|
|
322
296
|
expect(data).toMatchObject([]);
|
|
@@ -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,8 +3,7 @@ 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
|
-
import { gte } from 'semver';
|
|
6
|
+
import { getMySQLVersion, isVersionAtLeast } from '@module/utils/mysql-utils.js';
|
|
8
7
|
|
|
9
8
|
export const TEST_URI = env.MYSQL_TEST_URI;
|
|
10
9
|
|
|
@@ -38,7 +37,7 @@ export const INITIALIZED_MONGO_STORAGE_FACTORY: StorageFactory = async () => {
|
|
|
38
37
|
|
|
39
38
|
export async function clearTestDb(connection: mysqlPromise.Connection) {
|
|
40
39
|
const version = await getMySQLVersion(connection);
|
|
41
|
-
if (
|
|
40
|
+
if (isVersionAtLeast(version, '8.4.0')) {
|
|
42
41
|
await connection.query('RESET BINARY LOGS AND GTIDS');
|
|
43
42
|
} else {
|
|
44
43
|
await connection.query('RESET MASTER');
|
|
@@ -55,7 +54,3 @@ export async function clearTestDb(connection: mysqlPromise.Connection) {
|
|
|
55
54
|
}
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
|
-
|
|
59
|
-
export function connectMySQLPool(): mysqlPromise.Pool {
|
|
60
|
-
return mysqlPromise.createPool(TEST_URI);
|
|
61
|
-
}
|