UNPKG

mssql-change-tracking

Version:
99 lines 4.66 kB
import { writeLog } from "fast-node-logger"; import { ctCurrentVersionQuery } from ".."; import { getTableFullPath } from "../../../helpers/util"; import { ctCurrentVersion } from "../version/change-tracking-current-version"; /** * @returns changes since specific version number * @description This row-set function is used to query for change information. The function queries the data stored in the internal change tracking tables. The function returns a results set that contains the primary keys of rows that have changed together with other change information such as the operation, columns updated and version for the row. */ export async function ctChanges({ pool, sinceVersion, tableName, dbName, schema, safeRun, }) { writeLog(`ctChanges()`, { level: "trace" }); // set default value for flag. let safeRunFlag = true; if (typeof safeRun === "boolean") { safeRunFlag = safeRun; } if (safeRunFlag) { return pool .request() .query(ctChangesSafeQuery({ schema, dbName, tableName, sinceVersion, changeQuery: ctChangesQuery({ sinceVersion, tableName, schema }), })) .then((result) => { if (result.recordset[0].error) { throw new Error(result.recordset[0].error); } else if (Array.isArray(result.recordsets)) { return { currentVersion: result.recordsets[0][0]["current_version"], changes: result.recordsets[1], }; } else { throw new Error("query result should be array."); } }); } else { // do not check for version validity and snapshot isolation const currentVersion = await ctCurrentVersion({ pool, dbName }); const changes = await pool .request() .query(ctChangesQuery({ schema, dbName, tableName, sinceVersion })) .then((result) => result.recordset); return { changes, currentVersion }; } } /** * @reference https://docs.microsoft.com/en-us/sql/relational-databases/system-functions/changetable-transact-sql?view=sql-server-ver15 * @note [required permissions](https://docs.microsoft.com/en-us/sql/relational-databases/track-changes/manage-change-tracking-sql-server?view=sql-server-ver15#security) */ export function ctChangesQuery({ sinceVersion, dbName, schema, tableName, }) { writeLog(`ctChangesQuery()`, { level: "trace" }); const tableFullPath = getTableFullPath({ tableName, schema, dbName }); let query = `SELECT * FROM CHANGETABLE (CHANGES ${tableFullPath}, ${sinceVersion}) AS ct`; if (dbName) { query = `USE [${dbName}]; `.concat(query); } return query; } /** * @steps To obtain data inside a snapshot transaction, perform the following steps: ([Reference](https://docs.microsoft.com/en-us/sql/relational-databases/track-changes/work-with-change-tracking-sql-server?view=sql-server-ver15#using-snapshot-isolation)) * 1. Set the transaction isolation level to snapshot and start a transaction. * 1. Validate the last synchronization version by using CHANGE_TRACKING_MIN_VALID_VERSION(). * 1. Obtain the version to be used the next time by using CHANGE_TRACKING_CURRENT_VERSION(). * 1. Obtain the changes for the table by using CHANGETABLE(CHANGES ...) * 1. Commit the transaction. */ export function ctChangesSafeQuery({ tableName, sinceVersion, schema, dbName, changeQuery, }) { writeLog(`ctChangesSafeQuery()`, { level: "trace" }); const tableFullPath = getTableFullPath({ tableName, schema, dbName }); let query = ` SET TRANSACTION ISOLATION LEVEL SNAPSHOT; BEGIN TRAN -- Verify that version of the previous synchronization is valid. IF (${sinceVersion} >= CHANGE_TRACKING_MIN_VALID_VERSION( OBJECT_ID('${tableFullPath}'))) BEGIN -- Obtain the version to use next time. ${ctCurrentVersionQuery()} -- Obtain changes. ${changeQuery} END ELSE BEGIN -- Handle invalid version & do not enumerate changes -- Client must be reinitialized SELECT 'Version number ${sinceVersion} is not valid. Client must be reinitialized' As error END COMMIT TRAN`; if (dbName) { query = `USE [${dbName}]; `.concat(query); } return query; } //# sourceMappingURL=change-tracking-changes.js.map