@powersync/service-module-mssql 0.9.0 → 0.10.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.
- package/CHANGELOG.md +84 -0
- package/dist/api/MSSQLRouteAPIAdapter.js +26 -34
- package/dist/api/MSSQLRouteAPIAdapter.js.map +1 -1
- package/dist/common/MSSQLSourceTable.d.ts +12 -2
- package/dist/common/MSSQLSourceTable.js +30 -4
- package/dist/common/MSSQLSourceTable.js.map +1 -1
- package/dist/replication/CDCPoller.d.ts +13 -36
- package/dist/replication/CDCPoller.js +173 -129
- package/dist/replication/CDCPoller.js.map +1 -1
- package/dist/replication/CDCStream.d.ts +11 -14
- package/dist/replication/CDCStream.js +109 -103
- package/dist/replication/CDCStream.js.map +1 -1
- package/dist/replication/CaptureReconciler.d.ts +47 -0
- package/dist/replication/CaptureReconciler.js +155 -0
- package/dist/replication/CaptureReconciler.js.map +1 -0
- package/dist/replication/MSSQLConnectionManager.d.ts +1 -0
- package/dist/replication/MSSQLConnectionManager.js +19 -14
- package/dist/replication/MSSQLConnectionManager.js.map +1 -1
- package/dist/replication/MSSQLTableReconciliationContext.d.ts +21 -0
- package/dist/replication/MSSQLTableReconciliationContext.js +7 -0
- package/dist/replication/MSSQLTableReconciliationContext.js.map +1 -0
- package/dist/replication/SchemaChange.d.ts +67 -0
- package/dist/replication/SchemaChange.js +31 -0
- package/dist/replication/SchemaChange.js.map +1 -0
- package/dist/types/types.d.ts +8 -0
- package/dist/types/types.js +9 -0
- package/dist/types/types.js.map +1 -1
- package/dist/utils/mssql.js +1 -1
- package/dist/utils/schema.d.ts +14 -1
- package/dist/utils/schema.js +40 -45
- package/dist/utils/schema.js.map +1 -1
- package/package.json +4 -4
- package/src/api/MSSQLRouteAPIAdapter.ts +27 -33
- package/src/common/MSSQLSourceTable.ts +32 -4
- package/src/replication/CDCPoller.ts +206 -162
- package/src/replication/CDCStream.ts +142 -151
- package/src/replication/CaptureReconciler.ts +186 -0
- package/src/replication/MSSQLConnectionManager.ts +23 -14
- package/src/replication/MSSQLTableReconciliationContext.ts +29 -0
- package/src/replication/SchemaChange.ts +79 -0
- package/src/types/types.ts +21 -0
- package/src/utils/mssql.ts +1 -1
- package/src/utils/schema.ts +57 -58
- package/test/src/CDCPoller.test.ts +382 -0
- package/test/src/CDCStream.test.ts +6 -2
- package/test/src/CDCStreamTestContext.ts +7 -0
- package/test/src/CaptureReconciler.test.ts +171 -0
- package/test/src/MSSQLSourceTable.test.ts +30 -0
- package/test/src/config.test.ts +37 -0
- package/test/src/schema-changes.test.ts +513 -249
- package/test/src/schema.test.ts +17 -0
- package/test/src/util.ts +70 -6
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -3,6 +3,24 @@ import { POWERSYNC_VERSION } from '@powersync/service-core';
|
|
|
3
3
|
import sql from 'mssql';
|
|
4
4
|
import { addParameters } from '../utils/mssql.js';
|
|
5
5
|
export const DEFAULT_SCHEMA = 'dbo';
|
|
6
|
+
export function createConnectionPoolConfig(options, poolOptions) {
|
|
7
|
+
return {
|
|
8
|
+
authentication: options.authentication,
|
|
9
|
+
user: options.username,
|
|
10
|
+
password: options.password,
|
|
11
|
+
server: options.hostname,
|
|
12
|
+
port: options.port,
|
|
13
|
+
database: options.database,
|
|
14
|
+
pool: poolOptions,
|
|
15
|
+
options: {
|
|
16
|
+
appName: `powersync/${POWERSYNC_VERSION}`,
|
|
17
|
+
encrypt: true, // Required for Azure
|
|
18
|
+
trustServerCertificate: options.additionalConfig.trustServerCertificate,
|
|
19
|
+
...(options.tls_servername ? { serverName: options.tls_servername } : {}),
|
|
20
|
+
...(options.cacert ? { cryptoCredentialsDetails: { ca: options.cacert } } : {})
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
6
24
|
export class MSSQLConnectionManager extends BaseObserver {
|
|
7
25
|
options;
|
|
8
26
|
pool;
|
|
@@ -10,20 +28,7 @@ export class MSSQLConnectionManager extends BaseObserver {
|
|
|
10
28
|
super();
|
|
11
29
|
this.options = options;
|
|
12
30
|
// The pool is lazy - no connections are opened until a query is performed.
|
|
13
|
-
this.pool = new sql.ConnectionPool(
|
|
14
|
-
authentication: options.authentication,
|
|
15
|
-
user: options.username,
|
|
16
|
-
password: options.password,
|
|
17
|
-
server: options.hostname,
|
|
18
|
-
port: options.port,
|
|
19
|
-
database: options.database,
|
|
20
|
-
pool: poolOptions,
|
|
21
|
-
options: {
|
|
22
|
-
appName: `powersync/${POWERSYNC_VERSION}`,
|
|
23
|
-
encrypt: true, // Required for Azure
|
|
24
|
-
trustServerCertificate: options.additionalConfig.trustServerCertificate
|
|
25
|
-
}
|
|
26
|
-
});
|
|
31
|
+
this.pool = new sql.ConnectionPool(createConnectionPoolConfig(options, poolOptions));
|
|
27
32
|
}
|
|
28
33
|
get connectionTag() {
|
|
29
34
|
return this.options.tag;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MSSQLConnectionManager.js","sourceRoot":"","sources":["../../src/replication/MSSQLConnectionManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,GAAG,MAAM,OAAO,CAAC;AAGxB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC;AAMpC,MAAM,
|
|
1
|
+
{"version":3,"file":"MSSQLConnectionManager.js","sourceRoot":"","sources":["../../src/replication/MSSQLConnectionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { SourceEntityDescriptor } from '@powersync/service-core';
|
|
2
|
+
import type { CaptureInstance } from '../common/CaptureInstance.js';
|
|
3
|
+
export declare enum MSSQLTableReconciliationState {
|
|
4
|
+
TABLE_MISSING = "table_missing",
|
|
5
|
+
CDC_DISABLED = "cdc_disabled",
|
|
6
|
+
READY = "ready"
|
|
7
|
+
}
|
|
8
|
+
interface BaseMSSQLTableReconciliationContext {
|
|
9
|
+
source: SourceEntityDescriptor;
|
|
10
|
+
}
|
|
11
|
+
export type MSSQLUnavailableTableReconciliationContext = (BaseMSSQLTableReconciliationContext & {
|
|
12
|
+
state: MSSQLTableReconciliationState.TABLE_MISSING;
|
|
13
|
+
}) | (BaseMSSQLTableReconciliationContext & {
|
|
14
|
+
state: MSSQLTableReconciliationState.CDC_DISABLED;
|
|
15
|
+
});
|
|
16
|
+
export type MSSQLReadyTableReconciliationContext = BaseMSSQLTableReconciliationContext & {
|
|
17
|
+
state: MSSQLTableReconciliationState.READY;
|
|
18
|
+
captureInstances: readonly CaptureInstance[];
|
|
19
|
+
};
|
|
20
|
+
export type MSSQLTableReconciliationContext = MSSQLUnavailableTableReconciliationContext | MSSQLReadyTableReconciliationContext;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export var MSSQLTableReconciliationState;
|
|
2
|
+
(function (MSSQLTableReconciliationState) {
|
|
3
|
+
MSSQLTableReconciliationState["TABLE_MISSING"] = "table_missing";
|
|
4
|
+
MSSQLTableReconciliationState["CDC_DISABLED"] = "cdc_disabled";
|
|
5
|
+
MSSQLTableReconciliationState["READY"] = "ready";
|
|
6
|
+
})(MSSQLTableReconciliationState || (MSSQLTableReconciliationState = {}));
|
|
7
|
+
//# sourceMappingURL=MSSQLTableReconciliationContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MSSQLTableReconciliationContext.js","sourceRoot":"","sources":["../../src/replication/MSSQLTableReconciliationContext.ts"],"names":[],"mappings":"AAGA,MAAM,CAAN,IAAY,6BAIX;AAJD,WAAY,6BAA6B;IACvC,gEAA+B,CAAA;IAC/B,8DAA6B,CAAA;IAC7B,gDAAe,CAAA;AACjB,CAAC,EAJW,6BAA6B,KAA7B,6BAA6B,QAIxC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { CaptureInstance } from '../common/CaptureInstance.js';
|
|
2
|
+
import { MSSQLSourceTable } from '../common/MSSQLSourceTable.js';
|
|
3
|
+
import { SourceTableChangeRef } from '../utils/schema.js';
|
|
4
|
+
/**
|
|
5
|
+
* Schema changes are detected to warn or error on, not applied automatically. Polling cannot be
|
|
6
|
+
* made atomic with a commit, so the replicated schema stays fixed until the next deploy.
|
|
7
|
+
*
|
|
8
|
+
* Drops and renames fail the job because they have no known LSN. Continuing could skip unread
|
|
9
|
+
* changes. Existing replicated data is kept for the next deploy to clean up.
|
|
10
|
+
*/
|
|
11
|
+
export declare enum SchemaChangeType {
|
|
12
|
+
/**
|
|
13
|
+
* A replicated table was renamed.
|
|
14
|
+
*/
|
|
15
|
+
TABLE_RENAME = "table_rename",
|
|
16
|
+
/**
|
|
17
|
+
* A replicated table was dropped.
|
|
18
|
+
*/
|
|
19
|
+
TABLE_DROP = "table_drop",
|
|
20
|
+
/**
|
|
21
|
+
* The source columns changed. The pinned capture schema remains active.
|
|
22
|
+
*/
|
|
23
|
+
TABLE_COLUMN_CHANGES = "table_column_changes",
|
|
24
|
+
/**
|
|
25
|
+
* A newer capture instance exists, but the pinned one is still available.
|
|
26
|
+
*/
|
|
27
|
+
NEW_CAPTURE_INSTANCE = "new_capture_instance",
|
|
28
|
+
/**
|
|
29
|
+
* The pinned capture instance is no longer available.
|
|
30
|
+
*/
|
|
31
|
+
MISSING_CAPTURE_INSTANCE = "missing_capture_instance"
|
|
32
|
+
}
|
|
33
|
+
interface SchemaChangeBase<Type extends SchemaChangeType> {
|
|
34
|
+
type: Type;
|
|
35
|
+
/**
|
|
36
|
+
* The replicated table the change applies to.
|
|
37
|
+
*/
|
|
38
|
+
table: MSSQLSourceTable;
|
|
39
|
+
}
|
|
40
|
+
export interface TableRenameChange extends SchemaChangeBase<SchemaChangeType.TABLE_RENAME> {
|
|
41
|
+
/**
|
|
42
|
+
* The name the table was renamed to. Only used in the error reported for the rename.
|
|
43
|
+
*/
|
|
44
|
+
newTable: SourceTableChangeRef;
|
|
45
|
+
}
|
|
46
|
+
export type TableDropChange = SchemaChangeBase<SchemaChangeType.TABLE_DROP>;
|
|
47
|
+
export interface TableColumnChanges extends SchemaChangeBase<SchemaChangeType.TABLE_COLUMN_CHANGES> {
|
|
48
|
+
/**
|
|
49
|
+
* The pinned capture instance the drift was observed against.
|
|
50
|
+
*/
|
|
51
|
+
captureInstance: CaptureInstance;
|
|
52
|
+
}
|
|
53
|
+
export interface NewCaptureInstanceChange extends SchemaChangeBase<SchemaChangeType.NEW_CAPTURE_INSTANCE> {
|
|
54
|
+
/**
|
|
55
|
+
* The newer instance that is available but will not be adopted by this stream.
|
|
56
|
+
*/
|
|
57
|
+
newCaptureInstance: CaptureInstance;
|
|
58
|
+
}
|
|
59
|
+
export interface MissingCaptureInstanceChange extends SchemaChangeBase<SchemaChangeType.MISSING_CAPTURE_INSTANCE> {
|
|
60
|
+
/**
|
|
61
|
+
* A newer instance that replaced the pinned one, if CDC is still enabled for the table. Only used
|
|
62
|
+
* to report the right recovery step.
|
|
63
|
+
*/
|
|
64
|
+
replacementInstance?: CaptureInstance;
|
|
65
|
+
}
|
|
66
|
+
export type SchemaChange = TableRenameChange | TableDropChange | TableColumnChanges | NewCaptureInstanceChange | MissingCaptureInstanceChange;
|
|
67
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema changes are detected to warn or error on, not applied automatically. Polling cannot be
|
|
3
|
+
* made atomic with a commit, so the replicated schema stays fixed until the next deploy.
|
|
4
|
+
*
|
|
5
|
+
* Drops and renames fail the job because they have no known LSN. Continuing could skip unread
|
|
6
|
+
* changes. Existing replicated data is kept for the next deploy to clean up.
|
|
7
|
+
*/
|
|
8
|
+
export var SchemaChangeType;
|
|
9
|
+
(function (SchemaChangeType) {
|
|
10
|
+
/**
|
|
11
|
+
* A replicated table was renamed.
|
|
12
|
+
*/
|
|
13
|
+
SchemaChangeType["TABLE_RENAME"] = "table_rename";
|
|
14
|
+
/**
|
|
15
|
+
* A replicated table was dropped.
|
|
16
|
+
*/
|
|
17
|
+
SchemaChangeType["TABLE_DROP"] = "table_drop";
|
|
18
|
+
/**
|
|
19
|
+
* The source columns changed. The pinned capture schema remains active.
|
|
20
|
+
*/
|
|
21
|
+
SchemaChangeType["TABLE_COLUMN_CHANGES"] = "table_column_changes";
|
|
22
|
+
/**
|
|
23
|
+
* A newer capture instance exists, but the pinned one is still available.
|
|
24
|
+
*/
|
|
25
|
+
SchemaChangeType["NEW_CAPTURE_INSTANCE"] = "new_capture_instance";
|
|
26
|
+
/**
|
|
27
|
+
* The pinned capture instance is no longer available.
|
|
28
|
+
*/
|
|
29
|
+
SchemaChangeType["MISSING_CAPTURE_INSTANCE"] = "missing_capture_instance";
|
|
30
|
+
})(SchemaChangeType || (SchemaChangeType = {}));
|
|
31
|
+
//# sourceMappingURL=SchemaChange.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaChange.js","sourceRoot":"","sources":["../../src/replication/SchemaChange.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,CAAN,IAAY,gBAqBX;AArBD,WAAY,gBAAgB;IAC1B;;OAEG;IACH,iDAA6B,CAAA;IAC7B;;OAEG;IACH,6CAAyB,CAAA;IACzB;;OAEG;IACH,iEAA6C,CAAA;IAC7C;;OAEG;IACH,iEAA6C,CAAA;IAC7C;;OAEG;IACH,yEAAqD,CAAA;AACvD,CAAC,EArBW,gBAAgB,KAAhB,gBAAgB,QAqB3B"}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -104,6 +104,10 @@ export interface NormalizedMSSQLConnectionConfig {
|
|
|
104
104
|
port: number;
|
|
105
105
|
database: string;
|
|
106
106
|
schema?: string;
|
|
107
|
+
/** PEM-encoded certificate authority used to validate the SQL Server certificate. */
|
|
108
|
+
cacert?: string;
|
|
109
|
+
/** Server name to use when validating the SQL Server certificate. */
|
|
110
|
+
tls_servername?: string;
|
|
107
111
|
authentication?: Authentication;
|
|
108
112
|
lookup?: LookupFunction;
|
|
109
113
|
additionalConfig: AdditionalConfig;
|
|
@@ -128,6 +132,10 @@ export declare const MSSQLConnectionConfig: t.Intersection<t.Codec<{
|
|
|
128
132
|
schema: t.OptionalCodec<t.Codec<string, string, string, t.CodecProps>>;
|
|
129
133
|
hostname: t.OptionalCodec<t.Codec<string, string, string, t.CodecProps>>;
|
|
130
134
|
port: t.OptionalCodec<t.Codec<number, string | number, string, t.CodecProps>>;
|
|
135
|
+
/** PEM-encoded certificate authority used to validate the SQL Server certificate. */
|
|
136
|
+
cacert: t.OptionalCodec<t.Codec<string, string, string, t.CodecProps>>;
|
|
137
|
+
/** Server name to use when validating the SQL Server certificate. */
|
|
138
|
+
tls_servername: t.OptionalCodec<t.Codec<string, string, string, t.CodecProps>>;
|
|
131
139
|
authentication: t.OptionalCodec<t.Codec<{
|
|
132
140
|
type: "azure-active-directory-service-principal-secret";
|
|
133
141
|
options: {
|
package/dist/types/types.js
CHANGED
|
@@ -63,6 +63,10 @@ export const MSSQLConnectionConfig = service_types.configFile.DataSourceConfig.a
|
|
|
63
63
|
schema: t.string.optional(),
|
|
64
64
|
hostname: t.string.optional(),
|
|
65
65
|
port: service_types.configFile.portCodec.optional(),
|
|
66
|
+
/** PEM-encoded certificate authority used to validate the SQL Server certificate. */
|
|
67
|
+
cacert: t.string.optional(),
|
|
68
|
+
/** Server name to use when validating the SQL Server certificate. */
|
|
69
|
+
tls_servername: t.string.optional(),
|
|
66
70
|
authentication: Authentication.optional(),
|
|
67
71
|
reject_ip_ranges: t.array(t.string).optional(),
|
|
68
72
|
additionalConfig: AdditionalConfig.optional(),
|
|
@@ -105,6 +109,9 @@ export function normalizeConnectionConfig(options) {
|
|
|
105
109
|
if (database == '') {
|
|
106
110
|
throw new ServiceError(ErrorCode.PSYNC_S1105, `MSSQL connection: database required`);
|
|
107
111
|
}
|
|
112
|
+
if (options.cacert && options.additionalConfig?.trustServerCertificate) {
|
|
113
|
+
throw new ServiceError(ErrorCode.PSYNC_S1604, 'MSSQL connection: cacert cannot be used with trustServerCertificate because certificate validation would be disabled');
|
|
114
|
+
}
|
|
108
115
|
const lookup = makeHostnameLookupFunction(hostname, { reject_ip_ranges: options.reject_ip_ranges ?? [] });
|
|
109
116
|
return {
|
|
110
117
|
id: options.id ?? 'default',
|
|
@@ -114,6 +121,8 @@ export function normalizeConnectionConfig(options) {
|
|
|
114
121
|
hostname,
|
|
115
122
|
port,
|
|
116
123
|
database,
|
|
124
|
+
cacert: options.cacert,
|
|
125
|
+
tls_servername: options.tls_servername,
|
|
117
126
|
lookup,
|
|
118
127
|
authentication: options.authentication,
|
|
119
128
|
additionalConfig: {
|
package/dist/types/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACxG,OAAO,KAAK,aAAa,MAAM,0BAA0B,CAAC;AAE1D,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAC9B,OAAO,KAAK,KAAK,MAAM,QAAQ,CAAC;AAEhC,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAC7C,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,CAAC;AAChD,MAAM,CAAC,MAAM,qBAAqB,GAAG,OAAgB,CAAC;AAEtD,MAAM,kCAAkC,GAAG,EAAE,CAAC;AAC9C,MAAM,8BAA8B,GAAG,CAAC,CAAC;AACzC,MAAM,8BAA8B,GAAG,EAAE,CAAC;AAE1C,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC,CAAC,MAAM,CAAC;IACjE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,iDAAiD,CAAC;IAClE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB;;WAEG;QACH,QAAQ,EAAE,CAAC,CAAC,MAAM;QAClB;;WAEG;QACH,YAAY,EAAE,CAAC,CAAC,MAAM;QACtB;;WAEG;QACH,QAAQ,EAAE,CAAC,CAAC,MAAM;KACnB,CAAC;CACH,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB;;WAEG;QACH,QAAQ,EAAE,CAAC,CAAC,MAAM;QAClB;;WAEG;QACH,QAAQ,EAAE,CAAC,CAAC,MAAM;KACnB,CAAC;CACH,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,cAAc,GAAG,qBAAqB,CAAC,EAAE,CAAC,0CAA0C,CAAC,CAAC;AAGnG,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC;;OAEG;IACH,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE;IACtC;;OAEG;IACH,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE;IAErC;;;OAGG;IACH,sBAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;CAC7C,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/mssql.js
CHANGED
|
@@ -264,7 +264,7 @@ export async function getDebugTableInfo(options) {
|
|
|
264
264
|
if (captureInstanceDetails && captureInstanceDetails.instances[0].pendingSchemaChanges.length > 0) {
|
|
265
265
|
schemaDriftError = {
|
|
266
266
|
level: 'warning',
|
|
267
|
-
message: `Source table ${toQualifiedTableName(schema, table.name)} has schema changes not reflected in the CDC capture instance.
|
|
267
|
+
message: `Source table ${toQualifiedTableName(schema, table.name)} has schema changes not reflected in the CDC capture instance. Create a replacement CDC capture instance with the intended columns, update the sync config if needed, and deploy a new sync config. If the change requires disabling CDC, re-enable CDC before deploying.
|
|
268
268
|
Pending schema changes: ${captureInstanceDetails.instances[0].pendingSchemaChanges.join(', \n')}`
|
|
269
269
|
};
|
|
270
270
|
}
|
package/dist/utils/schema.d.ts
CHANGED
|
@@ -17,11 +17,24 @@ export interface ReplicationIdentityColumnsResult {
|
|
|
17
17
|
}
|
|
18
18
|
export declare function getReplicationIdentityColumns(options: GetReplicationIdentityColumnsOptions): Promise<ReplicationIdentityColumnsResult>;
|
|
19
19
|
export interface SourceTableChangeRef {
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* `sys.tables.object_id`, which SQL Server always reports as an int. Narrower than
|
|
22
|
+
* `SourceEntityDescriptor.objectId`, which has to accommodate other source databases.
|
|
23
|
+
*/
|
|
24
|
+
objectId: number;
|
|
21
25
|
schema: string;
|
|
22
26
|
name: string;
|
|
23
27
|
}
|
|
24
28
|
export type ResolvedTable = SourceTableChangeRef;
|
|
29
|
+
export declare const SCHEMA_WILDCARD_MESSAGE = "Schema wildcards (\"%\") in table patterns are not supported for SQL Server connections.";
|
|
30
|
+
/**
|
|
31
|
+
* Wildcards would allow the replicated table set to change between polls, so they are rejected.
|
|
32
|
+
*/
|
|
33
|
+
export declare function tableWildcardMessage(tablePattern: TablePattern): string;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the reason this pattern cannot be replicated, or null if it is supported.
|
|
36
|
+
*/
|
|
37
|
+
export declare function unsupportedTablePatternMessage(tablePattern: TablePattern): string | null;
|
|
25
38
|
export declare function getTablesFromPattern(connectionManager: MSSQLConnectionManager, tablePattern: TablePattern): Promise<ResolvedTable[]>;
|
|
26
39
|
export interface GetPendingSchemaChangesOptions {
|
|
27
40
|
connectionManager: MSSQLConnectionManager;
|
package/dist/utils/schema.js
CHANGED
|
@@ -97,56 +97,51 @@ export async function getReplicationIdentityColumns(options) {
|
|
|
97
97
|
identity: 'full'
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
|
-
export
|
|
100
|
+
export const SCHEMA_WILDCARD_MESSAGE = 'Schema wildcards ("%") in table patterns are not supported for SQL Server connections.';
|
|
101
|
+
/**
|
|
102
|
+
* Wildcards would allow the replicated table set to change between polls, so they are rejected.
|
|
103
|
+
*/
|
|
104
|
+
export function tableWildcardMessage(tablePattern) {
|
|
105
|
+
return (`Table wildcards ("%") are not supported for SQL Server connections: "${tablePattern.tablePattern}". ` +
|
|
106
|
+
`List each table explicitly.`);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Returns the reason this pattern cannot be replicated, or null if it is supported.
|
|
110
|
+
*/
|
|
111
|
+
export function unsupportedTablePatternMessage(tablePattern) {
|
|
101
112
|
if (tablePattern.isSchemaWildcard) {
|
|
102
|
-
|
|
113
|
+
return SCHEMA_WILDCARD_MESSAGE;
|
|
103
114
|
}
|
|
104
115
|
if (tablePattern.isWildcard) {
|
|
105
|
-
|
|
106
|
-
SELECT
|
|
107
|
-
tbl.name AS [table],
|
|
108
|
-
sch.name AS [schema],
|
|
109
|
-
tbl.object_id AS object_id
|
|
110
|
-
FROM sys.tables tbl
|
|
111
|
-
JOIN sys.schemas sch ON tbl.schema_id = sch.schema_id
|
|
112
|
-
WHERE sch.name = @schema
|
|
113
|
-
AND tbl.name LIKE @tablePattern
|
|
114
|
-
`, [
|
|
115
|
-
{ name: 'schema', type: sql.VarChar(sql.MAX), value: tablePattern.schema },
|
|
116
|
-
{ name: 'tablePattern', type: sql.VarChar(sql.MAX), value: tablePattern.tablePattern }
|
|
117
|
-
]);
|
|
118
|
-
return tableResults
|
|
119
|
-
.map((row) => {
|
|
120
|
-
return {
|
|
121
|
-
objectId: row.object_id,
|
|
122
|
-
schema: row.schema,
|
|
123
|
-
name: row.table
|
|
124
|
-
};
|
|
125
|
-
})
|
|
126
|
-
.filter((table) => table.name.startsWith(tablePattern.tablePrefix));
|
|
116
|
+
return tableWildcardMessage(tablePattern);
|
|
127
117
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
FROM sys.tables tbl
|
|
135
|
-
JOIN sys.schemas sch ON tbl.schema_id = sch.schema_id
|
|
136
|
-
WHERE sch.name = @schema
|
|
137
|
-
AND tbl.name = @tablePattern
|
|
138
|
-
`, [
|
|
139
|
-
{ name: 'schema', type: sql.VarChar(sql.MAX), value: tablePattern.schema },
|
|
140
|
-
{ name: 'tablePattern', type: sql.VarChar(sql.MAX), value: tablePattern.tablePattern }
|
|
141
|
-
]);
|
|
142
|
-
return tableResults.map((row) => {
|
|
143
|
-
return {
|
|
144
|
-
objectId: row.object_id,
|
|
145
|
-
schema: row.schema,
|
|
146
|
-
name: row.table
|
|
147
|
-
};
|
|
148
|
-
});
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
export async function getTablesFromPattern(connectionManager, tablePattern) {
|
|
121
|
+
const unsupported = unsupportedTablePatternMessage(tablePattern);
|
|
122
|
+
if (unsupported != null) {
|
|
123
|
+
throw new ServiceError(ErrorCode.PSYNC_R2201, unsupported);
|
|
149
124
|
}
|
|
125
|
+
const { recordset: tableResults } = await connectionManager.query(`
|
|
126
|
+
SELECT
|
|
127
|
+
tbl.name AS [table],
|
|
128
|
+
sch.name AS [schema],
|
|
129
|
+
tbl.object_id AS object_id
|
|
130
|
+
FROM sys.tables tbl
|
|
131
|
+
JOIN sys.schemas sch ON tbl.schema_id = sch.schema_id
|
|
132
|
+
WHERE sch.name = @schema
|
|
133
|
+
AND tbl.name = @tablePattern
|
|
134
|
+
`, [
|
|
135
|
+
{ name: 'schema', type: sql.VarChar(sql.MAX), value: tablePattern.schema },
|
|
136
|
+
{ name: 'tablePattern', type: sql.VarChar(sql.MAX), value: tablePattern.tablePattern }
|
|
137
|
+
]);
|
|
138
|
+
return tableResults.map((row) => {
|
|
139
|
+
return {
|
|
140
|
+
objectId: row.object_id,
|
|
141
|
+
schema: row.schema,
|
|
142
|
+
name: row.table
|
|
143
|
+
};
|
|
144
|
+
});
|
|
150
145
|
}
|
|
151
146
|
/**
|
|
152
147
|
* Returns the DDL commands that have been applied to the source table since the capture instance was created.
|
package/dist/utils/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powersync/service-module-mssql",
|
|
3
3
|
"repository": "https://github.com/powersync-ja/powersync-service",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.10.0",
|
|
5
5
|
"license": "FSL-1.1-ALv2",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"publishConfig": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"uri-js": "^4.4.1",
|
|
19
19
|
"uuid": "^14.0.0",
|
|
20
20
|
"@powersync/lib-services-framework": "0.10.0",
|
|
21
|
-
"@powersync/service-core": "1.
|
|
21
|
+
"@powersync/service-core": "1.25.0",
|
|
22
22
|
"@powersync/service-errors": "0.5.0",
|
|
23
23
|
"@powersync/service-jsonbig": "0.17.13",
|
|
24
24
|
"@powersync/service-sync-rules": "0.40.0",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"@types/semver": "^7.7.1",
|
|
30
30
|
"@types/uuid": "^11.0.0",
|
|
31
31
|
"@powersync/service-core-tests": "0.18.0",
|
|
32
|
-
"@powersync/service-module-mongodb-storage": "0.
|
|
33
|
-
"@powersync/service-module-postgres-storage": "0.
|
|
32
|
+
"@powersync/service-module-mongodb-storage": "0.20.0",
|
|
33
|
+
"@powersync/service-module-postgres-storage": "0.18.0"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "tsc -b",
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
getLatestLSN,
|
|
13
13
|
POWERSYNC_CHECKPOINTS_TABLE
|
|
14
14
|
} from '../utils/mssql.js';
|
|
15
|
-
import { getTablesFromPattern, ResolvedTable } from '../utils/schema.js';
|
|
15
|
+
import { getTablesFromPattern, ResolvedTable, unsupportedTablePatternMessage } from '../utils/schema.js';
|
|
16
16
|
|
|
17
17
|
export class MSSQLRouteAPIAdapter implements api.RouteAPI {
|
|
18
18
|
protected connectionManager: MSSQLConnectionManager;
|
|
@@ -182,41 +182,35 @@ export class MSSQLRouteAPIAdapter implements api.RouteAPI {
|
|
|
182
182
|
};
|
|
183
183
|
result.push(patternResult);
|
|
184
184
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
// This should technically never happen, but we'll handle it anyway.
|
|
200
|
-
const resolvedTable: ResolvedTable = {
|
|
201
|
-
objectId: 0,
|
|
202
|
-
schema: schema,
|
|
203
|
-
name: tablePattern.name
|
|
204
|
-
};
|
|
205
|
-
patternResult.table = await getDebugTableInfo({
|
|
206
|
-
connectionManager: this.connectionManager,
|
|
207
|
-
tablePattern,
|
|
208
|
-
table: resolvedTable,
|
|
209
|
-
syncRules: sqlSyncRules
|
|
210
|
-
});
|
|
185
|
+
// Unsupported patterns are reported per pattern here, rather than failing the whole request.
|
|
186
|
+
const unsupported = unsupportedTablePatternMessage(tablePattern);
|
|
187
|
+
if (unsupported != null) {
|
|
188
|
+
const unsupportedTable: service_types.TableInfo = {
|
|
189
|
+
schema,
|
|
190
|
+
name: tablePattern.tablePattern,
|
|
191
|
+
pattern: tablePattern.tablePattern,
|
|
192
|
+
replication_id: [],
|
|
193
|
+
data_queries: false,
|
|
194
|
+
parameter_queries: false,
|
|
195
|
+
errors: [{ level: 'fatal', message: unsupported }]
|
|
196
|
+
};
|
|
197
|
+
if (patternResult.wildcard) {
|
|
198
|
+
patternResult.tables = [unsupportedTable];
|
|
211
199
|
} else {
|
|
212
|
-
patternResult.table =
|
|
213
|
-
connectionManager: this.connectionManager,
|
|
214
|
-
tablePattern,
|
|
215
|
-
table: tables[0],
|
|
216
|
-
syncRules: sqlSyncRules
|
|
217
|
-
});
|
|
200
|
+
patternResult.table = unsupportedTable;
|
|
218
201
|
}
|
|
202
|
+
continue;
|
|
219
203
|
}
|
|
204
|
+
|
|
205
|
+
const tables = await getTablesFromPattern(this.connectionManager, tablePattern);
|
|
206
|
+
// A missing table is still reported, so that its errors are surfaced.
|
|
207
|
+
const resolvedTable: ResolvedTable = tables[0] ?? { objectId: 0, schema: schema, name: tablePattern.name };
|
|
208
|
+
patternResult.table = await getDebugTableInfo({
|
|
209
|
+
connectionManager: this.connectionManager,
|
|
210
|
+
tablePattern,
|
|
211
|
+
table: resolvedTable,
|
|
212
|
+
syncRules: sqlSyncRules
|
|
213
|
+
});
|
|
220
214
|
}
|
|
221
215
|
|
|
222
216
|
return result;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SourceEntityDescriptor, SourceTable } from '@powersync/service-core';
|
|
2
2
|
import { ServiceAssertionError } from '@powersync/service-errors';
|
|
3
|
+
import { readCaptureMetadata } from '../replication/CaptureReconciler.js';
|
|
3
4
|
import { toQualifiedTableName } from '../utils/mssql.js';
|
|
4
5
|
import { CaptureInstance } from './CaptureInstance.js';
|
|
5
6
|
|
|
@@ -26,9 +27,15 @@ export class MSSQLSourceTable {
|
|
|
26
27
|
|
|
27
28
|
public readonly ref: SourceEntityDescriptor;
|
|
28
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Decoded once, since the persisted metadata only changes when a SourceTable is replaced.
|
|
32
|
+
*/
|
|
33
|
+
private captureObjectId: number | null;
|
|
34
|
+
|
|
29
35
|
constructor(ref: SourceEntityDescriptor, sourceTables: SourceTable[]) {
|
|
30
36
|
this.sourceTables = sourceTables;
|
|
31
37
|
this.ref = ref;
|
|
38
|
+
this.captureObjectId = readPinnedCaptureObjectId(sourceTables);
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
updateSourceTable(updated: SourceTable): void {
|
|
@@ -37,6 +44,7 @@ export class MSSQLSourceTable {
|
|
|
37
44
|
throw new ServiceAssertionError(`No SourceTable found for table: ${updated.id}`);
|
|
38
45
|
}
|
|
39
46
|
this.sourceTables[index] = updated;
|
|
47
|
+
this.captureObjectId = readPinnedCaptureObjectId(this.sourceTables);
|
|
40
48
|
}
|
|
41
49
|
|
|
42
50
|
getReplicatedSourceTables(): SourceTable[] {
|
|
@@ -47,12 +55,19 @@ export class MSSQLSourceTable {
|
|
|
47
55
|
return this.captureInstance !== null;
|
|
48
56
|
}
|
|
49
57
|
|
|
50
|
-
|
|
51
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Persisted capture-table object id, or null for a legacy binding.
|
|
60
|
+
*/
|
|
61
|
+
get pinnedCaptureObjectId(): number | null {
|
|
62
|
+
return this.captureObjectId;
|
|
52
63
|
}
|
|
53
64
|
|
|
54
|
-
|
|
55
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Bind the available capture instance matching this table's persisted identity.
|
|
67
|
+
*/
|
|
68
|
+
setCaptureInstance(availableInstances: readonly CaptureInstance[]): void {
|
|
69
|
+
this.captureInstance =
|
|
70
|
+
availableInstances.find((instance) => instance.objectId === this.pinnedCaptureObjectId) ?? null;
|
|
56
71
|
}
|
|
57
72
|
|
|
58
73
|
get allChangesFunction() {
|
|
@@ -84,3 +99,16 @@ export class MSSQLSourceTable {
|
|
|
84
99
|
return toQualifiedTableName(this.ref.schema, this.ref.name);
|
|
85
100
|
}
|
|
86
101
|
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The pinned capture-table object id shared by these records, or null for a legacy binding.
|
|
105
|
+
*/
|
|
106
|
+
function readPinnedCaptureObjectId(sourceTables: SourceTable[]): number | null {
|
|
107
|
+
for (const sourceTable of sourceTables) {
|
|
108
|
+
const metadata = readCaptureMetadata(sourceTable.sourceMetadata);
|
|
109
|
+
if (metadata != null) {
|
|
110
|
+
return metadata.captureTableObjectId;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|