@powersync/service-module-mysql 0.7.4 → 0.8.0

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 (57) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dev/docker/mysql/init-scripts/my.cnf +1 -3
  3. package/dist/api/MySQLRouteAPIAdapter.js +11 -3
  4. package/dist/api/MySQLRouteAPIAdapter.js.map +1 -1
  5. package/dist/common/ReplicatedGTID.js +4 -0
  6. package/dist/common/ReplicatedGTID.js.map +1 -1
  7. package/dist/common/common-index.d.ts +1 -2
  8. package/dist/common/common-index.js +1 -2
  9. package/dist/common/common-index.js.map +1 -1
  10. package/dist/common/mysql-to-sqlite.js +4 -0
  11. package/dist/common/mysql-to-sqlite.js.map +1 -1
  12. package/dist/common/schema-utils.d.ts +20 -0
  13. package/dist/common/{get-replication-columns.js → schema-utils.js} +73 -30
  14. package/dist/common/schema-utils.js.map +1 -0
  15. package/dist/replication/BinLogStream.d.ts +9 -6
  16. package/dist/replication/BinLogStream.js +99 -70
  17. package/dist/replication/BinLogStream.js.map +1 -1
  18. package/dist/replication/zongji/BinLogListener.d.ts +52 -5
  19. package/dist/replication/zongji/BinLogListener.js +302 -85
  20. package/dist/replication/zongji/BinLogListener.js.map +1 -1
  21. package/dist/replication/zongji/zongji-utils.d.ts +2 -1
  22. package/dist/replication/zongji/zongji-utils.js +3 -0
  23. package/dist/replication/zongji/zongji-utils.js.map +1 -1
  24. package/dist/types/node-sql-parser-extended-types.d.ts +31 -0
  25. package/dist/types/node-sql-parser-extended-types.js +2 -0
  26. package/dist/types/node-sql-parser-extended-types.js.map +1 -0
  27. package/dist/utils/mysql-utils.d.ts +4 -2
  28. package/dist/utils/mysql-utils.js +15 -3
  29. package/dist/utils/mysql-utils.js.map +1 -1
  30. package/dist/utils/parser-utils.d.ts +16 -0
  31. package/dist/utils/parser-utils.js +58 -0
  32. package/dist/utils/parser-utils.js.map +1 -0
  33. package/package.json +9 -8
  34. package/src/api/MySQLRouteAPIAdapter.ts +11 -3
  35. package/src/common/ReplicatedGTID.ts +6 -1
  36. package/src/common/common-index.ts +1 -2
  37. package/src/common/mysql-to-sqlite.ts +3 -0
  38. package/src/common/{get-replication-columns.ts → schema-utils.ts} +96 -37
  39. package/src/replication/BinLogStream.ts +119 -91
  40. package/src/replication/zongji/BinLogListener.ts +370 -93
  41. package/src/replication/zongji/zongji-utils.ts +6 -1
  42. package/src/types/node-sql-parser-extended-types.ts +25 -0
  43. package/src/utils/mysql-utils.ts +19 -4
  44. package/src/utils/parser-utils.ts +73 -0
  45. package/test/src/BinLogListener.test.ts +415 -32
  46. package/test/src/BinLogStream.test.ts +128 -52
  47. package/test/src/BinlogStreamUtils.ts +12 -2
  48. package/test/src/parser-utils.test.ts +24 -0
  49. package/test/src/schema-changes.test.ts +663 -0
  50. package/test/src/util.ts +6 -0
  51. package/tsconfig.tsbuildinfo +1 -1
  52. package/dist/common/get-replication-columns.d.ts +0 -12
  53. package/dist/common/get-replication-columns.js.map +0 -1
  54. package/dist/common/get-tables-from-pattern.d.ts +0 -7
  55. package/dist/common/get-tables-from-pattern.js +0 -28
  56. package/dist/common/get-tables-from-pattern.js.map +0 -1
  57. package/src/common/get-tables-from-pattern.ts +0 -44
@@ -2,26 +2,45 @@ import * as common from '../../common/common-index.js';
2
2
  import async from 'async';
3
3
  import * as zongji_utils from './zongji-utils.js';
4
4
  import { logger as defaultLogger } from '@powersync/lib-services-framework';
5
- // Maximum time the processing queue can be paused before resuming automatically
6
- // MySQL server will automatically terminate replication connections after 60 seconds of inactivity, so this guards against that.
7
- const MAX_QUEUE_PAUSE_TIME_MS = 45_000;
5
+ import timers from 'timers/promises';
6
+ import pkg from 'node-sql-parser';
7
+ import { isAlterTable, isColumnExpression, isConstraintExpression, isCreateUniqueIndex, isDropIndex, isDropTable, isRenameExpression, isRenameTable, isTruncate, matchedSchemaChangeQuery } from '../../utils/parser-utils.js';
8
+ const { Parser } = pkg;
9
+ /**
10
+ * Schema changes that are detectable by inspecting query events.
11
+ * Create table statements are not included here, since new tables are automatically detected when row events
12
+ * are received for them.
13
+ */
14
+ export var SchemaChangeType;
15
+ (function (SchemaChangeType) {
16
+ SchemaChangeType["RENAME_TABLE"] = "Rename Table";
17
+ SchemaChangeType["DROP_TABLE"] = "Drop Table";
18
+ SchemaChangeType["TRUNCATE_TABLE"] = "Truncate Table";
19
+ SchemaChangeType["ALTER_TABLE_COLUMN"] = "Alter Table Column";
20
+ SchemaChangeType["REPLICATION_IDENTITY"] = "Alter Replication Identity";
21
+ })(SchemaChangeType || (SchemaChangeType = {}));
8
22
  /**
9
23
  * Wrapper class for the Zongji BinLog listener. Internally handles the creation and management of the listener and posts
10
24
  * events on the provided BinLogEventHandler.
11
25
  */
12
26
  export class BinLogListener {
13
27
  options;
28
+ sqlParser;
14
29
  connectionManager;
15
30
  eventHandler;
16
31
  binLogPosition;
17
32
  currentGTID;
18
33
  logger;
34
+ listenerError;
35
+ databaseFilter;
19
36
  zongji;
20
37
  processingQueue;
38
+ isStopped = false;
39
+ isStopping = false;
21
40
  /**
22
41
  * The combined size in bytes of all the binlog events currently in the processing queue.
23
42
  */
24
- queueMemoryUsage;
43
+ queueMemoryUsage = 0;
25
44
  constructor(options) {
26
45
  this.options = options;
27
46
  this.logger = options.logger ?? defaultLogger;
@@ -29,9 +48,11 @@ export class BinLogListener {
29
48
  this.eventHandler = options.eventHandler;
30
49
  this.binLogPosition = options.startPosition;
31
50
  this.currentGTID = null;
32
- this.processingQueue = async.queue(this.createQueueWorker(), 1);
33
- this.queueMemoryUsage = 0;
51
+ this.sqlParser = new Parser();
52
+ this.processingQueue = this.createProcessingQueue();
34
53
  this.zongji = this.createZongjiListener();
54
+ this.listenerError = null;
55
+ this.databaseFilter = this.createDatabaseFilter(options.sourceTables);
35
56
  }
36
57
  /**
37
58
  * The queue memory limit in bytes as defined in the connection options.
@@ -40,107 +61,128 @@ export class BinLogListener {
40
61
  get queueMemoryLimit() {
41
62
  return this.connectionManager.options.binlog_queue_memory_limit * 1024 * 1024;
42
63
  }
43
- async start() {
64
+ async start(isRestart = false) {
44
65
  if (this.isStopped) {
45
66
  return;
46
67
  }
47
- this.logger.info(`Starting replication. Created replica client with serverId:${this.options.serverId}`);
68
+ this.logger.info(`${isRestart ? 'Restarting' : 'Starting'} BinLog Listener with replica client id:${this.options.serverId}...`);
69
+ // Set a heartbeat interval for the Zongji replication connection
70
+ // Zongji does not explicitly handle the heartbeat events - they are categorized as event:unknown
71
+ // The heartbeat events are enough to keep the connection alive for setTimeout to work on the socket.
72
+ // The heartbeat needs to be set before starting the listener, since the replication connection is locked once replicating
73
+ await new Promise((resolve, reject) => {
74
+ this.zongji.connection.query(
75
+ // In nanoseconds, 10^9 = 1s
76
+ 'set @master_heartbeat_period=28*1000000000', (error, results, _fields) => {
77
+ if (error) {
78
+ reject(error);
79
+ }
80
+ else {
81
+ this.logger.info('Successfully set up replication connection heartbeat.');
82
+ resolve(results);
83
+ }
84
+ });
85
+ });
86
+ // The _socket member is only set after a query is run on the connection, so we set the timeout after setting the heartbeat.
87
+ // The timeout here must be greater than the master_heartbeat_period.
88
+ const socket = this.zongji.connection._socket;
89
+ socket.setTimeout(60_000, () => {
90
+ this.logger.info('Destroying socket due to replication connection timeout.');
91
+ socket.destroy(new Error('Replication connection timeout.'));
92
+ });
48
93
  this.zongji.start({
49
94
  // We ignore the unknown/heartbeat event since it currently serves no purpose other than to keep the connection alive
50
95
  // tablemap events always need to be included for the other row events to work
51
- includeEvents: ['tablemap', 'writerows', 'updaterows', 'deleterows', 'xid', 'rotate', 'gtidlog'],
52
- includeSchema: { [this.connectionManager.databaseName]: this.options.includedTables },
96
+ includeEvents: ['tablemap', 'writerows', 'updaterows', 'deleterows', 'xid', 'rotate', 'gtidlog', 'query'],
97
+ includeSchema: this.databaseFilter,
53
98
  filename: this.binLogPosition.filename,
54
99
  position: this.binLogPosition.offset,
55
100
  serverId: this.options.serverId
56
101
  });
57
- return new Promise((resolve, reject) => {
58
- // Handle an edge case where the listener has already been stopped before completing startup
59
- if (this.isStopped) {
60
- this.logger.info('BinLog listener was stopped before startup completed.');
102
+ return new Promise((resolve) => {
103
+ this.zongji.once('ready', () => {
104
+ this.logger.info(`BinLog Listener ${isRestart ? 'restarted' : 'started'}. Listening for events from position: ${this.binLogPosition.filename}:${this.binLogPosition.offset}`);
61
105
  resolve();
62
- }
63
- this.zongji.on('error', (error) => {
64
- if (!this.isStopped) {
65
- this.logger.error('Binlog listener error:', error);
66
- this.stop();
67
- reject(error);
68
- }
69
- else {
70
- this.logger.warn('Binlog listener error during shutdown:', error);
71
- }
72
- });
73
- this.processingQueue.error((error) => {
74
- if (!this.isStopped) {
75
- this.logger.error('BinlogEvent processing error:', error);
76
- this.stop();
77
- reject(error);
78
- }
79
- else {
80
- this.logger.warn('BinlogEvent processing error during shutdown:', error);
81
- }
82
- });
83
- this.zongji.on('stopped', () => {
84
- resolve();
85
- this.logger.info('BinLog listener stopped. Replication ended.');
86
106
  });
87
107
  });
88
108
  }
89
- stop() {
90
- if (!this.isStopped) {
91
- this.zongji.stop();
109
+ async restartZongji() {
110
+ if (this.zongji.stopped) {
111
+ this.zongji = this.createZongjiListener();
112
+ await this.start(true);
113
+ }
114
+ }
115
+ async stopZongji() {
116
+ if (!this.zongji.stopped) {
117
+ this.logger.info('Stopping BinLog Listener...');
118
+ await new Promise((resolve) => {
119
+ this.zongji.once('stopped', () => {
120
+ resolve();
121
+ });
122
+ this.zongji.stop();
123
+ });
124
+ this.logger.info('BinLog Listener stopped.');
125
+ }
126
+ }
127
+ async stop() {
128
+ if (!(this.isStopped || this.isStopping)) {
129
+ this.isStopping = true;
130
+ await this.stopZongji();
92
131
  this.processingQueue.kill();
132
+ this.isStopped = true;
93
133
  }
94
134
  }
95
- get isStopped() {
96
- return this.zongji.stopped;
135
+ async replicateUntilStopped() {
136
+ while (!this.isStopped) {
137
+ await timers.setTimeout(1_000);
138
+ }
139
+ if (this.listenerError) {
140
+ this.logger.error('BinLog Listener stopped due to an error:', this.listenerError);
141
+ throw this.listenerError;
142
+ }
143
+ }
144
+ createProcessingQueue() {
145
+ const queue = async.queue(this.createQueueWorker(), 1);
146
+ queue.error((error) => {
147
+ if (!(this.isStopped || this.isStopping)) {
148
+ this.listenerError = error;
149
+ this.stop();
150
+ }
151
+ else {
152
+ this.logger.warn('Error processing BinLog event during shutdown:', error);
153
+ }
154
+ });
155
+ return queue;
97
156
  }
98
157
  createZongjiListener() {
99
158
  const zongji = this.connectionManager.createBinlogListener();
100
159
  zongji.on('binlog', async (evt) => {
101
- this.logger.info(`Received Binlog event:${evt.getEventName()}`);
160
+ this.logger.debug(`Received BinLog event:${evt.getEventName()}`);
102
161
  this.processingQueue.push(evt);
103
162
  this.queueMemoryUsage += evt.size;
104
163
  // When the processing queue grows past the threshold, we pause the binlog listener
105
164
  if (this.isQueueOverCapacity()) {
106
- this.logger.info(`Binlog processing queue has reached its memory limit of [${this.connectionManager.options.binlog_queue_memory_limit}MB]. Pausing Binlog listener.`);
107
- zongji.pause();
108
- const resumeTimeoutPromise = new Promise((resolve) => {
109
- setTimeout(() => resolve('timeout'), MAX_QUEUE_PAUSE_TIME_MS);
110
- });
111
- await Promise.race([this.processingQueue.empty(), resumeTimeoutPromise]);
112
- this.logger.info(`Binlog processing queue backlog cleared. Resuming Binlog listener.`);
113
- zongji.resume();
165
+ this.logger.info(`BinLog processing queue has reached its memory limit of [${this.connectionManager.options.binlog_queue_memory_limit}MB]. Pausing BinLog Listener.`);
166
+ await this.stopZongji();
167
+ await this.processingQueue.drain();
168
+ this.logger.info(`BinLog processing queue backlog cleared. Resuming BinLog Listener.`);
169
+ await this.restartZongji();
114
170
  }
115
171
  });
116
- zongji.on('ready', async () => {
117
- // Set a heartbeat interval for the Zongji replication connection
118
- // Zongji does not explicitly handle the heartbeat events - they are categorized as event:unknown
119
- // The heartbeat events are enough to keep the connection alive for setTimeout to work on the socket.
120
- await new Promise((resolve, reject) => {
121
- this.zongji.connection.query(
122
- // In nanoseconds, 10^9 = 1s
123
- 'set @master_heartbeat_period=28*1000000000', (error, results, fields) => {
124
- if (error) {
125
- reject(error);
126
- }
127
- else {
128
- this.logger.info('Successfully set up replication connection heartbeat...');
129
- resolve(results);
130
- }
131
- });
132
- });
133
- // The _socket member is only set after a query is run on the connection, so we set the timeout after setting the heartbeat.
134
- // The timeout here must be greater than the master_heartbeat_period.
135
- const socket = this.zongji.connection._socket;
136
- socket.setTimeout(60_000, () => {
137
- this.logger.info('Destroying socket due to replication connection timeout.');
138
- socket.destroy(new Error('Replication connection timeout.'));
139
- });
140
- this.logger.info(`BinLog listener setup complete. Reading binlog from: ${this.binLogPosition.filename}:${this.binLogPosition.offset}`);
172
+ zongji.on('error', (error) => {
173
+ if (!(this.isStopped || this.isStopping)) {
174
+ this.listenerError = error;
175
+ this.stop();
176
+ }
177
+ else {
178
+ this.logger.warn('Ignored BinLog Listener error during shutdown:', error);
179
+ }
141
180
  });
142
181
  return zongji;
143
182
  }
183
+ isQueueOverCapacity() {
184
+ return this.queueMemoryUsage >= this.queueMemoryLimit;
185
+ }
144
186
  createQueueWorker() {
145
187
  return async (evt) => {
146
188
  switch (true) {
@@ -155,38 +197,213 @@ export class BinLogListener {
155
197
  offset: evt.nextPosition
156
198
  }
157
199
  });
200
+ this.binLogPosition.offset = evt.nextPosition;
158
201
  await this.eventHandler.onTransactionStart({ timestamp: new Date(evt.timestamp) });
202
+ this.logger.info(`Processed GTID event: ${this.currentGTID.comparable}`);
159
203
  break;
160
204
  case zongji_utils.eventIsRotation(evt):
205
+ const newFile = this.binLogPosition.filename !== evt.binlogName;
161
206
  this.binLogPosition.filename = evt.binlogName;
162
- this.binLogPosition.offset = evt.position;
163
207
  await this.eventHandler.onRotate();
208
+ if (newFile) {
209
+ this.logger.info(`Processed Rotate event. New BinLog file is: ${this.binLogPosition.filename}:${this.binLogPosition.offset}`);
210
+ }
164
211
  break;
165
212
  case zongji_utils.eventIsWriteMutation(evt):
166
- await this.eventHandler.onWrite(evt.rows, evt.tableMap[evt.tableId]);
213
+ const tableMap = evt.tableMap[evt.tableId];
214
+ await this.eventHandler.onWrite(evt.rows, tableMap);
215
+ this.logger.info(`Processed Write event for table [${tableMap.parentSchema}.${tableMap.tableName}]. ${evt.rows.length} row(s) inserted.`);
167
216
  break;
168
217
  case zongji_utils.eventIsUpdateMutation(evt):
169
218
  await this.eventHandler.onUpdate(evt.rows.map((row) => row.after), evt.rows.map((row) => row.before), evt.tableMap[evt.tableId]);
219
+ this.logger.info(`Processed Update event for table [${evt.tableMap[evt.tableId].tableName}]. ${evt.rows.length} row(s) updated.`);
170
220
  break;
171
221
  case zongji_utils.eventIsDeleteMutation(evt):
172
222
  await this.eventHandler.onDelete(evt.rows, evt.tableMap[evt.tableId]);
223
+ this.logger.info(`Processed Delete event for table [${evt.tableMap[evt.tableId].tableName}]. ${evt.rows.length} row(s) deleted.`);
173
224
  break;
174
225
  case zongji_utils.eventIsXid(evt):
226
+ this.binLogPosition.offset = evt.nextPosition;
175
227
  const LSN = new common.ReplicatedGTID({
176
228
  raw_gtid: this.currentGTID.raw,
177
- position: {
178
- filename: this.binLogPosition.filename,
179
- offset: evt.nextPosition
180
- }
229
+ position: this.binLogPosition
181
230
  }).comparable;
182
231
  await this.eventHandler.onCommit(LSN);
232
+ this.logger.info(`Processed Xid event - transaction complete. LSN: ${LSN}.`);
233
+ break;
234
+ case zongji_utils.eventIsQuery(evt):
235
+ await this.processQueryEvent(evt);
183
236
  break;
184
237
  }
238
+ // Update the binlog position after processing the event
239
+ this.binLogPosition.offset = evt.nextPosition;
185
240
  this.queueMemoryUsage -= evt.size;
186
241
  };
187
242
  }
188
- isQueueOverCapacity() {
189
- return this.queueMemoryUsage >= this.queueMemoryLimit;
243
+ async processQueryEvent(event) {
244
+ const { query, nextPosition } = event;
245
+ // BEGIN query events mark the start of a transaction before any row events. They are not relevant for schema changes
246
+ if (query === 'BEGIN') {
247
+ return;
248
+ }
249
+ const schemaChanges = this.toSchemaChanges(query, event.schema);
250
+ if (schemaChanges.length > 0) {
251
+ // Since handling the schema changes can take a long time, we need to stop the Zongji listener instead of pausing it.
252
+ await this.stopZongji();
253
+ for (const change of schemaChanges) {
254
+ this.logger.info(`Processing schema change ${change.type} for table [${change.schema}.${change.table}]`);
255
+ await this.eventHandler.onSchemaChange(change);
256
+ }
257
+ // DDL queries are auto commited, but do not come with a corresponding Xid event.
258
+ // This is problematic for DDL queries which result in row events because the checkpoint is not moved on,
259
+ // so we manually commit here.
260
+ this.binLogPosition.offset = nextPosition;
261
+ const LSN = new common.ReplicatedGTID({
262
+ raw_gtid: this.currentGTID.raw,
263
+ position: this.binLogPosition
264
+ }).comparable;
265
+ await this.eventHandler.onCommit(LSN);
266
+ this.logger.info(`Successfully processed ${schemaChanges.length} schema change(s).`);
267
+ // If there are still events in the processing queue, we need to process those before restarting Zongji
268
+ if (!this.processingQueue.idle()) {
269
+ this.logger.info(`Processing [${this.processingQueue.length()}] events(s) before resuming...`);
270
+ this.processingQueue.drain(async () => {
271
+ await this.restartZongji();
272
+ });
273
+ }
274
+ else {
275
+ await this.restartZongji();
276
+ }
277
+ }
278
+ }
279
+ /**
280
+ * Function that interprets a DDL query for any applicable schema changes.
281
+ * If the query does not contain any relevant schema changes, an empty array is returned.
282
+ * The defaultSchema is derived from the database set on the MySQL Node.js connection client.
283
+ * It is used as a fallback when the schema/database cannot be determined from the query DDL.
284
+ *
285
+ * @param query
286
+ * @param defaultSchema
287
+ */
288
+ toSchemaChanges(query, defaultSchema) {
289
+ let statements = [];
290
+ try {
291
+ const ast = this.sqlParser.astify(query, { database: 'MySQL' });
292
+ statements = Array.isArray(ast) ? ast : [ast];
293
+ }
294
+ catch (error) {
295
+ if (matchedSchemaChangeQuery(query, Object.values(this.databaseFilter))) {
296
+ this.logger.warn(`Failed to parse query: [${query}].
297
+ Please review for the schema changes and manually redeploy the sync rules if required.`);
298
+ }
299
+ return [];
300
+ }
301
+ const changes = [];
302
+ for (const statement of statements) {
303
+ if (isTruncate(statement)) {
304
+ const truncateStatement = statement;
305
+ // Truncate statements can apply to multiple tables
306
+ for (const entity of truncateStatement.name) {
307
+ changes.push({
308
+ type: SchemaChangeType.TRUNCATE_TABLE,
309
+ table: entity.table,
310
+ schema: entity.db ?? defaultSchema
311
+ });
312
+ }
313
+ }
314
+ else if (isDropTable(statement)) {
315
+ for (const entity of statement.name) {
316
+ changes.push({ type: SchemaChangeType.DROP_TABLE, table: entity.table, schema: entity.db ?? defaultSchema });
317
+ }
318
+ }
319
+ else if (isDropIndex(statement)) {
320
+ const dropStatement = statement;
321
+ changes.push({
322
+ type: SchemaChangeType.REPLICATION_IDENTITY,
323
+ table: dropStatement.table.table,
324
+ schema: dropStatement.table.db ?? defaultSchema
325
+ });
326
+ }
327
+ else if (isCreateUniqueIndex(statement)) {
328
+ // Potential change to the replication identity if the table has no prior unique constraint
329
+ changes.push({
330
+ type: SchemaChangeType.REPLICATION_IDENTITY,
331
+ // @ts-ignore - The type definitions for node-sql-parser do not reflect the correct structure here
332
+ table: statement.table.table,
333
+ // @ts-ignore
334
+ schema: statement.table.db ?? defaultSchema
335
+ });
336
+ }
337
+ else if (isRenameTable(statement)) {
338
+ const renameStatement = statement;
339
+ // Rename statements can apply to multiple tables
340
+ for (const table of renameStatement.table) {
341
+ const schema = table[0].db ?? defaultSchema;
342
+ const isNewTableIncluded = this.databaseFilter[schema](table[1].table);
343
+ changes.push({
344
+ type: SchemaChangeType.RENAME_TABLE,
345
+ table: table[0].table,
346
+ newTable: isNewTableIncluded ? table[1].table : undefined,
347
+ schema
348
+ });
349
+ }
350
+ }
351
+ else if (isAlterTable(statement)) {
352
+ const fromTable = statement.table[0];
353
+ for (const expression of statement.expr) {
354
+ if (isRenameExpression(expression)) {
355
+ changes.push({
356
+ type: SchemaChangeType.RENAME_TABLE,
357
+ table: fromTable.table,
358
+ newTable: expression.table,
359
+ schema: fromTable.db ?? defaultSchema
360
+ });
361
+ }
362
+ else if (isColumnExpression(expression)) {
363
+ changes.push({
364
+ type: SchemaChangeType.ALTER_TABLE_COLUMN,
365
+ table: fromTable.table,
366
+ schema: fromTable.db ?? defaultSchema
367
+ });
368
+ }
369
+ else if (isConstraintExpression(expression)) {
370
+ // Potential changes to the replication identity
371
+ changes.push({
372
+ type: SchemaChangeType.REPLICATION_IDENTITY,
373
+ table: fromTable.table,
374
+ schema: fromTable.db ?? defaultSchema
375
+ });
376
+ }
377
+ }
378
+ }
379
+ }
380
+ // Filter out schema changes that are not relevant to the included tables
381
+ return changes.filter((change) => this.isTableIncluded(change.table, change.schema) ||
382
+ (change.newTable && this.isTableIncluded(change.newTable, change.schema)));
383
+ }
384
+ isTableIncluded(tableName, schema) {
385
+ return this.databaseFilter[schema] && this.databaseFilter[schema](tableName);
386
+ }
387
+ createDatabaseFilter(sourceTables) {
388
+ // Group sync rule tables by schema
389
+ const schemaMap = new Map();
390
+ for (const table of sourceTables) {
391
+ if (!schemaMap.has(table.schema)) {
392
+ const tables = [table];
393
+ schemaMap.set(table.schema, tables);
394
+ }
395
+ else {
396
+ schemaMap.get(table.schema).push(table);
397
+ }
398
+ }
399
+ const databaseFilter = {};
400
+ for (const entry of schemaMap.entries()) {
401
+ const [schema, sourceTables] = entry;
402
+ databaseFilter[schema] = (table) => sourceTables.findIndex((sourceTable) => sourceTable.isWildcard
403
+ ? table.startsWith(sourceTable.tablePattern.substring(0, sourceTable.tablePattern.length - 1))
404
+ : table === sourceTable.name) !== -1;
405
+ }
406
+ return databaseFilter;
190
407
  }
191
408
  }
192
409
  //# sourceMappingURL=BinLogListener.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BinLogListener.js","sourceRoot":"","sources":["../../../src/replication/zongji/BinLogListener.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BinLogListener.js","sourceRoot":"","sources":["../../../src/replication/zongji/BinLogListener.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { BinLogEvent, BinLogGTIDLogEvent, BinLogRowEvent, BinLogRotationEvent, BinLogTableMapEvent, BinLogRowUpdateEvent, BinLogXidEvent } from '@powersync/mysql-zongji';
1
+ import { BinLogEvent, BinLogGTIDLogEvent, BinLogRowEvent, BinLogRotationEvent, BinLogTableMapEvent, BinLogRowUpdateEvent, BinLogXidEvent, BinLogQueryEvent } from '@powersync/mysql-zongji';
2
2
  export declare function eventIsGTIDLog(event: BinLogEvent): event is BinLogGTIDLogEvent;
3
3
  export declare function eventIsTableMap(event: BinLogEvent): event is BinLogTableMapEvent;
4
4
  export declare function eventIsXid(event: BinLogEvent): event is BinLogXidEvent;
@@ -6,3 +6,4 @@ export declare function eventIsRotation(event: BinLogEvent): event is BinLogRota
6
6
  export declare function eventIsWriteMutation(event: BinLogEvent): event is BinLogRowEvent;
7
7
  export declare function eventIsDeleteMutation(event: BinLogEvent): event is BinLogRowEvent;
8
8
  export declare function eventIsUpdateMutation(event: BinLogEvent): event is BinLogRowUpdateEvent;
9
+ export declare function eventIsQuery(event: BinLogEvent): event is BinLogQueryEvent;
@@ -19,4 +19,7 @@ export function eventIsDeleteMutation(event) {
19
19
  export function eventIsUpdateMutation(event) {
20
20
  return event.getEventName() == 'updaterows';
21
21
  }
22
+ export function eventIsQuery(event) {
23
+ return event.getEventName() == 'query';
24
+ }
22
25
  //# sourceMappingURL=zongji-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"zongji-utils.js","sourceRoot":"","sources":["../../../src/replication/zongji/zongji-utils.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,cAAc,CAAC,KAAkB;IAC/C,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,SAAS,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,UAAU,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAkB;IAC3C,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,KAAK,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,QAAQ,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAkB;IACrD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,WAAW,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACtD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,YAAY,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACtD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,YAAY,CAAC;AAC9C,CAAC"}
1
+ {"version":3,"file":"zongji-utils.js","sourceRoot":"","sources":["../../../src/replication/zongji/zongji-utils.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,cAAc,CAAC,KAAkB;IAC/C,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,SAAS,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,UAAU,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAkB;IAC3C,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,KAAK,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,QAAQ,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAkB;IACrD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,WAAW,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACtD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,YAAY,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACtD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,YAAY,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAkB;IAC7C,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,OAAO,CAAC;AACzC,CAAC"}
@@ -0,0 +1,31 @@
1
+ import 'node-sql-parser';
2
+ /**
3
+ * Missing Type definitions for the node-sql-parser
4
+ */
5
+ declare module 'node-sql-parser' {
6
+ interface RenameStatement {
7
+ type: 'rename';
8
+ table: {
9
+ db: string | null;
10
+ table: string;
11
+ }[][];
12
+ }
13
+ interface TruncateStatement {
14
+ type: 'truncate';
15
+ keyword: 'table';
16
+ name: {
17
+ db: string | null;
18
+ table: string;
19
+ as: string | null;
20
+ }[];
21
+ }
22
+ interface DropIndexStatement {
23
+ type: 'drop';
24
+ keyword: 'index';
25
+ table: {
26
+ db: string | null;
27
+ table: string;
28
+ };
29
+ name: any[];
30
+ }
31
+ }
@@ -0,0 +1,2 @@
1
+ import 'node-sql-parser';
2
+ //# sourceMappingURL=node-sql-parser-extended-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-sql-parser-extended-types.js","sourceRoot":"","sources":["../../src/types/node-sql-parser-extended-types.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import mysql from 'mysql2';
2
2
  import mysqlPromise from 'mysql2/promise';
3
3
  import * as types from '../types/types.js';
4
- import { SourceTable } from '@powersync/service-core';
4
+ import { SourceEntityDescriptor } from '@powersync/service-core';
5
5
  export type RetriedQueryOptions = {
6
6
  connection: mysqlPromise.Connection;
7
7
  query: string;
@@ -29,4 +29,6 @@ export declare function getMySQLVersion(connection: mysqlPromise.Connection): Pr
29
29
  * @param minimumVersion
30
30
  */
31
31
  export declare function isVersionAtLeast(version: string, minimumVersion: string): boolean;
32
- export declare function escapeMysqlTableName(table: SourceTable): string;
32
+ export declare function satisfiesVersion(version: string, targetVersion: string): boolean;
33
+ export declare function qualifiedMySQLTable(table: SourceEntityDescriptor): string;
34
+ export declare function qualifiedMySQLTable(table: string, schema: string): string;
@@ -1,6 +1,6 @@
1
1
  import { logger } from '@powersync/lib-services-framework';
2
2
  import mysql from 'mysql2';
3
- import { coerce, gte } from 'semver';
3
+ import { coerce, gte, satisfies } from 'semver';
4
4
  /**
5
5
  * Retry a simple query - up to 2 attempts total.
6
6
  */
@@ -69,7 +69,19 @@ export function isVersionAtLeast(version, minimumVersion) {
69
69
  const coercedMinimumVersion = coerce(minimumVersion);
70
70
  return gte(coercedVersion, coercedMinimumVersion, { loose: true });
71
71
  }
72
- export function escapeMysqlTableName(table) {
73
- return `\`${table.schema.replaceAll('`', '``')}\`.\`${table.table.replaceAll('`', '``')}\``;
72
+ export function satisfiesVersion(version, targetVersion) {
73
+ const coercedVersion = coerce(version);
74
+ return satisfies(coercedVersion, targetVersion, { loose: true });
75
+ }
76
+ export function qualifiedMySQLTable(table, schema) {
77
+ if (typeof table === 'object') {
78
+ return `\`${table.schema.replaceAll('`', '``')}\`.\`${table.name.replaceAll('`', '``')}\``;
79
+ }
80
+ else if (schema) {
81
+ return `\`${schema.replaceAll('`', '``')}\`.\`${table.replaceAll('`', '``')}\``;
82
+ }
83
+ else {
84
+ return `\`${table.replaceAll('`', '``')}\``;
85
+ }
74
86
  }
75
87
  //# sourceMappingURL=mysql-utils.js.map