@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.
Files changed (30) hide show
  1. package/CHANGELOG.md +7 -5
  2. package/dist/api/MySQLRouteAPIAdapter.js +9 -8
  3. package/dist/api/MySQLRouteAPIAdapter.js.map +1 -1
  4. package/dist/common/ReplicatedGTID.js +1 -1
  5. package/dist/common/check-source-configuration.d.ts +0 -1
  6. package/dist/common/check-source-configuration.js +6 -8
  7. package/dist/common/check-source-configuration.js.map +1 -1
  8. package/dist/common/get-replication-columns.js +1 -1
  9. package/dist/common/read-executed-gtid.js +4 -8
  10. package/dist/common/read-executed-gtid.js.map +1 -1
  11. package/dist/replication/BinLogStream.js +1 -1
  12. package/dist/replication/MySQLConnectionManager.js +1 -1
  13. package/dist/utils/{mysql_utils.d.ts → mysql-utils.d.ts} +7 -0
  14. package/dist/utils/{mysql_utils.js → mysql-utils.js} +19 -1
  15. package/dist/utils/mysql-utils.js.map +1 -0
  16. package/package.json +5 -5
  17. package/src/api/MySQLRouteAPIAdapter.ts +11 -9
  18. package/src/common/ReplicatedGTID.ts +1 -1
  19. package/src/common/check-source-configuration.ts +9 -10
  20. package/src/common/get-replication-columns.ts +1 -1
  21. package/src/common/read-executed-gtid.ts +5 -9
  22. package/src/replication/BinLogStream.ts +1 -1
  23. package/src/replication/MySQLConnectionManager.ts +1 -1
  24. package/src/utils/{mysql_utils.ts → mysql-utils.ts} +22 -0
  25. package/test/src/BinLogStream.test.ts +25 -51
  26. package/test/src/mysql-utils.test.ts +17 -0
  27. package/test/src/util.ts +2 -7
  28. package/tsconfig.tsbuildinfo +1 -1
  29. package/dist/utils/mysql_utils.js.map +0 -1
  30. /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
- await connectionManager.query(`INSERT INTO test_data(description, num) VALUES('test1', 1152921504606846976)`);
48
- const [[result]] = await connectionManager.query(
49
- `SELECT id AS test_id FROM test_data WHERE description = 'test1' AND num = 1152921504606846976`
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
- await connectionManager.query(`INSERT INTO test_DATA(description) VALUES('test1')`);
88
- const [[result]] = await connectionManager.query(
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
- await connectionManager.query(`INSERT INTO test_data(description) VALUES('test1')`);
155
- const [[result1]] = await connectionManager.query(
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
- await connectionManager.query(`UPDATE test_data SET id = UUID(), description = 'test2a' WHERE id = '${testId1}'`);
161
- const [[result2]] = await connectionManager.query(
162
- `SELECT id AS test_id FROM test_data WHERE description = 'test2a'`
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
- await connectionManager.query(`INSERT INTO test_data(description) VALUES('test1')`);
200
- const [[result]] = await connectionManager.query(
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 DEFAULT (UUID()), description TEXT, date DATE, datetime DATETIME, timestamp TIMESTAMP)`
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 DEFAULT (UUID()), description TEXT, date DATE, datetime DATETIME, timestamp TIMESTAMP)`
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/common/check-source-configuration.js';
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 (gte(version, '8.4.0')) {
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
- }