@voltro/sql-mssql 0.43.2 → 0.44.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/CHANGELOG.md +50 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +120 -111
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -39,6 +39,56 @@ _Changes staged for the next release accumulate here (rolled up from
|
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
+
## [0.44.1] — 2026-08-19
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- **@voltro/database, @voltro/data-transfer, @voltro/cli** — A refused import row reported `(FiberFailure) SqlError: Failed to execute statement` — our runtime's rendering of a rejection, marker and stack frames and all — instead of the constraint that fired. It names neither a rule, nor a code, nor even which layer refused, and every row refused for the same cause carries it identically.
|
|
47
|
+
|
|
48
|
+
Two defects, and fixing either alone still leaves a reader stuck.
|
|
49
|
+
|
|
50
|
+
**`Cause.squash` elects a branch, and first is a position, not a ranking.** A `Cause` is a tree, and a transaction routinely produces one with more than one leaf: the statement that failed, and whatever the rollback or a finalizer did on the way out. When the first leaf was the bare wrapper, the driver error sitting in the sibling branch was never looked at. Measured: `sequential(bareSqlError, sqlErrorWithDriver)` classified as nothing while the same two branches in the opposite order classified as `unique constraint PRIMARY … [ER_DUP_ENTRY/1062]`. `extractDbCause` flattens failures AND defects now, in Cause order, expanding a nested `FiberFailure` leaf, and elects the branch that names a driver — the others' chains are appended rather than dropped.
|
|
51
|
+
|
|
52
|
+
**A row's reason may never read like a stack trace.** The runtime rendering is stripped before any tier looks at the text, so the failure mode cannot return invisibly. And when no driver detail is reachable at all, the reason now names the CHAIN of wrappers the failure passed through — the difference between "the database refused this row" and "the connection died mid-import" — while the run logs the full rendering of the first few such failures. Never returned over the wire: it carries frames, and on some engines a driver's sentence carries row data.
|
|
53
|
+
|
|
54
|
+
`RowsRefusedError` also gained `byTable`: **complete** per-table counts. `rows` is capped at 20, so per-table counts tallied off the printed list sum to the cap rather than to the failure — and nothing else in the payload offered any.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## [0.44.0] — 2026-08-19
|
|
59
|
+
|
|
60
|
+
### ⚠ BREAKING
|
|
61
|
+
|
|
62
|
+
- **@voltro/data-transfer, @voltro/cli** — `runImport` returns an `ImportOutcome` instead of the bundle's `Manifest`, and `--mode replace` runs as ONE transaction by default.
|
|
63
|
+
|
|
64
|
+
**Why the return type changed.** The summary line counted the rows the BUNDLE carries, not the rows the run wrote. Those differ most exactly where it matters: a bundle directory carries its own resume ledger, so a copied directory imports nothing — correctly, with a warning naming the file to delete — and the run then printed `import complete … rows: 242950` over a target it had not touched. The warning was one line above, which is one line too far for anyone piping the output through `tail -1`. The outcome carries `rowsWritten`, `rowsSkipped` and `fullyResumed`, the CLI reports written-vs-carried, and a fully-skipped run says so on its LAST line.
|
|
65
|
+
|
|
66
|
+
Migration: `runImport(...)` now resolves to `{ manifest, tablesWritten, rowsWritten, tablesSkipped, rowsSkipped, fullyResumed }`. Read `.manifest` where you read the manifest before.
|
|
67
|
+
|
|
68
|
+
**Why replace is atomic now.** The all-or-nothing guarantee was written for the emptying step, and read — reasonably — as covering the run. A replace that died partway through the LOAD left the target emptied of its old rows and holding part of the new ones, measured on a live instance over sixteen minutes. There is no useful state for a replace to stop in, so it is a default rather than a flag you have to know about. It also closes the window that produced that failure: with the tables emptied and the load uncommitted, a concurrent writer in the application waits instead of inserting a row the bundle is about to insert too.
|
|
69
|
+
|
|
70
|
+
`--no-atomic` (CLI) / `atomic: false` (API) opts out. The trade is stated where it bites: every write to those tables waits for the load, and on postgres the bulk `COPY` loader cannot join a transaction it does not own — an atomic run now says that once rather than being quietly slower.
|
|
71
|
+
|
|
72
|
+
Two smaller things from the same report: `--mode replace` against a running instance warns about the empty-target window when it is NOT atomic, and the `--target api` upload reports progress per chunk plus a line explaining that the final request stays open for the whole import — sixteen minutes of silence is indistinguishable from a hang, and one operator killed a run that had finished.
|
|
73
|
+
|
|
74
|
+
**`voltro update` carries you across this** — codemod `0.44.0/01_import-outcome`.
|
|
75
|
+
|
|
76
|
+
### Fixed
|
|
77
|
+
|
|
78
|
+
- **@voltro/sql-mysql, @voltro/sql-postgres, @voltro/sql-sqlite, @voltro/sql-mssql, @voltro/data-transfer** — A write and its write-recorders now succeed or fail together on every SQL dialect, and the data importer's retry is idempotent.
|
|
79
|
+
|
|
80
|
+
A recorder (a versioning trail, an audit log) runs on the caller's connection and is ALLOWED to fail — a recorder that throws must take the write down with it, that is its contract. Outside a caller transaction the two were not one unit: the row's statement committed on its own, and the recorder's INSERT ran afterwards as a second autocommit statement. So a recorder that threw left a COMMITTED row behind a write that reported failure. Measured directly: `insert` throws, the row is in the table, and a second attempt at the same row is `ER_DUP_ENTRY` on PRIMARY.
|
|
81
|
+
|
|
82
|
+
Anything that retries a failed write then meets its own row. The data importer retries by design — it holds a row whose write failed and tries again once the remaining tables have streamed — so a `--mode replace` that had just emptied a table failed on a duplicate key IN that table. From outside, that is the impossible-looking thing: an import that emptied a table and then failed because something was already in it. Reproduced verbatim, including the table name and `[ER_DUP_ENTRY/1062]`, by putting the old retry back.
|
|
83
|
+
|
|
84
|
+
Both ends are closed, and they are independent on purpose:
|
|
85
|
+
|
|
86
|
+
- **The cause.** A table that HAS recorders writes inside a transaction now, so the row and the trail commit together or not at all — on mysql, mariadb, postgres, sqlite and mssql, verified by one suite that asks all five the same question. A table with no recorders — the default — takes the direct path unchanged; `recordsTable` is a Map-size check first, so it costs one comparison. - **The defence.** The importer's retry upserts instead of inserting in `replace` mode. That covers every OTHER way a write can land while reporting failure: a driver timeout on a write the server applied, a connection lost after the commit, a concurrent writer inserting the same key. It is sound precisely because the table was emptied by this same run — there is nothing in it that is not ours.
|
|
87
|
+
|
|
88
|
+
The test that pinned the divergence went red when the fix landed, exactly as its own note said it would, and is inverted with that note kept.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
42
92
|
## [0.43.2] — 2026-08-18
|
|
43
93
|
|
|
44
94
|
### Fixed
|
package/dist/index.d.ts
CHANGED
|
@@ -222,6 +222,13 @@ export declare class MssqlStore implements DataStore {
|
|
|
222
222
|
* stores is what lets the parity test ask the question at all.
|
|
223
223
|
*/
|
|
224
224
|
private localWrite;
|
|
225
|
+
/**
|
|
226
|
+
* A write and its write-recorders, as ONE unit — see `MysqlStore.
|
|
227
|
+
* writeWithRecorders` for the failure this closes: a recorder that throws
|
|
228
|
+
* after the row's statement committed leaves a committed row behind a write
|
|
229
|
+
* that reported failure, and a caller that retries meets its own row.
|
|
230
|
+
*/
|
|
231
|
+
private writeWithRecorders;
|
|
225
232
|
insert(t: string, r: Row): Promise<Readonly<Record<string, unknown>>>;
|
|
226
233
|
insertMany(t: string, rows: ReadonlyArray<Row>): Promise<readonly Readonly<Record<string, unknown>>[]>;
|
|
227
234
|
patchJson(t: string, pk: string, path: string, value: unknown): Promise<Readonly<Record<string, unknown>> | null>;
|
package/dist/index.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
import { MssqlClient as e } from "@effect/sql-mssql";
|
|
2
|
-
import { Config as t, Duration as n, Effect as r, Layer as i, ManagedRuntime as a,
|
|
3
|
-
import { CDC_OFFSETS_TABLE as
|
|
4
|
-
import { EventEmitter as
|
|
5
|
-
import { createLogger as
|
|
6
|
-
import { SqlClient as
|
|
2
|
+
import { Config as t, Duration as n, Effect as r, Layer as i, ManagedRuntime as a, Option as o, Redacted as s } from "effect";
|
|
3
|
+
import { CDC_OFFSETS_TABLE as c, DEFAULT_ACQUIRE_TIMEOUT_MS as l, EagerCardinalityError as u, _voltroMssqlCdcOffsetsTable as d, attachEagerLoads as f, attributionFields as p, bulkInsertLimitsFor as m, chunkRowsForInsert as h, compileEagerJson as g, compilePredicate as _, compileRawFragment as v, compileSelect as y, decodeRowsFromSchema as b, externalChangeEvent as ee, hasEagerLoads as x, isTableReactive as S, makeEagerFallbackReporter as te, observeDbOp as C, qualifyTable as ne, quoteIdent as w, raiseChangeListenerCeiling as T, recordsTable as E, requireTable as D, runStoreTransaction as O, runWriteRecorders as k, stampGeneratedId as A, stampGeneratedIds as j, withCapturedAttribution as re } from "@voltro/database";
|
|
4
|
+
import { EventEmitter as ie } from "node:events";
|
|
5
|
+
import { createLogger as M } from "@voltro/logger";
|
|
6
|
+
import { SqlClient as N, TransactionConnection as P } from "@effect/sql/SqlClient";
|
|
7
7
|
//#region src/sqlLayer.ts
|
|
8
|
-
var
|
|
8
|
+
var ae = {
|
|
9
9
|
...e.defaultParameterTypes,
|
|
10
10
|
null: e.defaultParameterTypes.object
|
|
11
|
-
},
|
|
12
|
-
let t = e.acquireTimeoutMs ??
|
|
11
|
+
}, oe = (e) => {
|
|
12
|
+
let t = e.acquireTimeoutMs ?? l;
|
|
13
13
|
return t > 0 ? t : void 0;
|
|
14
|
-
},
|
|
15
|
-
let i =
|
|
14
|
+
}, F = (r) => {
|
|
15
|
+
let i = oe(r);
|
|
16
16
|
return e.layerConfig({
|
|
17
17
|
server: t.succeed(r.server),
|
|
18
|
-
parameterTypes: t.succeed(
|
|
18
|
+
parameterTypes: t.succeed(ae),
|
|
19
19
|
...i === void 0 ? {} : { connectTimeout: t.succeed(n.millis(i)) },
|
|
20
20
|
...r.port === void 0 ? {} : { port: t.succeed(r.port) },
|
|
21
21
|
...r.database === void 0 ? {} : { database: t.succeed(r.database) },
|
|
22
22
|
...r.username === void 0 ? {} : { username: t.succeed(r.username) },
|
|
23
|
-
...r.password === void 0 ? {} : { password: t.succeed(
|
|
23
|
+
...r.password === void 0 ? {} : { password: t.succeed(s.make(r.password)) },
|
|
24
24
|
...r.encrypt === void 0 ? {} : { encrypt: t.succeed(r.encrypt) },
|
|
25
25
|
...r.trustServer === void 0 ? {} : { trustServer: t.succeed(r.trustServer) },
|
|
26
26
|
...r.maxConnections === void 0 ? {} : { maxConnections: t.succeed(r.maxConnections) }
|
|
27
27
|
});
|
|
28
|
-
},
|
|
28
|
+
}, I = (e) => {
|
|
29
29
|
let t = e.get("sslmode");
|
|
30
30
|
if (t !== null) {
|
|
31
31
|
if (t === "require") return !0;
|
|
@@ -40,7 +40,7 @@ var re = {
|
|
|
40
40
|
throw Error(`DB_URL '?${t}=${n}' is not supported by the mssql dialect — use 'true'/'1' or 'false'/'0'.`);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
},
|
|
43
|
+
}, L = (e) => {
|
|
44
44
|
let t = e.acquireTimeoutMs === void 0 ? {} : { acquireTimeoutMs: e.acquireTimeoutMs }, n = (e) => e === void 0 ? {} : {
|
|
45
45
|
encrypt: e,
|
|
46
46
|
...e ? { trustServer: !0 } : {}
|
|
@@ -53,7 +53,7 @@ var re = {
|
|
|
53
53
|
username: decodeURIComponent(r.username || "sa"),
|
|
54
54
|
password: decodeURIComponent(r.password || ""),
|
|
55
55
|
database: r.pathname.replace(/^\//, "") || "master",
|
|
56
|
-
...n(e.ssl ??
|
|
56
|
+
...n(e.ssl ?? I(r.searchParams)),
|
|
57
57
|
...e.maxConnections === void 0 ? {} : { maxConnections: e.maxConnections },
|
|
58
58
|
...t
|
|
59
59
|
};
|
|
@@ -68,7 +68,7 @@ var re = {
|
|
|
68
68
|
...e.maxConnections === void 0 ? {} : { maxConnections: e.maxConnections },
|
|
69
69
|
...t
|
|
70
70
|
};
|
|
71
|
-
},
|
|
71
|
+
}, R = (e) => F(L(e)), z = /* @__PURE__ */ new Set(["1205"]), B = (e) => {
|
|
72
72
|
let t = e;
|
|
73
73
|
for (let e = 0; e < 5 && typeof t == "object" && t; e++) {
|
|
74
74
|
let e = t.number;
|
|
@@ -77,36 +77,36 @@ var re = {
|
|
|
77
77
|
if (typeof n == "string") return n;
|
|
78
78
|
t = t.cause;
|
|
79
79
|
}
|
|
80
|
-
},
|
|
81
|
-
let t =
|
|
82
|
-
return t !== void 0 &&
|
|
83
|
-
},
|
|
84
|
-
let t =
|
|
85
|
-
return t !== void 0 &&
|
|
86
|
-
},
|
|
80
|
+
}, V = (e) => {
|
|
81
|
+
let t = B(e);
|
|
82
|
+
return t !== void 0 && z.has(t);
|
|
83
|
+
}, H = /* @__PURE__ */ new Set(["2601", "2627"]), U = (e) => {
|
|
84
|
+
let t = B(e);
|
|
85
|
+
return t !== void 0 && H.has(t);
|
|
86
|
+
}, W = (e) => V(e) ? "retry" : "noRetry", G = {
|
|
87
87
|
I: "insert",
|
|
88
88
|
U: "update",
|
|
89
89
|
D: "delete"
|
|
90
|
-
},
|
|
91
|
-
let e = yield*
|
|
90
|
+
}, K = (e, t) => e(r.gen(function* () {
|
|
91
|
+
let e = yield* N;
|
|
92
92
|
if (((yield* e`
|
|
93
93
|
SELECT COUNT(*) AS ${e("on")}
|
|
94
94
|
FROM sys.change_tracking_databases
|
|
95
95
|
WHERE database_id = DB_ID()`)[0]?.on ?? 0) === 0) return yield* r.fail(/* @__PURE__ */ Error("mssql Change Tracking CDC requires CT enabled on the database. Run `ALTER DATABASE <db> SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON)`, or set CDC=0 for inline emit."));
|
|
96
96
|
for (let n of t) yield* e.unsafe(`IF NOT EXISTS (
|
|
97
97
|
SELECT 1 FROM sys.change_tracking_tables
|
|
98
|
-
WHERE object_id = OBJECT_ID(${
|
|
98
|
+
WHERE object_id = OBJECT_ID(${q(n)})
|
|
99
99
|
)
|
|
100
|
-
ALTER TABLE ${
|
|
101
|
-
})).then(() => void 0),
|
|
102
|
-
let t =
|
|
103
|
-
await
|
|
100
|
+
ALTER TABLE ${J(n)} ENABLE CHANGE_TRACKING WITH (TRACK_COLUMNS_UPDATED = OFF)`);
|
|
101
|
+
})).then(() => void 0), q = (e) => `'${e.replace(/'/g, "''")}'`, J = (e) => `[${e.replace(/\]/g, "]]")}]`, Y = async (e) => {
|
|
102
|
+
let t = M({ scope: "voltro:mssql:cdc" }), n = e.pollIntervalMs ?? 500;
|
|
103
|
+
await K(e.run, e.tables);
|
|
104
104
|
let i = async () => (await e.run(r.gen(function* () {
|
|
105
|
-
return yield* (yield*
|
|
105
|
+
return yield* (yield* N)`SELECT CONVERT(VARCHAR(40), CHANGE_TRACKING_CURRENT_VERSION()) AS v`;
|
|
106
106
|
})))[0]?.v ?? "0", a = e.startVersion ?? await i(), o = !1, s = null, c = !1, l = (e, t) => BigInt(e) > BigInt(t), u = async (n, o) => {
|
|
107
107
|
let s = await e.run(r.gen(function* () {
|
|
108
|
-
let e = yield*
|
|
109
|
-
SELECT CONVERT(VARCHAR(40), CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(${e.unsafe(
|
|
108
|
+
let e = yield* N, t = e.unsafe(J(n)), r = (yield* e`
|
|
109
|
+
SELECT CONVERT(VARCHAR(40), CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(${e.unsafe(q(n))}))) AS floor`)[0]?.floor;
|
|
110
110
|
return r != null && BigInt(o) < BigInt(r) ? {
|
|
111
111
|
resync: !0,
|
|
112
112
|
rows: []
|
|
@@ -124,7 +124,7 @@ var re = {
|
|
|
124
124
|
return;
|
|
125
125
|
}
|
|
126
126
|
for (let t of s.rows) {
|
|
127
|
-
let r =
|
|
127
|
+
let r = G[t.__ct_op];
|
|
128
128
|
if (!r) continue;
|
|
129
129
|
let { __ct_op: i, __ct_id: a, ...o } = t;
|
|
130
130
|
if (r === "delete") e.onChange({
|
|
@@ -134,7 +134,7 @@ var re = {
|
|
|
134
134
|
new: null
|
|
135
135
|
});
|
|
136
136
|
else {
|
|
137
|
-
let t =
|
|
137
|
+
let t = b([o], n, "mssql")[0];
|
|
138
138
|
e.onChange({
|
|
139
139
|
table: n,
|
|
140
140
|
op: r,
|
|
@@ -175,26 +175,26 @@ var re = {
|
|
|
175
175
|
},
|
|
176
176
|
currentVersion: () => a
|
|
177
177
|
};
|
|
178
|
-
},
|
|
178
|
+
}, X = M({ scope: "voltro:mssql" }), Z = async (e) => {
|
|
179
179
|
let t = e.changeStrategy ?? "inline", n = t;
|
|
180
|
-
t === "cdc" && !e.cdcConfig && (
|
|
181
|
-
let r = e.tracerLayer ? i.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, o = a.make(r), s = new
|
|
180
|
+
t === "cdc" && !e.cdcConfig && (X.warn("changeStrategy='cdc' requires cdcConfig (replicaId + includeTables); falling back to 'inline'."), n = "inline");
|
|
181
|
+
let r = e.tracerLayer ? i.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, o = a.make(r), s = new se(await o.runPromise(N), o, n);
|
|
182
182
|
return n === "cdc" && e.cdcConfig && await s.startCdcConsumer(e.cdcConfig), s;
|
|
183
|
-
},
|
|
183
|
+
}, se = class e {
|
|
184
184
|
sql;
|
|
185
185
|
runtime;
|
|
186
186
|
changeStrategy;
|
|
187
187
|
namespace;
|
|
188
188
|
emitter;
|
|
189
189
|
inflightTxns = 0;
|
|
190
|
-
reportEagerFallback = te(
|
|
190
|
+
reportEagerFallback = te(X);
|
|
191
191
|
cdcHandle = null;
|
|
192
192
|
cdcCheckpointTimer = null;
|
|
193
193
|
cdcPendingVersion = null;
|
|
194
194
|
cdcReplicaId = "";
|
|
195
195
|
cdcStreamName = "default";
|
|
196
196
|
constructor(e, t, n = "inline", r = null, i) {
|
|
197
|
-
this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new
|
|
197
|
+
this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new ie(), T(this.emitter);
|
|
198
198
|
}
|
|
199
199
|
get inlineEmit() {
|
|
200
200
|
return this.changeStrategy === "inline";
|
|
@@ -203,16 +203,16 @@ var re = {
|
|
|
203
203
|
return t === this.namespace ? this : new e(this.sql, this.runtime, this.changeStrategy, t, this.emitter);
|
|
204
204
|
}
|
|
205
205
|
nsT(e) {
|
|
206
|
-
return
|
|
206
|
+
return ne(this.namespace, e);
|
|
207
207
|
}
|
|
208
208
|
__mssqlReplicationFriend = { runEffect: (e) => this.runtime.runPromise(e) };
|
|
209
209
|
async executeQuery(e, t) {
|
|
210
|
-
let n =
|
|
211
|
-
return
|
|
210
|
+
let n = y(e, this.sql, this.namespace), i = t ? r.provideService(n, P, t) : n, a = await C("mssql", "select", () => this.runtime.runPromise(i));
|
|
211
|
+
return b(a, e.table, "mssql");
|
|
212
212
|
}
|
|
213
213
|
async executeInsert(e, t, n, i, a) {
|
|
214
|
-
t =
|
|
215
|
-
let o = this.sql, s = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t).returning("*")}`, c = n ? r.provideService(s,
|
|
214
|
+
t = A(e, t);
|
|
215
|
+
let o = this.sql, s = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t).returning("*")}`, c = n ? r.provideService(s, P, n) : s, l = (await this.runtime.runPromise(c))[0];
|
|
216
216
|
if (!l) throw Error(`MssqlStore.insert: row not returned post-insert in '${e}'`);
|
|
217
217
|
return await this.routeEvent({
|
|
218
218
|
table: e,
|
|
@@ -222,7 +222,7 @@ var re = {
|
|
|
222
222
|
}, i, n, a), l;
|
|
223
223
|
}
|
|
224
224
|
async executeUpdate(e, t, n, i, a, o) {
|
|
225
|
-
let s = this.sql, c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(n).returning("*")} WHERE ${s("id")} = ${t}`, l = i ? r.provideService(c,
|
|
225
|
+
let s = this.sql, c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(n).returning("*")} WHERE ${s("id")} = ${t}`, l = i ? r.provideService(c, P, i) : c, u = (await this.runtime.runPromise(l))[0];
|
|
226
226
|
return u ? (await this.routeEvent({
|
|
227
227
|
table: e,
|
|
228
228
|
op: "update",
|
|
@@ -231,27 +231,27 @@ var re = {
|
|
|
231
231
|
}, a, i, o), u) : null;
|
|
232
232
|
}
|
|
233
233
|
async executeInsertMany(e, t, n, i, a) {
|
|
234
|
-
if (t =
|
|
235
|
-
let o = this.sql, s =
|
|
234
|
+
if (t = j(e, t), t.length === 0) return [];
|
|
235
|
+
let o = this.sql, s = h(t, m("mssql")), c = (t) => o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t).returning("*")}`, l;
|
|
236
236
|
if (s.length === 1) {
|
|
237
|
-
let e = c(s[0]), t = n ? r.provideService(e,
|
|
237
|
+
let e = c(s[0]), t = n ? r.provideService(e, P, n) : e;
|
|
238
238
|
l = await this.runtime.runPromise(t);
|
|
239
239
|
} else if (n) {
|
|
240
240
|
let e = [];
|
|
241
|
-
for (let t of s) e.push(...await this.runtime.runPromise(r.provideService(c(t),
|
|
241
|
+
for (let t of s) e.push(...await this.runtime.runPromise(r.provideService(c(t), P, n)));
|
|
242
242
|
l = e;
|
|
243
243
|
} else l = await this.runtime.runPromise(o.withTransaction(r.map(r.forEach(s, c, { concurrency: 1 }), (e) => e.flat())));
|
|
244
|
-
let u = t.map((e) => e.id), d = new Map(l.map((e) => [e.id, e])), f = u.map((e) => d.get(e)).filter((e) => e !== void 0),
|
|
245
|
-
for (let t of
|
|
244
|
+
let u = t.map((e) => e.id), d = new Map(l.map((e) => [e.id, e])), f = u.map((e) => d.get(e)).filter((e) => e !== void 0), p = f.length === l.length ? f : [...l];
|
|
245
|
+
for (let t of p) await this.routeEvent({
|
|
246
246
|
table: e,
|
|
247
247
|
op: "insert",
|
|
248
248
|
old: null,
|
|
249
249
|
new: t
|
|
250
250
|
}, i, n, a);
|
|
251
|
-
return
|
|
251
|
+
return p;
|
|
252
252
|
}
|
|
253
253
|
async executePatchJson(e, t, n, i, a, o, s) {
|
|
254
|
-
let c = this.sql, l = n.split("."), u = l[0], d = l.slice(1), f = d.length === 0 ? "$" : `$.${d.join(".")}`, p = JSON.stringify(i ?? null), m = c`UPDATE ${c(this.nsT(e))} SET ${c(u)} = JSON_MODIFY(${c(u)}, ${f}, JSON_QUERY(${p})) OUTPUT INSERTED.* WHERE ${c("id")} = ${t}`, h = a ? r.provideService(m,
|
|
254
|
+
let c = this.sql, l = n.split("."), u = l[0], d = l.slice(1), f = d.length === 0 ? "$" : `$.${d.join(".")}`, p = JSON.stringify(i ?? null), m = c`UPDATE ${c(this.nsT(e))} SET ${c(u)} = JSON_MODIFY(${c(u)}, ${f}, JSON_QUERY(${p})) OUTPUT INSERTED.* WHERE ${c("id")} = ${t}`, h = a ? r.provideService(m, P, a) : m, g = (await this.runtime.runPromise(h))[0];
|
|
255
255
|
return g ? (await this.routeEvent({
|
|
256
256
|
table: e,
|
|
257
257
|
op: "update",
|
|
@@ -260,7 +260,7 @@ var re = {
|
|
|
260
260
|
}, o, a, s), g) : null;
|
|
261
261
|
}
|
|
262
262
|
async executeDelete(e, t, n, i, a) {
|
|
263
|
-
let o = this.sql, s = o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* WHERE ${o("id")} = ${t}`, c = n ? r.provideService(s,
|
|
263
|
+
let o = this.sql, s = o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* WHERE ${o("id")} = ${t}`, c = n ? r.provideService(s, P, n) : s, l = (await this.runtime.runPromise(c))[0];
|
|
264
264
|
return l ? (await this.routeEvent({
|
|
265
265
|
table: e,
|
|
266
266
|
op: "delete",
|
|
@@ -270,17 +270,17 @@ var re = {
|
|
|
270
270
|
}
|
|
271
271
|
async appendInTxn(e, t, n) {
|
|
272
272
|
let i = this.sql, a = i`INSERT INTO ${i(this.nsT(e))} ${i.insert(t)}`;
|
|
273
|
-
await this.runtime.runPromise(n ? r.provideService(a,
|
|
273
|
+
await this.runtime.runPromise(n ? r.provideService(a, P, n) : a);
|
|
274
274
|
}
|
|
275
275
|
async maxInTxn(e, t, n, i) {
|
|
276
|
-
let a = this.sql, o = Object.entries(n).map(([e, t]) => a`${a(e)} = ${t}`), s = a`SELECT MAX(${a(t)}) AS ${a("m")} FROM ${a(this.nsT(e))} WHERE ${a.and(o)}`, c = (await this.runtime.runPromise(i ? r.provideService(s,
|
|
276
|
+
let a = this.sql, o = Object.entries(n).map(([e, t]) => a`${a(e)} = ${t}`), s = a`SELECT MAX(${a(t)}) AS ${a("m")} FROM ${a(this.nsT(e))} WHERE ${a.and(o)}`, c = (await this.runtime.runPromise(i ? r.provideService(s, P, i) : s))[0]?.m;
|
|
277
277
|
return c == null ? null : Number(c);
|
|
278
278
|
}
|
|
279
279
|
async routeEvent(e, t, n = null, r) {
|
|
280
280
|
e = {
|
|
281
|
-
...
|
|
281
|
+
...p(r),
|
|
282
282
|
...e
|
|
283
|
-
}, E(e.table) && await
|
|
283
|
+
}, E(e.table) && await k({
|
|
284
284
|
append: (e, t) => this.appendInTxn(e, t, n),
|
|
285
285
|
maxOf: (e, t, r) => this.maxInTxn(e, t, r, n)
|
|
286
286
|
}, {
|
|
@@ -290,23 +290,23 @@ var re = {
|
|
|
290
290
|
prev: e.old,
|
|
291
291
|
traceId: e.traceId,
|
|
292
292
|
subjectId: e.subjectId
|
|
293
|
-
}),
|
|
293
|
+
}), S(e.table) && (t === null ? this.inlineEmit && this.emitter.emit("change", e) : t.push(e));
|
|
294
294
|
}
|
|
295
295
|
query(e) {
|
|
296
296
|
return this.runWithEager(e, null);
|
|
297
297
|
}
|
|
298
298
|
raw(e, t) {
|
|
299
|
-
let n =
|
|
300
|
-
return
|
|
299
|
+
let n = v(e, this.sql);
|
|
300
|
+
return C("mssql", "raw", () => this.runtime.runPromise(n));
|
|
301
301
|
}
|
|
302
302
|
async runWithEager(e, t) {
|
|
303
|
-
if (!
|
|
304
|
-
let n = this.namespace === null ?
|
|
303
|
+
if (!x(e)) return this.executeQuery(e, t);
|
|
304
|
+
let n = this.namespace === null ? g(e, this.sql, "mssql") : null;
|
|
305
305
|
if (n !== null) try {
|
|
306
|
-
let e = t ? r.provideService(n.fragment,
|
|
306
|
+
let e = t ? r.provideService(n.fragment, P, t) : n.fragment, i = await C("mssql", "select", () => this.runtime.runPromise(e));
|
|
307
307
|
return n.decode(i);
|
|
308
308
|
} catch (t) {
|
|
309
|
-
if (t instanceof
|
|
309
|
+
if (t instanceof u) throw t;
|
|
310
310
|
this.reportEagerFallback({
|
|
311
311
|
dialect: "mssql",
|
|
312
312
|
table: e.table,
|
|
@@ -320,31 +320,40 @@ var re = {
|
|
|
320
320
|
reason: "not-compilable"
|
|
321
321
|
});
|
|
322
322
|
let i = await this.executeQuery(e, t);
|
|
323
|
-
return
|
|
323
|
+
return f(i, e.eager, e.sourceTable ?? D(e.table), (e) => this.executeQuery(e, t));
|
|
324
324
|
}
|
|
325
325
|
getInternalRunWithEager() {
|
|
326
326
|
return this.runWithEager.bind(this);
|
|
327
327
|
}
|
|
328
|
-
localWrite(e, t) {
|
|
329
|
-
|
|
328
|
+
localWrite(e, t, n) {
|
|
329
|
+
let r = (e) => E(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
|
|
330
|
+
return C("mssql", e, () => re(r));
|
|
331
|
+
}
|
|
332
|
+
async writeWithRecorders(e, t) {
|
|
333
|
+
let n = [], i = this.sql, a = await this.runtime.runPromise(i.withTransaction(r.flatMap(r.serviceOption(P), (i) => o.isNone(i) ? r.fail(/* @__PURE__ */ Error("MssqlStore.write: TransactionConnection missing.")) : r.tryPromise({
|
|
334
|
+
try: () => e(t, i.value, n),
|
|
335
|
+
catch: (e) => e
|
|
336
|
+
}))));
|
|
337
|
+
for (let e of n) this.emitChange(e);
|
|
338
|
+
return a;
|
|
330
339
|
}
|
|
331
340
|
insert(e, t) {
|
|
332
|
-
return this.localWrite("insert", (n) => this.executeInsert(e, t,
|
|
341
|
+
return this.localWrite("insert", e, (n, r, i) => this.executeInsert(e, t, r, i, n));
|
|
333
342
|
}
|
|
334
343
|
insertMany(e, t) {
|
|
335
|
-
return this.localWrite("insert", (n) => this.executeInsertMany(e, t,
|
|
344
|
+
return this.localWrite("insert", e, (n, r, i) => this.executeInsertMany(e, t, r, i, n));
|
|
336
345
|
}
|
|
337
346
|
patchJson(e, t, n, r) {
|
|
338
|
-
return this.localWrite("update", (i) => this.executePatchJson(e, t, n, r,
|
|
347
|
+
return this.localWrite("update", e, (i, a, o) => this.executePatchJson(e, t, n, r, a, o, i));
|
|
339
348
|
}
|
|
340
349
|
update(e, t, n) {
|
|
341
|
-
return this.localWrite("update", (r) => this.executeUpdate(e, t, n,
|
|
350
|
+
return this.localWrite("update", e, (r, i, a) => this.executeUpdate(e, t, n, i, a, r));
|
|
342
351
|
}
|
|
343
352
|
delete(e, t) {
|
|
344
|
-
return this.localWrite("delete", (n) => this.executeDelete(e, t,
|
|
353
|
+
return this.localWrite("delete", e, (n, r, i) => this.executeDelete(e, t, r, i, n));
|
|
345
354
|
}
|
|
346
355
|
async updateMany(e, t, n) {
|
|
347
|
-
let r = this.sql, i =
|
|
356
|
+
let r = this.sql, i = _(n.where, r, this.namespace), a = r`UPDATE ${r(this.nsT(e))} SET ${r.update(t)} OUTPUT INSERTED.* WHERE ${i}`, o = await C("mssql", "update", () => this.runtime.runPromise(a));
|
|
348
357
|
for (let t of o) await this.routeEvent({
|
|
349
358
|
table: e,
|
|
350
359
|
op: "update",
|
|
@@ -354,7 +363,7 @@ var re = {
|
|
|
354
363
|
return o.length;
|
|
355
364
|
}
|
|
356
365
|
async deleteMany(e, t) {
|
|
357
|
-
let n = this.sql, r =
|
|
366
|
+
let n = this.sql, r = _(t.where, n, this.namespace), i = n`DELETE FROM ${n(this.nsT(e))} OUTPUT DELETED.* WHERE ${r}`, a = await C("mssql", "delete", () => this.runtime.runPromise(i));
|
|
358
367
|
for (let t of a) await this.routeEvent({
|
|
359
368
|
table: e,
|
|
360
369
|
op: "delete",
|
|
@@ -364,10 +373,10 @@ var re = {
|
|
|
364
373
|
return a.length;
|
|
365
374
|
}
|
|
366
375
|
upsert(e, t, n) {
|
|
367
|
-
return this.localWrite("upsert", (r) => this.executeUpsert(e, t, n,
|
|
376
|
+
return this.localWrite("upsert", e, (r, i, a) => this.executeUpsert(e, t, n, i, a, r));
|
|
368
377
|
}
|
|
369
378
|
insertIgnore(e, t, n) {
|
|
370
|
-
return this.localWrite("upsert", (r) => this.executeInsertIgnore(e, t, n,
|
|
379
|
+
return this.localWrite("upsert", e, (r, i, a) => this.executeInsertIgnore(e, t, n, i, a, r));
|
|
371
380
|
}
|
|
372
381
|
upsertPatch(e, t, n) {
|
|
373
382
|
if (typeof n.update == "function") return n.update(t);
|
|
@@ -390,7 +399,7 @@ var re = {
|
|
|
390
399
|
try {
|
|
391
400
|
return await this.executeInsert(e, t, r, i);
|
|
392
401
|
} catch (a) {
|
|
393
|
-
if (!
|
|
402
|
+
if (!U(a)) throw a;
|
|
394
403
|
let o = await this.findByConflict(e, t, n.conflictColumns, r);
|
|
395
404
|
if (!o) throw a;
|
|
396
405
|
return await this.executeUpdate(e, o.id, this.upsertPatch(t, o, n), r, i) ?? o;
|
|
@@ -403,7 +412,7 @@ var re = {
|
|
|
403
412
|
ON ${o.and(d)}
|
|
404
413
|
WHEN MATCHED THEN UPDATE SET ${o.csv(m)}
|
|
405
414
|
WHEN NOT MATCHED THEN INSERT (${o.csv(f)}) VALUES (${o.csv(p)})
|
|
406
|
-
OUTPUT $action AS ${o("__action")}, INSERTED.*;`, g = i ? r.provideService(h,
|
|
415
|
+
OUTPUT $action AS ${o("__action")}, INSERTED.*;`, g = i ? r.provideService(h, P, i) : h, _ = (await this.runtime.runPromise(g))[0];
|
|
407
416
|
if (!_) throw Error(`MssqlStore.upsert: MERGE returned no row for '${e}'`);
|
|
408
417
|
let v = _.__action, { __action: y, ...b } = _;
|
|
409
418
|
return this.routeEvent({
|
|
@@ -414,13 +423,13 @@ var re = {
|
|
|
414
423
|
}, a), b;
|
|
415
424
|
}
|
|
416
425
|
async executeInsertIgnore(e, t, n, r, i, a) {
|
|
417
|
-
t =
|
|
426
|
+
t = A(e, t);
|
|
418
427
|
let o = await this.findByConflict(e, t, n.conflictColumns, r);
|
|
419
428
|
if (o) return o;
|
|
420
429
|
try {
|
|
421
430
|
return await this.executeInsert(e, t, r, i);
|
|
422
431
|
} catch (i) {
|
|
423
|
-
if (!
|
|
432
|
+
if (!U(i)) throw i;
|
|
424
433
|
let a = await this.findByConflict(e, t, n.conflictColumns, r);
|
|
425
434
|
if (!a) throw i;
|
|
426
435
|
return a;
|
|
@@ -428,7 +437,7 @@ var re = {
|
|
|
428
437
|
}
|
|
429
438
|
async findByConflict(e, t, n, i) {
|
|
430
439
|
if (n.length === 0) return;
|
|
431
|
-
let a = this.sql, o = n.map((e) => a`${a(e)} = ${t[e]}`), s = a`SELECT TOP 1 * FROM ${a(this.nsT(e))} WHERE ${a.and(o)}`, c = i ? r.provideService(s,
|
|
440
|
+
let a = this.sql, o = n.map((e) => a`${a(e)} = ${t[e]}`), s = a`SELECT TOP 1 * FROM ${a(this.nsT(e))} WHERE ${a.and(o)}`, c = i ? r.provideService(s, P, i) : s;
|
|
432
441
|
return (await this.runtime.runPromise(c))[0];
|
|
433
442
|
}
|
|
434
443
|
emitChange(e) {
|
|
@@ -438,9 +447,9 @@ var re = {
|
|
|
438
447
|
if (this.cdcHandle) return;
|
|
439
448
|
this.cdcReplicaId = e.replicaId;
|
|
440
449
|
let t = e.includeTables ?? [];
|
|
441
|
-
t.length === 0 &&
|
|
450
|
+
t.length === 0 && X.warn("cdc: no reactive tables to tail; Change Tracking reader idle. Set includeTables to enable.");
|
|
442
451
|
let n = await this.readCdcOffset(e.replicaId);
|
|
443
|
-
this.cdcHandle = await
|
|
452
|
+
this.cdcHandle = await Y({
|
|
444
453
|
run: this.__mssqlReplicationFriend.runEffect,
|
|
445
454
|
tables: t,
|
|
446
455
|
startVersion: n,
|
|
@@ -448,9 +457,9 @@ var re = {
|
|
|
448
457
|
onVersion: (e) => {
|
|
449
458
|
this.cdcPendingVersion = e;
|
|
450
459
|
},
|
|
451
|
-
onError: (e) =>
|
|
460
|
+
onError: (e) => X.warn("cdc: consumer error", {}, e),
|
|
452
461
|
onResync: () => {
|
|
453
|
-
|
|
462
|
+
X.warn("cdc: resynced to current CT version after retention gap — subscriptions self-heal on the next change");
|
|
454
463
|
}
|
|
455
464
|
}), this.cdcCheckpointTimer = setInterval(() => {
|
|
456
465
|
this.flushCdcOffset();
|
|
@@ -459,14 +468,14 @@ var re = {
|
|
|
459
468
|
async readCdcOffset(e) {
|
|
460
469
|
try {
|
|
461
470
|
let t = this.sql, n = (await this.runtime.runPromise(t`
|
|
462
|
-
SELECT TOP 1 ${t("ctVersion")} FROM ${t(
|
|
471
|
+
SELECT TOP 1 ${t("ctVersion")} FROM ${t(c)}
|
|
463
472
|
WHERE ${t("id")} = ${e}`))[0]?.ctVersion;
|
|
464
|
-
return n ? (
|
|
473
|
+
return n ? (X.info("cdc: resuming from persisted CT version", {
|
|
465
474
|
replicaId: e,
|
|
466
475
|
version: n
|
|
467
476
|
}), n) : null;
|
|
468
477
|
} catch (t) {
|
|
469
|
-
return
|
|
478
|
+
return X.warn("cdc: no readable offset; starting at current CT version", { replicaId: e }, t), null;
|
|
470
479
|
}
|
|
471
480
|
}
|
|
472
481
|
async flushCdcOffset() {
|
|
@@ -475,7 +484,7 @@ var re = {
|
|
|
475
484
|
this.cdcPendingVersion = null;
|
|
476
485
|
try {
|
|
477
486
|
let t = this.cdcReplicaId;
|
|
478
|
-
await this.executeUpsert(
|
|
487
|
+
await this.executeUpsert(c, {
|
|
479
488
|
id: t,
|
|
480
489
|
replicaId: t,
|
|
481
490
|
streamName: this.cdcStreamName,
|
|
@@ -486,7 +495,7 @@ var re = {
|
|
|
486
495
|
update: ["ctVersion", "updatedAt"]
|
|
487
496
|
}, null, null);
|
|
488
497
|
} catch (t) {
|
|
489
|
-
this.cdcPendingVersion = e,
|
|
498
|
+
this.cdcPendingVersion = e, X.warn("cdc: checkpoint write failed", {}, t);
|
|
490
499
|
}
|
|
491
500
|
}
|
|
492
501
|
}
|
|
@@ -535,16 +544,16 @@ var re = {
|
|
|
535
544
|
}
|
|
536
545
|
async emptyTablesOn(e, t) {
|
|
537
546
|
if (e.length === 0) return;
|
|
538
|
-
let n = this.sql, i = (e) => this.nsT(e), a = (e, t) => n.unsafe(`ALTER TABLE ${w(i(e), "mssql")} ${t ? "WITH CHECK CHECK" : "NOCHECK"} CONSTRAINT ALL`), o = r.acquireUseRelease(r.forEach(e, (e) => a(e, !1), { discard: !0 }), () => r.forEach(e, (e) => n`DELETE FROM ${n(i(e))}`, { discard: !0 }), () => r.orDie(r.ignore(r.forEach(e, (e) => a(e, !0), { discard: !0 })))), s = t === null ? n.withTransaction(o) : r.provideService(o,
|
|
547
|
+
let n = this.sql, i = (e) => this.nsT(e), a = (e, t) => n.unsafe(`ALTER TABLE ${w(i(e), "mssql")} ${t ? "WITH CHECK CHECK" : "NOCHECK"} CONSTRAINT ALL`), o = r.acquireUseRelease(r.forEach(e, (e) => a(e, !1), { discard: !0 }), () => r.forEach(e, (e) => n`DELETE FROM ${n(i(e))}`, { discard: !0 }), () => r.orDie(r.ignore(r.forEach(e, (e) => a(e, !0), { discard: !0 })))), s = t === null ? n.withTransaction(o) : r.provideService(o, P, t);
|
|
539
548
|
await this.runtime.runPromise(s);
|
|
540
549
|
}
|
|
541
550
|
async transactional(e) {
|
|
542
551
|
this.inflightTxns++;
|
|
543
552
|
try {
|
|
544
|
-
return await
|
|
553
|
+
return await O({
|
|
545
554
|
...this.txnSpec("MssqlStore.transactional"),
|
|
546
555
|
work: e,
|
|
547
|
-
makeView: (e, t) => new
|
|
556
|
+
makeView: (e, t) => new ce(this, e, t)
|
|
548
557
|
});
|
|
549
558
|
} finally {
|
|
550
559
|
this.inflightTxns--;
|
|
@@ -556,7 +565,7 @@ var re = {
|
|
|
556
565
|
dialect: "mssql",
|
|
557
566
|
withTransaction: (e) => this.sql.withTransaction(e),
|
|
558
567
|
runPromiseExit: (e) => this.runtime.runPromiseExit(e),
|
|
559
|
-
isRetryable:
|
|
568
|
+
isRetryable: V,
|
|
560
569
|
span: {
|
|
561
570
|
name: "store.transactional",
|
|
562
571
|
attributes: {
|
|
@@ -575,7 +584,7 @@ var re = {
|
|
|
575
584
|
return this.changeStrategy === "cdc" ? "fleet" : "local";
|
|
576
585
|
}
|
|
577
586
|
injectExternalChange(e) {
|
|
578
|
-
|
|
587
|
+
S(e.table) && this.emitter.emit("change", ee(e));
|
|
579
588
|
}
|
|
580
589
|
run(e) {
|
|
581
590
|
return this.runtime.runPromise(e);
|
|
@@ -588,7 +597,7 @@ var re = {
|
|
|
588
597
|
if (this.inflightTxns > 0) {
|
|
589
598
|
let t = Date.now() + e;
|
|
590
599
|
for (; this.inflightTxns > 0 && Date.now() < t;) await new Promise((e) => setTimeout(e, 25));
|
|
591
|
-
this.inflightTxns > 0 &&
|
|
600
|
+
this.inflightTxns > 0 && X.warn("close: grace period expired with in-flight transactions", {
|
|
592
601
|
gracePeriodMs: e,
|
|
593
602
|
inflight: this.inflightTxns
|
|
594
603
|
});
|
|
@@ -598,7 +607,7 @@ var re = {
|
|
|
598
607
|
async ping() {
|
|
599
608
|
await this.runtime.runPromise(this.sql`SELECT 1`);
|
|
600
609
|
}
|
|
601
|
-
},
|
|
610
|
+
}, ce = class {
|
|
602
611
|
parent;
|
|
603
612
|
txn;
|
|
604
613
|
attr;
|
|
@@ -674,12 +683,12 @@ var re = {
|
|
|
674
683
|
this.events.length = 0;
|
|
675
684
|
}
|
|
676
685
|
}
|
|
677
|
-
},
|
|
686
|
+
}, Q = (e) => e.__mssqlReplicationFriend ?? null, le = (e, t) => e === t ? 0 : e < t ? -1 : 1, $ = () => ({
|
|
678
687
|
async capturePrimaryPosition(e) {
|
|
679
|
-
let t =
|
|
688
|
+
let t = Q(e);
|
|
680
689
|
if (t === null) throw Error("mssqlReplicationAdapter: primary is not an MssqlStore (missing __mssqlReplicationFriend).");
|
|
681
690
|
return t.runEffect(r.gen(function* () {
|
|
682
|
-
return (yield* (yield*
|
|
691
|
+
return (yield* (yield* N)`
|
|
683
692
|
SELECT CONVERT(VARCHAR(40), end_of_log_lsn) AS lsn
|
|
684
693
|
FROM sys.dm_hadr_database_replica_states
|
|
685
694
|
WHERE database_id = DB_ID()
|
|
@@ -689,10 +698,10 @@ var re = {
|
|
|
689
698
|
}));
|
|
690
699
|
},
|
|
691
700
|
async probeReplicaPosition(e) {
|
|
692
|
-
let t =
|
|
701
|
+
let t = Q(e);
|
|
693
702
|
if (t === null) throw Error("mssqlReplicationAdapter: replica is not an MssqlStore.");
|
|
694
703
|
return t.runEffect(r.gen(function* () {
|
|
695
|
-
return (yield* (yield*
|
|
704
|
+
return (yield* (yield* N)`
|
|
696
705
|
SELECT CONVERT(VARCHAR(40), last_hardened_lsn) AS lsn
|
|
697
706
|
FROM sys.dm_hadr_database_replica_states
|
|
698
707
|
WHERE database_id = DB_ID()
|
|
@@ -701,14 +710,14 @@ var re = {
|
|
|
701
710
|
}));
|
|
702
711
|
},
|
|
703
712
|
compare(e, t) {
|
|
704
|
-
return
|
|
713
|
+
return le(t, e) >= 0 ? "caught-up" : "behind";
|
|
705
714
|
}
|
|
706
|
-
}),
|
|
715
|
+
}), ue = {
|
|
707
716
|
id: "mssql",
|
|
708
|
-
makeSqlLayer: (e) =>
|
|
709
|
-
makeStore: (e) =>
|
|
717
|
+
makeSqlLayer: (e) => R(e),
|
|
718
|
+
makeStore: (e) => Z(e),
|
|
710
719
|
compileContains: (e, t, n) => n`${e} LIKE ${`%${t.replace(/[\\%_[\]]/g, (e) => `\\${e}`)}%`} ESCAPE '\\'`,
|
|
711
|
-
retryFilter:
|
|
720
|
+
retryFilter: W
|
|
712
721
|
};
|
|
713
722
|
//#endregion
|
|
714
|
-
export {
|
|
723
|
+
export { c as CDC_OFFSETS_TABLE, e as MssqlClient, d as _voltroMssqlCdcOffsetsTable, L as connectionFromConfig, K as ensureChangeTracking, F as makeMssqlSqlLayer, R as makeMssqlSqlLayerFromConfig, Z as makeMssqlStore, ue as mssqlDialect, $ as mssqlReplicationAdapter, W as mssqlRetryFilter, Y as startChangeTrackingCdc };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/sql-mssql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.1",
|
|
4
4
|
"description": "SQL Server (mssql) dialect adapter for Voltro's cross-dialect DataStore (OUTPUT-clause returning, OFFSET/FETCH paging, inline reactivity).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@effect/sql": "^0.52.0",
|
|
37
37
|
"@effect/sql-mssql": "^0.53.0",
|
|
38
|
-
"@voltro/database": "0.
|
|
39
|
-
"@voltro/logger": "0.
|
|
38
|
+
"@voltro/database": "0.44.1",
|
|
39
|
+
"@voltro/logger": "0.44.1"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"effect": "^3.22.0"
|