Skip to content

Commit 85b39bd

Browse files
committed
Support column filters
1 parent 2949d58 commit 85b39bd

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

packages/common/src/db/schema/Table.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,23 @@ interface SharedTableOptions {
1414
localOnly?: boolean;
1515
insertOnly?: boolean;
1616
viewName?: string;
17-
includeOld?: boolean | 'when-changed';
17+
includeOld?: boolean | IncludeOldOptions;
1818
includeMetadata?: boolean;
1919
ignoreEmptyUpdate?: boolean;
2020
}
2121

22+
/** Whether to include old columns when PowerSync tracks local changes.
23+
*
24+
* Including old columns may be helpful for some backend connector implementations, which is
25+
* why it can be enabled on per-table or per-columm basis.
26+
*/
27+
export interface IncludeOldOptions {
28+
/** When defined, a list of column names for which old values should be tracked. */
29+
columns?: string[];
30+
/** When enabled, only include values that have actually been changed by an update. */
31+
onlyWhenChanged?: boolean;
32+
}
33+
2234
export interface TableOptions extends SharedTableOptions {
2335
/**
2436
* The synced table name, matching sync rules
@@ -329,13 +341,15 @@ export class Table<Columns extends ColumnsType = ColumnsType> {
329341
}
330342

331343
toJSON() {
344+
const includeOld = this.includeOld;
345+
332346
return {
333347
name: this.name,
334348
view_name: this.viewName,
335349
local_only: this.localOnly,
336350
insert_only: this.insertOnly,
337-
include_old: this.includeOld != false,
338-
include_old_only_when_changed: this.includeOld == 'when-changed',
351+
include_old: includeOld && ((includeOld as any).columns ?? true),
352+
include_old_only_when_changed: typeof includeOld == 'object' && includeOld.onlyWhenChanged == true,
339353
include_metadata: this.includeMetadata,
340354
ignore_empty_update: this.ignoreEmptyUpdate,
341355
columns: this.columns.map((c) => c.toJSON()),

packages/common/tests/db/schema/Table.test.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,13 @@ describe('Table', () => {
140140

141141
expect(createTable({ includeOld: true }).toJSON().include_old).toBe(true);
142142
expect(createTable({ includeOld: true }).toJSON().include_old_only_when_changed).toBe(false);
143-
expect(createTable({ includeOld: 'when-changed' }).toJSON().include_old).toBe(true);
144-
expect(createTable({ includeOld: 'when-changed' }).toJSON().include_old_only_when_changed).toBe(true);
143+
144+
const complexIncldueOld = createTable({ includeOld: {
145+
columns: ['foo', 'bar'],
146+
onlyWhenChanged: true,
147+
} });
148+
expect(complexIncldueOld.toJSON().include_old).toStrictEqual(['foo', 'bar']);
149+
expect(complexIncldueOld.toJSON().include_old_only_when_changed).toBe(true);
145150

146151
expect(createTable({ ignoreEmptyUpdate: true }).toJSON().ignore_empty_update).toBe(true);
147152
});
@@ -220,7 +225,7 @@ describe('Table', () => {
220225
{
221226
name: column.text
222227
},
223-
{ localOnly: true, includeOld: 'when-changed' }
228+
{ localOnly: true, includeOld: { onlyWhenChanged: false } }
224229
).validate()
225230
).toThrowError("Can't include old values for local-only tables.");
226231
});

packages/node/tests/crud.test.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,26 @@ databaseTest('include old values', async ({ database }) => {
3838
expect(batch?.crud[0].oldData).toStrictEqual({name: 'entry'});
3939
});
4040

41+
databaseTest('include old values with column filter', async ({ database }) => {
42+
await database.init();
43+
const schema = new Schema({
44+
lists: new Table(
45+
{
46+
name: column.text,
47+
content: column.text
48+
},
49+
{ includeOld: { columns: ['name'] } }
50+
)
51+
});
52+
await database.updateSchema(schema);
53+
await database.execute('INSERT INTO lists (id, name, content) VALUES (uuid(), ?, ?);', ['name', 'content']);
54+
await database.execute('DELETE FROM ps_crud;');
55+
await database.execute('UPDATE lists SET name = ?, content = ?', ['new name', 'new content']);
56+
57+
const batch = await database.getNextCrudTransaction();
58+
expect(batch?.crud[0].oldData).toStrictEqual({name: 'name'});
59+
});
60+
4161
databaseTest('include old values when changed', async ({ database }) => {
4262
await database.init();
4363
const schema = new Schema({
@@ -46,7 +66,7 @@ databaseTest('include old values when changed', async ({ database }) => {
4666
name: column.text,
4767
content: column.text
4868
},
49-
{ includeOld: 'when-changed' }
69+
{ includeOld: { onlyWhenChanged: true } }
5070
)
5171
});
5272
await database.updateSchema(schema);

0 commit comments

Comments
 (0)