@powersync/service-module-mssql 0.0.1
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/LICENSE +67 -0
- package/README.md +3 -0
- package/ci/init-mssql.sql +50 -0
- package/dist/api/MSSQLRouteAPIAdapter.d.ts +21 -0
- package/dist/api/MSSQLRouteAPIAdapter.js +248 -0
- package/dist/api/MSSQLRouteAPIAdapter.js.map +1 -0
- package/dist/common/LSN.d.ts +37 -0
- package/dist/common/LSN.js +64 -0
- package/dist/common/LSN.js.map +1 -0
- package/dist/common/MSSQLSourceTable.d.ts +27 -0
- package/dist/common/MSSQLSourceTable.js +35 -0
- package/dist/common/MSSQLSourceTable.js.map +1 -0
- package/dist/common/MSSQLSourceTableCache.d.ts +14 -0
- package/dist/common/MSSQLSourceTableCache.js +28 -0
- package/dist/common/MSSQLSourceTableCache.js.map +1 -0
- package/dist/common/mssqls-to-sqlite.d.ts +18 -0
- package/dist/common/mssqls-to-sqlite.js +143 -0
- package/dist/common/mssqls-to-sqlite.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/module/MSSQLModule.d.ts +15 -0
- package/dist/module/MSSQLModule.js +68 -0
- package/dist/module/MSSQLModule.js.map +1 -0
- package/dist/replication/CDCPoller.d.ts +67 -0
- package/dist/replication/CDCPoller.js +183 -0
- package/dist/replication/CDCPoller.js.map +1 -0
- package/dist/replication/CDCReplicationJob.d.ts +17 -0
- package/dist/replication/CDCReplicationJob.js +76 -0
- package/dist/replication/CDCReplicationJob.js.map +1 -0
- package/dist/replication/CDCReplicator.d.ts +18 -0
- package/dist/replication/CDCReplicator.js +55 -0
- package/dist/replication/CDCReplicator.js.map +1 -0
- package/dist/replication/CDCStream.d.ts +106 -0
- package/dist/replication/CDCStream.js +536 -0
- package/dist/replication/CDCStream.js.map +1 -0
- package/dist/replication/MSSQLConnectionManager.d.ts +23 -0
- package/dist/replication/MSSQLConnectionManager.js +97 -0
- package/dist/replication/MSSQLConnectionManager.js.map +1 -0
- package/dist/replication/MSSQLConnectionManagerFactory.d.ts +10 -0
- package/dist/replication/MSSQLConnectionManagerFactory.js +28 -0
- package/dist/replication/MSSQLConnectionManagerFactory.js.map +1 -0
- package/dist/replication/MSSQLErrorRateLimiter.d.ts +10 -0
- package/dist/replication/MSSQLErrorRateLimiter.js +34 -0
- package/dist/replication/MSSQLErrorRateLimiter.js.map +1 -0
- package/dist/replication/MSSQLSnapshotQuery.d.ts +71 -0
- package/dist/replication/MSSQLSnapshotQuery.js +190 -0
- package/dist/replication/MSSQLSnapshotQuery.js.map +1 -0
- package/dist/types/mssql-data-types.d.ts +66 -0
- package/dist/types/mssql-data-types.js +62 -0
- package/dist/types/mssql-data-types.js.map +1 -0
- package/dist/types/types.d.ts +177 -0
- package/dist/types/types.js +141 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utils/mssql.d.ts +80 -0
- package/dist/utils/mssql.js +329 -0
- package/dist/utils/mssql.js.map +1 -0
- package/dist/utils/schema.d.ts +21 -0
- package/dist/utils/schema.js +131 -0
- package/dist/utils/schema.js.map +1 -0
- package/package.json +51 -0
- package/src/api/MSSQLRouteAPIAdapter.ts +283 -0
- package/src/common/LSN.ts +77 -0
- package/src/common/MSSQLSourceTable.ts +54 -0
- package/src/common/MSSQLSourceTableCache.ts +36 -0
- package/src/common/mssqls-to-sqlite.ts +151 -0
- package/src/index.ts +1 -0
- package/src/module/MSSQLModule.ts +82 -0
- package/src/replication/CDCPoller.ts +241 -0
- package/src/replication/CDCReplicationJob.ts +87 -0
- package/src/replication/CDCReplicator.ts +70 -0
- package/src/replication/CDCStream.ts +688 -0
- package/src/replication/MSSQLConnectionManager.ts +113 -0
- package/src/replication/MSSQLConnectionManagerFactory.ts +33 -0
- package/src/replication/MSSQLErrorRateLimiter.ts +36 -0
- package/src/replication/MSSQLSnapshotQuery.ts +230 -0
- package/src/types/mssql-data-types.ts +79 -0
- package/src/types/types.ts +224 -0
- package/src/utils/mssql.ts +420 -0
- package/src/utils/schema.ts +172 -0
- package/test/src/CDCStream.test.ts +206 -0
- package/test/src/CDCStreamTestContext.ts +212 -0
- package/test/src/CDCStream_resumable_snapshot.test.ts +152 -0
- package/test/src/env.ts +11 -0
- package/test/src/mssql-to-sqlite.test.ts +474 -0
- package/test/src/setup.ts +12 -0
- package/test/src/util.ts +189 -0
- package/test/tsconfig.json +28 -0
- package/test/tsconfig.tsbuildinfo +1 -0
- package/tsconfig.json +26 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +15 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import sql from 'mssql';
|
|
2
|
+
import { coerce, gte } from 'semver';
|
|
3
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
4
|
+
import { LSN } from '../common/LSN.js';
|
|
5
|
+
import { getReplicationIdentityColumns } from './schema.js';
|
|
6
|
+
export const POWERSYNC_CHECKPOINTS_TABLE = '_powersync_checkpoints';
|
|
7
|
+
export const SUPPORTED_ENGINE_EDITIONS = new Map([
|
|
8
|
+
[2, 'Standard'],
|
|
9
|
+
[3, 'Enterprise - Enterprise, Developer, Evaluation'],
|
|
10
|
+
[5, 'SqlDatabase - Azure SQL Database'],
|
|
11
|
+
[8, 'SqlManagedInstance - Azure SQL Managed Instance']
|
|
12
|
+
]);
|
|
13
|
+
// SQL Server 2022 and newer
|
|
14
|
+
export const MINIMUM_SUPPORTED_VERSION = '16.0';
|
|
15
|
+
export async function checkSourceConfiguration(connectionManager) {
|
|
16
|
+
const errors = [];
|
|
17
|
+
// 1) Check MSSQL version and Editions
|
|
18
|
+
const { recordset: versionResult } = await connectionManager.query(`
|
|
19
|
+
SELECT
|
|
20
|
+
CAST(SERVERPROPERTY('EngineEdition') AS int) AS engine,
|
|
21
|
+
CAST(SERVERPROPERTY('Edition') AS nvarchar(128)) AS edition,
|
|
22
|
+
CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(128)) AS version
|
|
23
|
+
`);
|
|
24
|
+
// If the edition is unsupported, return immediately
|
|
25
|
+
if (!SUPPORTED_ENGINE_EDITIONS.has(versionResult[0]?.engine)) {
|
|
26
|
+
errors.push(`The SQL Server edition '${versionResult[0]?.edition}' is not supported. PowerSync requires a MSSQL edition that supports CDC: ${Array.from(SUPPORTED_ENGINE_EDITIONS.values()).join(', ')}.`);
|
|
27
|
+
return errors;
|
|
28
|
+
}
|
|
29
|
+
// Only applicable to SQL Server stand-alone editions
|
|
30
|
+
if (versionResult[0]?.engine == 2 || versionResult[0]?.engine == 3) {
|
|
31
|
+
if (!isVersionAtLeast(versionResult[0]?.version, MINIMUM_SUPPORTED_VERSION)) {
|
|
32
|
+
errors.push(`The SQL Server version '${versionResult[0]?.version}' is not supported. PowerSync requires MSSQL 2022 (v16) or newer.`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// 2) Check DB-level CDC
|
|
36
|
+
const { recordset: cdcEnabledResult } = await connectionManager.query(`
|
|
37
|
+
SELECT name AS db_name, is_cdc_enabled FROM sys.databases WHERE name = DB_NAME();
|
|
38
|
+
`);
|
|
39
|
+
const cdcEnabled = cdcEnabledResult[0]?.is_cdc_enabled;
|
|
40
|
+
if (!cdcEnabled) {
|
|
41
|
+
errors.push(`CDC is not enabled for database. Please enable it.`);
|
|
42
|
+
}
|
|
43
|
+
// 3) Check CDC user permissions
|
|
44
|
+
const { recordset: cdcUserResult } = await connectionManager.query(`
|
|
45
|
+
SELECT
|
|
46
|
+
CASE
|
|
47
|
+
WHEN IS_SRVROLEMEMBER('sysadmin') = 1
|
|
48
|
+
OR IS_MEMBER('db_owner') = 1
|
|
49
|
+
OR IS_MEMBER('cdc_admin') = 1
|
|
50
|
+
OR IS_MEMBER('cdc_reader') = 1
|
|
51
|
+
THEN 1 ELSE 0
|
|
52
|
+
END AS has_cdc_access;
|
|
53
|
+
`);
|
|
54
|
+
if (!cdcUserResult[0]?.has_cdc_access) {
|
|
55
|
+
errors.push(`The current user does not have the 'cdc_reader' role. Please assign this role to the user.`);
|
|
56
|
+
}
|
|
57
|
+
// 4) Check if the _powersync_checkpoints table is correctly configured
|
|
58
|
+
const checkpointTableErrors = await ensurePowerSyncCheckpointsTable(connectionManager);
|
|
59
|
+
errors.push(...checkpointTableErrors);
|
|
60
|
+
return errors;
|
|
61
|
+
}
|
|
62
|
+
export async function ensurePowerSyncCheckpointsTable(connectionManager) {
|
|
63
|
+
const errors = [];
|
|
64
|
+
try {
|
|
65
|
+
// check if the dbo_powersync_checkpoints table exists
|
|
66
|
+
const { recordset: checkpointsResult } = await connectionManager.query(`
|
|
67
|
+
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '${connectionManager.schema}' AND TABLE_NAME = '${POWERSYNC_CHECKPOINTS_TABLE}';
|
|
68
|
+
`);
|
|
69
|
+
if (checkpointsResult.length > 0) {
|
|
70
|
+
// Table already exists, check if CDC is enabled
|
|
71
|
+
const isEnabled = await isTableEnabledForCDC({
|
|
72
|
+
connectionManager,
|
|
73
|
+
table: POWERSYNC_CHECKPOINTS_TABLE,
|
|
74
|
+
schema: connectionManager.schema
|
|
75
|
+
});
|
|
76
|
+
if (!isEnabled) {
|
|
77
|
+
// Enable CDC on the table
|
|
78
|
+
await enableCDCForTable({
|
|
79
|
+
connectionManager,
|
|
80
|
+
table: POWERSYNC_CHECKPOINTS_TABLE
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return errors;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
errors.push(`Failed ensure ${POWERSYNC_CHECKPOINTS_TABLE} table is correctly configured: ${error}`);
|
|
88
|
+
}
|
|
89
|
+
// Try to create the table
|
|
90
|
+
try {
|
|
91
|
+
await connectionManager.query(`
|
|
92
|
+
CREATE TABLE ${connectionManager.schema}.${POWERSYNC_CHECKPOINTS_TABLE} (
|
|
93
|
+
id INT IDENTITY PRIMARY KEY,
|
|
94
|
+
last_updated DATETIME NOT NULL DEFAULT (GETDATE())
|
|
95
|
+
)`);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
errors.push(`Failed to create ${POWERSYNC_CHECKPOINTS_TABLE} table: ${error}`);
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
// Enable CDC on the table if not already enabled
|
|
102
|
+
await enableCDCForTable({
|
|
103
|
+
connectionManager,
|
|
104
|
+
table: POWERSYNC_CHECKPOINTS_TABLE
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
errors.push(`Failed to enable CDC on ${POWERSYNC_CHECKPOINTS_TABLE} table: ${error}`);
|
|
109
|
+
}
|
|
110
|
+
return errors;
|
|
111
|
+
}
|
|
112
|
+
export async function createCheckpoint(connectionManager) {
|
|
113
|
+
await connectionManager.query(`
|
|
114
|
+
MERGE ${connectionManager.schema}.${POWERSYNC_CHECKPOINTS_TABLE} AS target
|
|
115
|
+
USING (SELECT 1 AS id) AS source
|
|
116
|
+
ON target.id = source.id
|
|
117
|
+
WHEN MATCHED THEN
|
|
118
|
+
UPDATE SET last_updated = GETDATE()
|
|
119
|
+
WHEN NOT MATCHED THEN
|
|
120
|
+
INSERT (last_updated) VALUES (GETDATE());
|
|
121
|
+
`);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Check if the specified table is enabled for CDC.
|
|
125
|
+
* @param options
|
|
126
|
+
*/
|
|
127
|
+
export async function isTableEnabledForCDC(options) {
|
|
128
|
+
const { connectionManager, table, schema } = options;
|
|
129
|
+
const { recordset: checkResult } = await connectionManager.query(`
|
|
130
|
+
SELECT 1 FROM cdc.change_tables ct
|
|
131
|
+
JOIN sys.tables AS tbl ON tbl.object_id = ct.source_object_id
|
|
132
|
+
JOIN sys.schemas AS sch ON sch.schema_id = tbl.schema_id
|
|
133
|
+
WHERE sch.name = '${schema}'
|
|
134
|
+
AND tbl.name = '${table}'
|
|
135
|
+
`);
|
|
136
|
+
return checkResult.length > 0;
|
|
137
|
+
}
|
|
138
|
+
export async function enableCDCForTable(options) {
|
|
139
|
+
const { connectionManager, table } = options;
|
|
140
|
+
await connectionManager.execute('sys.sp_cdc_enable_table', [
|
|
141
|
+
{ name: 'source_schema', value: connectionManager.schema },
|
|
142
|
+
{ name: 'source_name', value: table },
|
|
143
|
+
{ name: 'role_name', value: 'NULL' },
|
|
144
|
+
{ name: 'supports_net_changes', value: 1 }
|
|
145
|
+
]);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Check if the supplied version is newer or equal to the target version.
|
|
149
|
+
* @param version
|
|
150
|
+
* @param minimumVersion
|
|
151
|
+
*/
|
|
152
|
+
export function isVersionAtLeast(version, minimumVersion) {
|
|
153
|
+
const coercedVersion = coerce(version);
|
|
154
|
+
const coercedMinimumVersion = coerce(minimumVersion);
|
|
155
|
+
return gte(coercedVersion, coercedMinimumVersion, { loose: true });
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Checks that CDC the specified checkpoint LSN is within the retention threshold for all specified tables.
|
|
159
|
+
* CDC periodically cleans up old data up to the retention threshold. If replication has been stopped for too long it is
|
|
160
|
+
* possible for the checkpoint LSN to be older than the minimum LSN in the CDC tables. In such a case we need to perform a new snapshot.
|
|
161
|
+
* @param options
|
|
162
|
+
*/
|
|
163
|
+
export async function isWithinRetentionThreshold(options) {
|
|
164
|
+
const { checkpointLSN, tables, connectionManager } = options;
|
|
165
|
+
for (const table of tables) {
|
|
166
|
+
const minLSN = await getMinLSN(connectionManager, table.captureInstance);
|
|
167
|
+
if (minLSN > checkpointLSN) {
|
|
168
|
+
logger.warn(`The checkpoint LSN:[${checkpointLSN}] is older than the minimum LSN:[${minLSN}] for table ${table.sourceTable.qualifiedName}. This indicates that the checkpoint LSN is outside of the retention window.`);
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
export async function getMinLSN(connectionManager, captureInstance) {
|
|
175
|
+
const { recordset: result } = await connectionManager.query(`SELECT sys.fn_cdc_get_min_lsn('${captureInstance}') AS min_lsn`);
|
|
176
|
+
const rawMinLSN = result[0].min_lsn;
|
|
177
|
+
return LSN.fromBinary(rawMinLSN);
|
|
178
|
+
}
|
|
179
|
+
export async function incrementLSN(lsn, connectionManager) {
|
|
180
|
+
const { recordset: result } = await connectionManager.query(`SELECT sys.fn_cdc_increment_lsn(@lsn) AS incremented_lsn`, [{ name: 'lsn', type: sql.VarBinary, value: lsn.toBinary() }]);
|
|
181
|
+
return LSN.fromBinary(result[0].incremented_lsn);
|
|
182
|
+
}
|
|
183
|
+
export async function getCaptureInstance(options) {
|
|
184
|
+
const { connectionManager, tableName, schema } = options;
|
|
185
|
+
const { recordset: result } = await connectionManager.query(`
|
|
186
|
+
SELECT
|
|
187
|
+
ct.capture_instance,
|
|
188
|
+
OBJECT_SCHEMA_NAME(ct.[object_id]) AS cdc_schema
|
|
189
|
+
FROM
|
|
190
|
+
sys.tables tbl
|
|
191
|
+
INNER JOIN sys.schemas sch ON tbl.schema_id = sch.schema_id
|
|
192
|
+
INNER JOIN cdc.change_tables ct ON ct.source_object_id = tbl.object_id
|
|
193
|
+
WHERE sch.name = '${schema}'
|
|
194
|
+
AND tbl.name = '${tableName}'
|
|
195
|
+
AND ct.end_lsn IS NULL;
|
|
196
|
+
`);
|
|
197
|
+
if (result.length === 0) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
name: result[0].capture_instance,
|
|
202
|
+
schema: result[0].cdc_schema
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Return the LSN of the latest transaction recorded in the transaction log
|
|
207
|
+
* @param connectionManager
|
|
208
|
+
*/
|
|
209
|
+
export async function getLatestLSN(connectionManager) {
|
|
210
|
+
const { recordset: result } = await connectionManager.query('SELECT log_end_lsn FROM sys.dm_db_log_stats(DB_ID()) AS log_end_lsn');
|
|
211
|
+
return LSN.fromString(result[0].log_end_lsn);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Return the LSN of the lastest transaction replicated to the CDC tables.
|
|
215
|
+
* @param connectionManager
|
|
216
|
+
*/
|
|
217
|
+
export async function getLatestReplicatedLSN(connectionManager) {
|
|
218
|
+
const { recordset: result } = await connectionManager.query('SELECT sys.fn_cdc_get_max_lsn() AS max_lsn;');
|
|
219
|
+
// LSN is a binary(10) returned as a Buffer
|
|
220
|
+
const rawLSN = result[0].max_lsn;
|
|
221
|
+
return LSN.fromBinary(rawLSN);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Escapes an identifier for use in MSSQL queries.
|
|
225
|
+
* @param identifier
|
|
226
|
+
*/
|
|
227
|
+
export function escapeIdentifier(identifier) {
|
|
228
|
+
return `[${identifier}]`;
|
|
229
|
+
}
|
|
230
|
+
export function toQualifiedTableName(schema, tableName) {
|
|
231
|
+
return `${escapeIdentifier(schema)}.${escapeIdentifier(tableName)}`;
|
|
232
|
+
}
|
|
233
|
+
export function isIColumnMetadata(obj) {
|
|
234
|
+
if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
let propertiesMatched = true;
|
|
238
|
+
for (const value of Object.values(obj)) {
|
|
239
|
+
const property = value;
|
|
240
|
+
propertiesMatched =
|
|
241
|
+
typeof property.index === 'number' &&
|
|
242
|
+
typeof property.name === 'string' &&
|
|
243
|
+
typeof property.length === 'number' &&
|
|
244
|
+
(typeof property.type === 'function' || typeof property.type === 'object') &&
|
|
245
|
+
typeof property.nullable === 'boolean' &&
|
|
246
|
+
typeof property.caseSensitive === 'boolean' &&
|
|
247
|
+
typeof property.identity === 'boolean' &&
|
|
248
|
+
typeof property.readOnly === 'boolean';
|
|
249
|
+
}
|
|
250
|
+
return propertiesMatched;
|
|
251
|
+
}
|
|
252
|
+
export function addParameters(request, parameters) {
|
|
253
|
+
for (const param of parameters) {
|
|
254
|
+
if (param.type) {
|
|
255
|
+
request.input(param.name, param.type, param.value);
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
request.input(param.name, param.value);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return request;
|
|
262
|
+
}
|
|
263
|
+
export async function getDebugTableInfo(options) {
|
|
264
|
+
const { connectionManager, tablePattern, table, syncRules } = options;
|
|
265
|
+
const { schema } = tablePattern;
|
|
266
|
+
let idColumnsResult = null;
|
|
267
|
+
let idColumnsError = null;
|
|
268
|
+
try {
|
|
269
|
+
idColumnsResult = await getReplicationIdentityColumns({
|
|
270
|
+
connectionManager: connectionManager,
|
|
271
|
+
schema,
|
|
272
|
+
tableName: table.name
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
catch (ex) {
|
|
276
|
+
idColumnsError = { level: 'fatal', message: ex.message };
|
|
277
|
+
}
|
|
278
|
+
const idColumns = idColumnsResult?.columns ?? [];
|
|
279
|
+
const sourceTable = {
|
|
280
|
+
connectionTag: connectionManager.connectionTag,
|
|
281
|
+
schema: schema,
|
|
282
|
+
name: table.name
|
|
283
|
+
};
|
|
284
|
+
const syncData = syncRules.tableSyncsData(sourceTable);
|
|
285
|
+
const syncParameters = syncRules.tableSyncsParameters(sourceTable);
|
|
286
|
+
if (idColumns.length === 0 && idColumnsError == null) {
|
|
287
|
+
let message = `No replication id found for ${toQualifiedTableName(schema, table.name)}. Replica identity: ${idColumnsResult?.identity}.`;
|
|
288
|
+
if (idColumnsResult?.identity === 'default') {
|
|
289
|
+
message += ' Configure a primary key on the table.';
|
|
290
|
+
}
|
|
291
|
+
idColumnsError = { level: 'fatal', message };
|
|
292
|
+
}
|
|
293
|
+
let selectError = null;
|
|
294
|
+
try {
|
|
295
|
+
await connectionManager.query(`SELECT TOP 1 * FROM [${toQualifiedTableName(schema, table.name)}]`);
|
|
296
|
+
}
|
|
297
|
+
catch (e) {
|
|
298
|
+
selectError = { level: 'fatal', message: e.message };
|
|
299
|
+
}
|
|
300
|
+
// Check if CDC is enabled for the table
|
|
301
|
+
let cdcError = null;
|
|
302
|
+
try {
|
|
303
|
+
const isEnabled = await isTableEnabledForCDC({
|
|
304
|
+
connectionManager: connectionManager,
|
|
305
|
+
table: table.name,
|
|
306
|
+
schema: schema
|
|
307
|
+
});
|
|
308
|
+
if (!isEnabled) {
|
|
309
|
+
cdcError = {
|
|
310
|
+
level: 'fatal',
|
|
311
|
+
message: `CDC is not enabled for table ${toQualifiedTableName(schema, table.name)}. Enable CDC with: sys.sp_cdc_enable_table @source_schema = '${schema}', @source_name = '${table.name}', @role_name = NULL, @supports_net_changes = 1`
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
catch (e) {
|
|
316
|
+
cdcError = { level: 'warning', message: `Could not check CDC status: ${e.message}` };
|
|
317
|
+
}
|
|
318
|
+
// TODO check RLS settings for table
|
|
319
|
+
return {
|
|
320
|
+
schema: schema,
|
|
321
|
+
name: table.name,
|
|
322
|
+
pattern: tablePattern.isWildcard ? tablePattern.tablePattern : undefined,
|
|
323
|
+
replication_id: idColumns.map((c) => c.name),
|
|
324
|
+
data_queries: syncData,
|
|
325
|
+
parameter_queries: syncParameters,
|
|
326
|
+
errors: [idColumnsError, selectError, cdcError].filter((error) => error != null)
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
//# sourceMappingURL=mssql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mssql.js","sourceRoot":"","sources":["../../src/utils/mssql.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SourceEntityDescriptor } from '@powersync/service-core';
|
|
2
|
+
import { TablePattern } from '@powersync/service-sync-rules';
|
|
3
|
+
import { MSSQLConnectionManager } from '../replication/MSSQLConnectionManager.js';
|
|
4
|
+
import { MSSQLColumnDescriptor } from '../types/mssql-data-types.js';
|
|
5
|
+
export interface GetColumnsOptions {
|
|
6
|
+
connectionManager: MSSQLConnectionManager;
|
|
7
|
+
schema: string;
|
|
8
|
+
tableName: string;
|
|
9
|
+
}
|
|
10
|
+
export interface GetReplicationIdentityColumnsOptions {
|
|
11
|
+
connectionManager: MSSQLConnectionManager;
|
|
12
|
+
schema: string;
|
|
13
|
+
tableName: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ReplicationIdentityColumnsResult {
|
|
16
|
+
columns: MSSQLColumnDescriptor[];
|
|
17
|
+
identity: 'default' | 'nothing' | 'full' | 'index';
|
|
18
|
+
}
|
|
19
|
+
export declare function getReplicationIdentityColumns(options: GetReplicationIdentityColumnsOptions): Promise<ReplicationIdentityColumnsResult>;
|
|
20
|
+
export type ResolvedTable = Omit<SourceEntityDescriptor, 'replicaIdColumns'>;
|
|
21
|
+
export declare function getTablesFromPattern(connectionManager: MSSQLConnectionManager, tablePattern: TablePattern): Promise<ResolvedTable[]>;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
async function getColumns(options) {
|
|
2
|
+
const { connectionManager, schema, tableName } = options;
|
|
3
|
+
const { recordset: columnResults } = await connectionManager.query(`
|
|
4
|
+
SELECT
|
|
5
|
+
col.name AS [name],
|
|
6
|
+
typ.name AS [type],
|
|
7
|
+
typ.system_type_id AS type_id,
|
|
8
|
+
typ.user_type_id AS user_type_id
|
|
9
|
+
FROM sys.columns AS col
|
|
10
|
+
JOIN sys.tables AS tbl ON tbl.object_id = col.object_id
|
|
11
|
+
JOIN sys.schemas AS sch ON sch.schema_id = tbl.schema_id
|
|
12
|
+
JOIN sys.types AS typ ON typ.user_type_id = col.user_type_id
|
|
13
|
+
WHERE sch.name = '${schema}'
|
|
14
|
+
AND tbl.name = '${tableName}'
|
|
15
|
+
ORDER BY col.column_id;
|
|
16
|
+
`);
|
|
17
|
+
return columnResults.map((row) => {
|
|
18
|
+
return {
|
|
19
|
+
name: row.name,
|
|
20
|
+
type: row.type,
|
|
21
|
+
typeId: row.type_id,
|
|
22
|
+
userTypeId: row.user_type_id
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export async function getReplicationIdentityColumns(options) {
|
|
27
|
+
const { connectionManager, schema, tableName } = options;
|
|
28
|
+
const { recordset: primaryKeyColumns } = await connectionManager.query(`
|
|
29
|
+
SELECT
|
|
30
|
+
col.name AS [name],
|
|
31
|
+
typ.name AS [type],
|
|
32
|
+
typ.system_type_id AS type_id,
|
|
33
|
+
typ.user_type_id AS user_type_id
|
|
34
|
+
FROM sys.tables AS tbl
|
|
35
|
+
JOIN sys.schemas AS sch ON sch.schema_id = tbl.schema_id
|
|
36
|
+
JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id AND idx.is_primary_key = 1
|
|
37
|
+
JOIN sys.index_columns AS idx_col ON idx_col.object_id = idx.object_id AND idx_col.index_id = idx.index_id
|
|
38
|
+
JOIN sys.columns AS col ON col.object_id = idx_col.object_id AND col.column_id = idx_col.column_id
|
|
39
|
+
JOIN sys.types AS typ ON typ.user_type_id = col.user_type_id
|
|
40
|
+
WHERE sch.name = '${schema}'
|
|
41
|
+
AND tbl.name = '${tableName}'
|
|
42
|
+
ORDER BY idx_col.key_ordinal;
|
|
43
|
+
`);
|
|
44
|
+
if (primaryKeyColumns.length > 0) {
|
|
45
|
+
return {
|
|
46
|
+
columns: primaryKeyColumns.map((row) => ({
|
|
47
|
+
name: row.name,
|
|
48
|
+
type: row.type,
|
|
49
|
+
typeId: row.type_id,
|
|
50
|
+
userTypeId: row.user_type_id
|
|
51
|
+
})),
|
|
52
|
+
identity: 'default'
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// No primary key, check if any of the columns have a unique constraint we can use
|
|
56
|
+
const { recordset: uniqueKeyColumns } = await connectionManager.query(`
|
|
57
|
+
SELECT
|
|
58
|
+
col.name AS [name],
|
|
59
|
+
typ.name AS [type],
|
|
60
|
+
typ.system_type_id AS type_id,
|
|
61
|
+
typ.user_type_id AS user_type_id
|
|
62
|
+
FROM sys.tables AS tbl
|
|
63
|
+
JOIN sys.schemas AS sch ON sch.schema_id = tbl.schema_id
|
|
64
|
+
JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id AND idx.is_unique_constraint = 1
|
|
65
|
+
JOIN sys.index_columns AS idx_col ON idx_col.object_id = idx.object_id AND idx_col.index_id = idx.index_id
|
|
66
|
+
JOIN sys.columns AS col ON col.object_id = idx_col.object_id AND col.column_id = idx_col.column_id
|
|
67
|
+
JOIN sys.types AS typ ON typ.user_type_id = col.user_type_id
|
|
68
|
+
WHERE sch.name = '${schema}'
|
|
69
|
+
AND tbl.name = '${tableName}'
|
|
70
|
+
ORDER BY idx_col.key_ordinal;
|
|
71
|
+
`);
|
|
72
|
+
if (uniqueKeyColumns.length > 0) {
|
|
73
|
+
return {
|
|
74
|
+
columns: uniqueKeyColumns.map((row) => ({
|
|
75
|
+
name: row.name,
|
|
76
|
+
type: row.type,
|
|
77
|
+
typeId: row.type_id,
|
|
78
|
+
userTypeId: row.user_type_id
|
|
79
|
+
})),
|
|
80
|
+
identity: 'index'
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const allColumns = await getColumns(options);
|
|
84
|
+
return {
|
|
85
|
+
columns: allColumns,
|
|
86
|
+
identity: 'full'
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export async function getTablesFromPattern(connectionManager, tablePattern) {
|
|
90
|
+
if (tablePattern.isWildcard) {
|
|
91
|
+
const { recordset: tableResults } = await connectionManager.query(`
|
|
92
|
+
SELECT
|
|
93
|
+
tbl.name AS [table],
|
|
94
|
+
sch.name AS [schema],
|
|
95
|
+
tbl.object_id AS object_id
|
|
96
|
+
FROM sys.tables tbl
|
|
97
|
+
JOIN sys.schemas sch ON tbl.schema_id = sch.schema_id
|
|
98
|
+
WHERE sch.name = '${tablePattern.schema}'
|
|
99
|
+
AND tbl.name LIKE '${tablePattern.tablePattern}'
|
|
100
|
+
`);
|
|
101
|
+
return tableResults
|
|
102
|
+
.map((row) => {
|
|
103
|
+
return {
|
|
104
|
+
objectId: row.object_id,
|
|
105
|
+
schema: row.schema,
|
|
106
|
+
name: row.table
|
|
107
|
+
};
|
|
108
|
+
})
|
|
109
|
+
.filter((table) => table.name.startsWith(tablePattern.tablePrefix));
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const { recordset: tableResults } = await connectionManager.query(`
|
|
113
|
+
SELECT
|
|
114
|
+
tbl.name AS [table],
|
|
115
|
+
sch.name AS [schema],
|
|
116
|
+
tbl.object_id AS object_id
|
|
117
|
+
FROM sys.tables tbl
|
|
118
|
+
JOIN sys.schemas sch ON tbl.schema_id = sch.schema_id
|
|
119
|
+
WHERE sch.name = '${tablePattern.schema}'
|
|
120
|
+
AND tbl.name = '${tablePattern.name}'
|
|
121
|
+
`);
|
|
122
|
+
return tableResults.map((row) => {
|
|
123
|
+
return {
|
|
124
|
+
objectId: row.object_id,
|
|
125
|
+
schema: row.schema,
|
|
126
|
+
name: row.table
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@powersync/service-module-mssql",
|
|
3
|
+
"repository": "https://github.com/powersync-ja/powersync-service",
|
|
4
|
+
"types": "dist/index.d.ts",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"license": "FSL-1.1-ALv2",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.js",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./types": {
|
|
19
|
+
"import": "./dist/types/types.js",
|
|
20
|
+
"require": "./dist/types/types.js",
|
|
21
|
+
"default": "./dist/types/types.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"mssql": "^12.1.1",
|
|
26
|
+
"semver": "^7.7.2",
|
|
27
|
+
"ts-codec": "^1.3.0",
|
|
28
|
+
"uri-js": "^4.4.1",
|
|
29
|
+
"uuid": "^11.1.0",
|
|
30
|
+
"@powersync/service-sync-rules": "0.29.7",
|
|
31
|
+
"@powersync/service-jsonbig": "0.17.12",
|
|
32
|
+
"@powersync/lib-services-framework": "0.7.10",
|
|
33
|
+
"@powersync/service-errors": "0.3.5",
|
|
34
|
+
"@powersync/service-core": "1.16.3",
|
|
35
|
+
"@powersync/service-types": "0.13.1"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/mssql": "^9.1.8",
|
|
39
|
+
"@types/semver": "^7.7.1",
|
|
40
|
+
"@types/uuid": "^10.0.0",
|
|
41
|
+
"@powersync/service-module-postgres-storage": "0.10.12",
|
|
42
|
+
"@powersync/service-module-mongodb-storage": "0.12.12",
|
|
43
|
+
"@powersync/service-core-tests": "0.12.12"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsc -b",
|
|
47
|
+
"build:tests": "tsc -b test/tsconfig.json",
|
|
48
|
+
"clean": "rm -rf ./dist && tsc -b --clean",
|
|
49
|
+
"test": "vitest"
|
|
50
|
+
}
|
|
51
|
+
}
|