@voltro/sql-mssql 0.81.0 → 0.82.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 +1520 -6
- package/dist/index.js +95 -82
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,24 +1,35 @@
|
|
|
1
1
|
import { MssqlClient as e } from "@effect/sql-mssql";
|
|
2
2
|
import { TYPES as t } from "tedious";
|
|
3
3
|
import { Config as n, Duration as r, Effect as i, Layer as a, ManagedRuntime as o, Option as s, Redacted as c } from "effect";
|
|
4
|
-
import { CDC_OFFSETS_TABLE as l, DEFAULT_ACQUIRE_TIMEOUT_MS as u, EagerCardinalityError as d, MSSQL_TRANSIENT_NUMBERS as f, _voltroMssqlCdcOffsetsTable as p, attachEagerLoads as m, attributionFields as h, bulkInsertLimitsFor as g, causeBranches as _, chunkRowsForInsert as v, compileEagerJson as y, compileJsonPatch as b, compilePredicate as x, compileRawFragment as S, compileSelect as
|
|
4
|
+
import { CDC_OFFSETS_TABLE as l, DEFAULT_ACQUIRE_TIMEOUT_MS as u, EagerCardinalityError as d, MSSQL_TRANSIENT_NUMBERS as f, _voltroMssqlCdcOffsetsTable as p, attachEagerLoads as m, attributionFields as h, bulkInsertLimitsFor as g, causeBranches as _, chunkRowsForInsert as v, compileEagerJson as y, compileJsonPatch as b, compilePredicate as x, compileRawFragment as S, compileSelect as ee, decodeRowsFromSchema as C, encodeRowForSchema as w, externalChangeEvent as T, hasEagerLoads as te, isTableReactive as E, jsonPatchAssignments as ne, makeEagerFallbackReporter as re, makeTransactionAbortTracker as ie, observeDbOp as D, qualifyTable as ae, quoteIdent as oe, raiseChangeListenerCeiling as O, recordsTable as k, requireTable as se, rowKeyColumns as A, runSavepoint as ce, runStoreTransaction as le, runWriteRecorders as ue, stampGeneratedId as j, stampGeneratedIds as de, upsertUpdatePatch as M, upsertUpdateValues as N, withCapturedAttribution as fe } from "@voltro/database";
|
|
5
5
|
import { EventEmitter as pe } from "node:events";
|
|
6
6
|
import { createLogger as P } from "@voltro/logger";
|
|
7
7
|
import { SqlClient as F, TransactionConnection as I } from "@effect/sql/SqlClient";
|
|
8
|
-
//#region src/
|
|
9
|
-
var L = {
|
|
8
|
+
//#region src/numberParameter.ts
|
|
9
|
+
var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.isSafeInteger(e) ? e >= -2147483648 && e <= 2147483647 ? t.Int : t.BigInt : t.Float, me = {
|
|
10
|
+
...t.Int,
|
|
11
|
+
declaration: (e) => L(e.value).declaration(e),
|
|
12
|
+
generateTypeInfo: (e, t) => L(e.value).generateTypeInfo(e, t),
|
|
13
|
+
generateParameterLength: (e, t) => L(e.value).generateParameterLength(e, t),
|
|
14
|
+
generateParameterData: (e, t) => L(e.value).generateParameterData(e, t),
|
|
15
|
+
validate: (e, t, n) => {
|
|
16
|
+
if (typeof e == "number" && !Number.isFinite(e)) throw TypeError("SQL Server numeric parameters must be finite.");
|
|
17
|
+
return L(e).validate(e, t, n);
|
|
18
|
+
}
|
|
19
|
+
}, R = {
|
|
10
20
|
...e.defaultParameterTypes,
|
|
11
21
|
null: t.NVarChar,
|
|
12
22
|
Date: t.DateTime2,
|
|
13
|
-
string: t.NVarChar
|
|
14
|
-
|
|
23
|
+
string: t.NVarChar,
|
|
24
|
+
number: me
|
|
25
|
+
}, z = (e) => {
|
|
15
26
|
let t = e.acquireTimeoutMs ?? u;
|
|
16
27
|
return t > 0 ? t : void 0;
|
|
17
|
-
},
|
|
18
|
-
let i =
|
|
28
|
+
}, B = (t) => {
|
|
29
|
+
let i = z(t);
|
|
19
30
|
return e.layerConfig({
|
|
20
31
|
server: n.succeed(t.server),
|
|
21
|
-
parameterTypes: n.succeed(
|
|
32
|
+
parameterTypes: n.succeed(R),
|
|
22
33
|
...i === void 0 ? {} : { connectTimeout: n.succeed(r.millis(i)) },
|
|
23
34
|
...t.port === void 0 ? {} : { port: n.succeed(t.port) },
|
|
24
35
|
...t.database === void 0 ? {} : { database: n.succeed(t.database) },
|
|
@@ -28,7 +39,7 @@ var L = {
|
|
|
28
39
|
...t.trustServer === void 0 ? {} : { trustServer: n.succeed(t.trustServer) },
|
|
29
40
|
...t.maxConnections === void 0 ? {} : { maxConnections: n.succeed(t.maxConnections) }
|
|
30
41
|
});
|
|
31
|
-
},
|
|
42
|
+
}, he = (e) => {
|
|
32
43
|
let t = e.get("sslmode");
|
|
33
44
|
if (t !== null) {
|
|
34
45
|
if (t === "require") return !0;
|
|
@@ -43,7 +54,7 @@ var L = {
|
|
|
43
54
|
throw Error(`DB_URL '?${t}=${n}' is not supported by the mssql dialect — use 'true'/'1' or 'false'/'0'.`);
|
|
44
55
|
}
|
|
45
56
|
}
|
|
46
|
-
},
|
|
57
|
+
}, V = (e) => {
|
|
47
58
|
let t = e.acquireTimeoutMs === void 0 ? {} : { acquireTimeoutMs: e.acquireTimeoutMs }, n = (e) => e === void 0 ? {} : {
|
|
48
59
|
encrypt: e,
|
|
49
60
|
...e ? { trustServer: !0 } : {}
|
|
@@ -56,7 +67,7 @@ var L = {
|
|
|
56
67
|
username: decodeURIComponent(r.username || "sa"),
|
|
57
68
|
password: decodeURIComponent(r.password || ""),
|
|
58
69
|
database: r.pathname.replace(/^\//, "") || "master",
|
|
59
|
-
...n(e.ssl ??
|
|
70
|
+
...n(e.ssl ?? he(r.searchParams)),
|
|
60
71
|
...e.maxConnections === void 0 ? {} : { maxConnections: e.maxConnections },
|
|
61
72
|
...t
|
|
62
73
|
};
|
|
@@ -71,7 +82,7 @@ var L = {
|
|
|
71
82
|
...e.maxConnections === void 0 ? {} : { maxConnections: e.maxConnections },
|
|
72
83
|
...t
|
|
73
84
|
};
|
|
74
|
-
},
|
|
85
|
+
}, H = (e) => B(V(e)), ge = f, U = (e) => {
|
|
75
86
|
let t = e;
|
|
76
87
|
for (let e = 0; e < 5 && typeof t == "object" && t; e++) {
|
|
77
88
|
let e = t.number;
|
|
@@ -80,17 +91,17 @@ var L = {
|
|
|
80
91
|
if (typeof n == "string") return n;
|
|
81
92
|
t = t.cause;
|
|
82
93
|
}
|
|
83
|
-
},
|
|
84
|
-
let t =
|
|
85
|
-
return t !== void 0 && he.has(t);
|
|
86
|
-
}), ge = /* @__PURE__ */ new Set(["2601", "2627"]), W = (e) => _(e).some((e) => {
|
|
87
|
-
let t = H(e);
|
|
94
|
+
}, W = (e) => _(e).some((e) => {
|
|
95
|
+
let t = U(e);
|
|
88
96
|
return t !== void 0 && ge.has(t);
|
|
89
|
-
}),
|
|
97
|
+
}), _e = /* @__PURE__ */ new Set(["2601", "2627"]), G = (e) => _(e).some((e) => {
|
|
98
|
+
let t = U(e);
|
|
99
|
+
return t !== void 0 && _e.has(t);
|
|
100
|
+
}), K = (e) => W(e) ? "retry" : "noRetry", ve = {
|
|
90
101
|
I: "insert",
|
|
91
102
|
U: "update",
|
|
92
103
|
D: "delete"
|
|
93
|
-
},
|
|
104
|
+
}, q = (e, t) => e(i.gen(function* () {
|
|
94
105
|
let e = yield* F;
|
|
95
106
|
if (((yield* e`
|
|
96
107
|
SELECT COUNT(*) AS ${e("on")}
|
|
@@ -105,18 +116,18 @@ var L = {
|
|
|
105
116
|
}
|
|
106
117
|
yield* e.unsafe(`IF NOT EXISTS (
|
|
107
118
|
SELECT 1 FROM sys.change_tracking_tables
|
|
108
|
-
WHERE object_id = OBJECT_ID(${
|
|
119
|
+
WHERE object_id = OBJECT_ID(${J(r)})
|
|
109
120
|
)
|
|
110
|
-
ALTER TABLE ${
|
|
121
|
+
ALTER TABLE ${Y(r)} ENABLE CHANGE_TRACKING WITH (TRACK_COLUMNS_UPDATED = OFF)`);
|
|
111
122
|
}
|
|
112
123
|
return n;
|
|
113
|
-
})),
|
|
114
|
-
let t = P({ scope: "voltro:mssql:cdc" }), n = e.pollIntervalMs ?? 500, r = await
|
|
124
|
+
})), J = (e) => `'${e.replace(/'/g, "''")}'`, Y = (e) => `[${e.replace(/\]/g, "]]")}]`, X = async (e) => {
|
|
125
|
+
let t = P({ scope: "voltro:mssql:cdc" }), n = e.pollIntervalMs ?? 500, r = await q(e.run, e.tables), a = /* @__PURE__ */ new Set(), o = async () => (await e.run(i.gen(function* () {
|
|
115
126
|
return yield* (yield* F)`SELECT CONVERT(VARCHAR(40), CHANGE_TRACKING_CURRENT_VERSION()) AS v`;
|
|
116
127
|
})))[0]?.v ?? "0", s = e.startVersion ?? await o(), c = !1, l = null, u = !1, d = (e, t) => BigInt(e) > BigInt(t), f = async (n, r) => {
|
|
117
128
|
let c = await e.run(i.gen(function* () {
|
|
118
|
-
let e = yield* F, t = e.unsafe(
|
|
119
|
-
SELECT CONVERT(VARCHAR(40), CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(${e.unsafe(
|
|
129
|
+
let e = yield* F, t = e.unsafe(Y(n)), i = (yield* e`
|
|
130
|
+
SELECT CONVERT(VARCHAR(40), CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(${e.unsafe(J(n))}))) AS floor`)[0]?.floor, o = r;
|
|
120
131
|
if (i != null && BigInt(r) < BigInt(i)) {
|
|
121
132
|
if (!a.has(n)) return {
|
|
122
133
|
resync: !0,
|
|
@@ -138,22 +149,24 @@ var L = {
|
|
|
138
149
|
return;
|
|
139
150
|
}
|
|
140
151
|
for (let t of c.rows) {
|
|
141
|
-
let r =
|
|
152
|
+
let r = ve[t.__ct_op];
|
|
142
153
|
if (!r) continue;
|
|
143
154
|
let { __ct_op: i, __ct_id: a, ...o } = t;
|
|
144
155
|
if (r === "delete") e.onChange({
|
|
145
156
|
table: n,
|
|
146
157
|
op: "delete",
|
|
147
158
|
old: { id: a },
|
|
148
|
-
new: null
|
|
159
|
+
new: null,
|
|
160
|
+
netChange: !0
|
|
149
161
|
});
|
|
150
162
|
else {
|
|
151
|
-
let t =
|
|
163
|
+
let t = C([o], n, "mssql")[0];
|
|
152
164
|
e.onChange({
|
|
153
165
|
table: n,
|
|
154
166
|
op: r,
|
|
155
167
|
old: null,
|
|
156
|
-
new: t
|
|
168
|
+
new: t,
|
|
169
|
+
netChange: !0
|
|
157
170
|
});
|
|
158
171
|
}
|
|
159
172
|
}
|
|
@@ -163,7 +176,7 @@ var L = {
|
|
|
163
176
|
try {
|
|
164
177
|
if (r.length > 0) {
|
|
165
178
|
let t = r;
|
|
166
|
-
r = await
|
|
179
|
+
r = await q(e.run, t);
|
|
167
180
|
for (let e of t) r.includes(e) || a.add(e);
|
|
168
181
|
}
|
|
169
182
|
let t = await o();
|
|
@@ -194,26 +207,26 @@ var L = {
|
|
|
194
207
|
},
|
|
195
208
|
currentVersion: () => s
|
|
196
209
|
};
|
|
197
|
-
},
|
|
210
|
+
}, Z = P({ scope: "voltro:mssql" }), Q = async (e) => {
|
|
198
211
|
let t = e.changeStrategy ?? "inline", n = t;
|
|
199
|
-
t === "cdc" && !e.cdcConfig && (
|
|
200
|
-
let r = e.tracerLayer ? a.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, i = o.make(r), s = new
|
|
212
|
+
t === "cdc" && !e.cdcConfig && (Z.warn("changeStrategy='cdc' requires cdcConfig (replicaId + includeTables); falling back to 'inline'."), n = "inline");
|
|
213
|
+
let r = e.tracerLayer ? a.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, i = o.make(r), s = new ye(await i.runPromise(F), i, n);
|
|
201
214
|
return n === "cdc" && e.cdcConfig && await s.startCdcConsumer(e.cdcConfig), s;
|
|
202
|
-
},
|
|
215
|
+
}, ye = class e {
|
|
203
216
|
sql;
|
|
204
217
|
runtime;
|
|
205
218
|
changeStrategy;
|
|
206
219
|
namespace;
|
|
207
220
|
emitter;
|
|
208
221
|
inflightTxns = 0;
|
|
209
|
-
reportEagerFallback =
|
|
222
|
+
reportEagerFallback = re(Z);
|
|
210
223
|
cdcHandle = null;
|
|
211
224
|
cdcCheckpointTimer = null;
|
|
212
225
|
cdcPendingVersion = null;
|
|
213
226
|
cdcReplicaId = "";
|
|
214
227
|
cdcStreamName = "default";
|
|
215
228
|
constructor(e, t, n = "inline", r = null, i) {
|
|
216
|
-
this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new pe(),
|
|
229
|
+
this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new pe(), O(this.emitter);
|
|
217
230
|
}
|
|
218
231
|
get inlineEmit() {
|
|
219
232
|
return this.changeStrategy === "inline";
|
|
@@ -222,19 +235,19 @@ var L = {
|
|
|
222
235
|
return t === this.namespace ? this : new e(this.sql, this.runtime, this.changeStrategy, t, this.emitter);
|
|
223
236
|
}
|
|
224
237
|
nsT(e) {
|
|
225
|
-
return
|
|
238
|
+
return ae(this.namespace, e);
|
|
226
239
|
}
|
|
227
240
|
__mssqlReplicationFriend = { runEffect: (e) => this.runtime.runPromise(e) };
|
|
228
241
|
async executeQuery(e, t) {
|
|
229
|
-
let n =
|
|
230
|
-
return
|
|
242
|
+
let n = ee(e, this.sql, this.namespace), r = t ? i.provideService(n, I, t) : n, a = await D("mssql", "select", () => this.runtime.runPromise(r));
|
|
243
|
+
return C(a, e.table, "mssql");
|
|
231
244
|
}
|
|
232
245
|
decodeWritten(e, t) {
|
|
233
|
-
return
|
|
246
|
+
return C([t], e, "mssql")[0] ?? t;
|
|
234
247
|
}
|
|
235
248
|
async executeInsert(e, t, n, r, a) {
|
|
236
249
|
t = j(e, t);
|
|
237
|
-
let o = this.sql, s = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(
|
|
250
|
+
let o = this.sql, s = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(w(t, e)).returning("*")}`, c = n ? i.provideService(s, I, n) : s, l = (await this.runtime.runPromise(c))[0];
|
|
238
251
|
if (!l) throw Error(`MssqlStore.insert: row not returned post-insert in '${e}'`);
|
|
239
252
|
let u = this.decodeWritten(e, l);
|
|
240
253
|
return await this.routeEvent({
|
|
@@ -245,7 +258,7 @@ var L = {
|
|
|
245
258
|
}, r, n, a), u;
|
|
246
259
|
}
|
|
247
260
|
async executeUpdate(e, t, n, r, a, o) {
|
|
248
|
-
let s = this.sql, c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(
|
|
261
|
+
let s = this.sql, c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(w(n, e)).returning("*")} WHERE ${s.and(A(t).map(([e, t]) => s`${s(e)} = ${t}`))}`, l = r ? i.provideService(c, I, r) : c, u = (await this.runtime.runPromise(l))[0];
|
|
249
262
|
if (!u) return null;
|
|
250
263
|
let d = this.decodeWritten(e, u);
|
|
251
264
|
return await this.routeEvent({
|
|
@@ -257,7 +270,7 @@ var L = {
|
|
|
257
270
|
}
|
|
258
271
|
async executeInsertMany(e, t, n, r, a) {
|
|
259
272
|
if (t = de(e, t), t.length === 0) return [];
|
|
260
|
-
let o = this.sql, s = v(t, g("mssql")), c = (t) => o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t.map((t) =>
|
|
273
|
+
let o = this.sql, s = v(t, g("mssql")), c = (t) => o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t.map((t) => w(t, e))).returning("*")}`, l;
|
|
261
274
|
if (s.length === 1) {
|
|
262
275
|
let e = c(s[0]), t = n ? i.provideService(e, I, n) : e;
|
|
263
276
|
l = await this.runtime.runPromise(t);
|
|
@@ -266,7 +279,7 @@ var L = {
|
|
|
266
279
|
for (let t of s) e.push(...await this.runtime.runPromise(i.provideService(c(t), I, n)));
|
|
267
280
|
l = e;
|
|
268
281
|
} else l = await this.runtime.runPromise(o.withTransaction(i.map(i.forEach(s, c, { concurrency: 1 }), (e) => e.flat())));
|
|
269
|
-
let u = t.map((e) => e.id), d =
|
|
282
|
+
let u = t.map((e) => e.id), d = C(l, e, "mssql"), f = new Map(d.map((e) => [e.id, e])), p = u.map((e) => f.get(e)).filter((e) => e !== void 0), m = p.length === l.length ? p : d;
|
|
270
283
|
for (let t of m) await this.routeEvent({
|
|
271
284
|
table: e,
|
|
272
285
|
op: "insert",
|
|
@@ -276,7 +289,7 @@ var L = {
|
|
|
276
289
|
return m;
|
|
277
290
|
}
|
|
278
291
|
async executePatchJson(e, t, n, r, a, o, s, c) {
|
|
279
|
-
let l = this.sql, u =
|
|
292
|
+
let l = this.sql, u = w(ne(t, n, c), e), d = l.csv([b(l, "mssql", n, r), ...Object.entries(u).map(([e, t]) => l`${l(e)} = ${t}`)]), f = l`UPDATE ${l(this.nsT(e))} SET ${d} OUTPUT INSERTED.* WHERE ${l.and(A(t).map(([e, t]) => l`${l(e)} = ${t}`))}`, p = a ? i.provideService(f, I, a) : f, m = (await this.runtime.runPromise(p))[0];
|
|
280
293
|
if (!m) return null;
|
|
281
294
|
let h = this.decodeWritten(e, m);
|
|
282
295
|
return await this.routeEvent({
|
|
@@ -298,7 +311,7 @@ var L = {
|
|
|
298
311
|
}, r, n, a), !0;
|
|
299
312
|
}
|
|
300
313
|
async appendInTxn(e, t, n) {
|
|
301
|
-
let r = this.sql, a = r`INSERT INTO ${r(this.nsT(e))} ${r.insert(
|
|
314
|
+
let r = this.sql, a = r`INSERT INTO ${r(this.nsT(e))} ${r.insert(w(t, e))}`;
|
|
302
315
|
await this.runtime.runPromise(n ? i.provideService(a, I, n) : a);
|
|
303
316
|
}
|
|
304
317
|
async maxInTxn(e, t, n, r) {
|
|
@@ -319,7 +332,7 @@ var L = {
|
|
|
319
332
|
prev: e.old,
|
|
320
333
|
traceId: e.traceId,
|
|
321
334
|
subjectId: e.subjectId
|
|
322
|
-
}),
|
|
335
|
+
}), E(e.table) && (t === null ? this.inlineEmit && this.emitter.emit("change", e) : t.push(e));
|
|
323
336
|
}
|
|
324
337
|
query(e) {
|
|
325
338
|
return this.runWithEager(e, null);
|
|
@@ -329,13 +342,13 @@ var L = {
|
|
|
329
342
|
}
|
|
330
343
|
rawOn(e, t) {
|
|
331
344
|
let n = S(e, this.sql), r = t ? i.provideService(n, I, t) : n;
|
|
332
|
-
return
|
|
345
|
+
return D("mssql", "raw", () => this.runtime.runPromise(r));
|
|
333
346
|
}
|
|
334
347
|
async runWithEager(e, t) {
|
|
335
|
-
if (!
|
|
348
|
+
if (!te(e)) return this.executeQuery(e, t);
|
|
336
349
|
let n = this.namespace === null ? y(e, this.sql, "mssql") : null;
|
|
337
350
|
if (n !== null) try {
|
|
338
|
-
let e = t ? i.provideService(n.fragment, I, t) : n.fragment, r = await
|
|
351
|
+
let e = t ? i.provideService(n.fragment, I, t) : n.fragment, r = await D("mssql", "select", () => this.runtime.runPromise(e));
|
|
339
352
|
return n.decode(r);
|
|
340
353
|
} catch (t) {
|
|
341
354
|
if (t instanceof d) throw t;
|
|
@@ -359,7 +372,7 @@ var L = {
|
|
|
359
372
|
}
|
|
360
373
|
localWrite(e, t, n) {
|
|
361
374
|
let r = (e) => k(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
|
|
362
|
-
return
|
|
375
|
+
return D("mssql", e, () => fe(r));
|
|
363
376
|
}
|
|
364
377
|
async writeWithRecorders(e, t) {
|
|
365
378
|
let n = [], r = this.sql, a = await this.runtime.runPromise(r.withTransaction(i.flatMap(i.serviceOption(I), (r) => s.isNone(r) ? i.fail(/* @__PURE__ */ Error("MssqlStore.write: TransactionConnection missing.")) : i.tryPromise({
|
|
@@ -391,8 +404,8 @@ var L = {
|
|
|
391
404
|
return this.executeDeleteMany(e, t, null, null);
|
|
392
405
|
}
|
|
393
406
|
async executeUpdateMany(e, t, n, r, a, o) {
|
|
394
|
-
let s = this.sql, c = x(n.where, s, this.namespace), l = s`UPDATE ${s(this.nsT(e))} SET ${s.update(
|
|
395
|
-
for (let t of
|
|
407
|
+
let s = this.sql, c = x(n.where, s, this.namespace), l = s`UPDATE ${s(this.nsT(e))} SET ${s.update(w(t, e))} OUTPUT INSERTED.* WHERE ${c}`, u = r ? i.provideService(l, I, r) : l, d = await D("mssql", "update", () => this.runtime.runPromise(u));
|
|
408
|
+
for (let t of C(d, e, "mssql")) await this.routeEvent({
|
|
396
409
|
table: e,
|
|
397
410
|
op: "update",
|
|
398
411
|
old: null,
|
|
@@ -401,8 +414,8 @@ var L = {
|
|
|
401
414
|
return d.length;
|
|
402
415
|
}
|
|
403
416
|
async executeDeleteMany(e, t, n, r, a) {
|
|
404
|
-
let o = this.sql, s = x(t.where, o, this.namespace), c = o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* WHERE ${s}`, l = n ? i.provideService(c, I, n) : c, u = await
|
|
405
|
-
for (let t of
|
|
417
|
+
let o = this.sql, s = x(t.where, o, this.namespace), c = o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* WHERE ${s}`, l = n ? i.provideService(c, I, n) : c, u = await D("mssql", "delete", () => this.runtime.runPromise(l));
|
|
418
|
+
for (let t of C(u, e, "mssql")) await this.routeEvent({
|
|
406
419
|
table: e,
|
|
407
420
|
op: "delete",
|
|
408
421
|
old: t,
|
|
@@ -430,14 +443,14 @@ var L = {
|
|
|
430
443
|
try {
|
|
431
444
|
return await this.executeInsert(e, t, r, i, a);
|
|
432
445
|
} catch (o) {
|
|
433
|
-
if (!
|
|
446
|
+
if (!G(o)) throw o;
|
|
434
447
|
let s = await this.findByConflict(e, t, n.conflictColumns, r);
|
|
435
448
|
if (!s) throw o;
|
|
436
449
|
return await this.executeUpdate(e, s.id, M(t, s, n), r, i, a) ?? s;
|
|
437
450
|
}
|
|
438
451
|
}
|
|
439
452
|
async mergeUpsert(e, t, n, r, a, o) {
|
|
440
|
-
let s = this.sql, c = Object.keys(t), l = Array.isArray(n.update) ? n.update.filter((e) => c.includes(e)) : c.filter((e) => e !== "id" && !n.conflictColumns.includes(e)), u =
|
|
453
|
+
let s = this.sql, c = Object.keys(t), l = Array.isArray(n.update) ? n.update.filter((e) => c.includes(e)) : c.filter((e) => e !== "id" && !n.conflictColumns.includes(e)), u = w(t, e), d = c.map((e) => s`${u[e]}`), f = c.map((e) => s`${s(e)}`), p = n.conflictColumns.map((e) => s`tgt.${s(e)} = src.${s(e)}`), m = c.map((e) => s`${s(e)}`), h = c.map((e) => s`src.${s(e)}`), g = N(n), _ = w(g, e), v = [...l.filter((e) => !Object.hasOwn(g, e)).map((e) => s`tgt.${s(e)} = src.${s(e)}`), ...Object.entries(_).map(([e, t]) => s`tgt.${s(e)} = ${t}`)];
|
|
441
454
|
v.length === 0 && v.push(s`tgt.${s(n.conflictColumns[0])} = src.${s(n.conflictColumns[0])}`);
|
|
442
455
|
let y = s`
|
|
443
456
|
MERGE ${s(this.nsT(e))} WITH (HOLDLOCK) AS tgt
|
|
@@ -447,13 +460,13 @@ var L = {
|
|
|
447
460
|
WHEN NOT MATCHED THEN INSERT (${s.csv(m)}) VALUES (${s.csv(h)})
|
|
448
461
|
OUTPUT $action AS ${s("__action")}, INSERTED.*;`, b = r ? i.provideService(y, I, r) : y, x = (await this.runtime.runPromise(b))[0];
|
|
449
462
|
if (!x) throw Error(`MssqlStore.upsert: MERGE returned no row for '${e}'`);
|
|
450
|
-
let S = x.__action, { __action:
|
|
463
|
+
let S = x.__action, { __action: ee, ...C } = x, T = this.decodeWritten(e, C);
|
|
451
464
|
return await this.routeEvent({
|
|
452
465
|
table: e,
|
|
453
466
|
op: S === "INSERT" ? "insert" : "update",
|
|
454
467
|
old: null,
|
|
455
|
-
new:
|
|
456
|
-
}, a, r, o),
|
|
468
|
+
new: T
|
|
469
|
+
}, a, r, o), T;
|
|
457
470
|
}
|
|
458
471
|
async executeInsertIgnore(e, t, n, r, i, a) {
|
|
459
472
|
t = j(e, t);
|
|
@@ -468,7 +481,7 @@ var L = {
|
|
|
468
481
|
outcome: "inserted"
|
|
469
482
|
};
|
|
470
483
|
} catch (i) {
|
|
471
|
-
if (!
|
|
484
|
+
if (!G(i)) throw i;
|
|
472
485
|
let a = await this.findByConflict(e, t, n.conflictColumns, r);
|
|
473
486
|
if (!a) throw i;
|
|
474
487
|
return {
|
|
@@ -489,9 +502,9 @@ var L = {
|
|
|
489
502
|
if (this.cdcHandle) return;
|
|
490
503
|
this.cdcReplicaId = e.replicaId;
|
|
491
504
|
let t = e.includeTables ?? [];
|
|
492
|
-
t.length === 0 &&
|
|
505
|
+
t.length === 0 && Z.warn("cdc: no reactive tables to tail; Change Tracking reader idle. Set includeTables to enable.");
|
|
493
506
|
let n = await this.readCdcOffset(e.replicaId);
|
|
494
|
-
this.cdcHandle = await
|
|
507
|
+
this.cdcHandle = await X({
|
|
495
508
|
run: this.__mssqlReplicationFriend.runEffect,
|
|
496
509
|
tables: t,
|
|
497
510
|
startVersion: n,
|
|
@@ -499,9 +512,9 @@ var L = {
|
|
|
499
512
|
onVersion: (e) => {
|
|
500
513
|
this.cdcPendingVersion = e;
|
|
501
514
|
},
|
|
502
|
-
onError: (e) =>
|
|
515
|
+
onError: (e) => Z.warn("cdc: consumer error", {}, e),
|
|
503
516
|
onResync: () => {
|
|
504
|
-
|
|
517
|
+
Z.warn("cdc: resynced to current CT version after retention gap — subscriptions self-heal on the next change");
|
|
505
518
|
}
|
|
506
519
|
}), this.cdcCheckpointTimer = setInterval(() => {
|
|
507
520
|
this.flushCdcOffset();
|
|
@@ -512,12 +525,12 @@ var L = {
|
|
|
512
525
|
let t = this.sql, n = (await this.runtime.runPromise(t`
|
|
513
526
|
SELECT TOP 1 ${t("ctVersion")} FROM ${t(l)}
|
|
514
527
|
WHERE ${t("id")} = ${e}`))[0]?.ctVersion;
|
|
515
|
-
return n ? (
|
|
528
|
+
return n ? (Z.info("cdc: resuming from persisted CT version", {
|
|
516
529
|
replicaId: e,
|
|
517
530
|
version: n
|
|
518
531
|
}), n) : null;
|
|
519
532
|
} catch (t) {
|
|
520
|
-
return
|
|
533
|
+
return Z.warn("cdc: no readable offset; starting at current CT version", { replicaId: e }, t), null;
|
|
521
534
|
}
|
|
522
535
|
}
|
|
523
536
|
async flushCdcOffset() {
|
|
@@ -537,7 +550,7 @@ var L = {
|
|
|
537
550
|
update: ["ctVersion", "updatedAt"]
|
|
538
551
|
}, null, null);
|
|
539
552
|
} catch (t) {
|
|
540
|
-
this.cdcPendingVersion = e,
|
|
553
|
+
this.cdcPendingVersion = e, Z.warn("cdc: checkpoint write failed", {}, t);
|
|
541
554
|
}
|
|
542
555
|
}
|
|
543
556
|
}
|
|
@@ -592,7 +605,7 @@ var L = {
|
|
|
592
605
|
}
|
|
593
606
|
async emptyTablesOn(e, t) {
|
|
594
607
|
if (e.length === 0) return;
|
|
595
|
-
let n = this.sql, r = (e) => this.nsT(e), a = (e, t) => n.unsafe(`ALTER TABLE ${
|
|
608
|
+
let n = this.sql, r = (e) => this.nsT(e), a = (e, t) => n.unsafe(`ALTER TABLE ${oe(r(e), "mssql")} ${t ? "WITH CHECK CHECK" : "NOCHECK"} CONSTRAINT ALL`), o = i.acquireUseRelease(i.forEach(e, (e) => a(e, !1), { discard: !0 }), () => i.forEach(e, (e) => n`DELETE FROM ${n(r(e))}`, { discard: !0 }), () => i.orDie(i.ignore(i.forEach(e, (e) => a(e, !0), { discard: !0 })))), s = t === null ? n.withTransaction(o) : i.provideService(o, I, t);
|
|
596
609
|
await this.runtime.runPromise(s);
|
|
597
610
|
}
|
|
598
611
|
async transactional(e) {
|
|
@@ -601,7 +614,7 @@ var L = {
|
|
|
601
614
|
return await le({
|
|
602
615
|
...this.txnSpec("MssqlStore.transactional"),
|
|
603
616
|
work: e,
|
|
604
|
-
makeView: (e, t) => new
|
|
617
|
+
makeView: (e, t) => new be(this, e, t)
|
|
605
618
|
});
|
|
606
619
|
} finally {
|
|
607
620
|
this.inflightTxns--;
|
|
@@ -613,7 +626,7 @@ var L = {
|
|
|
613
626
|
dialect: "mssql",
|
|
614
627
|
withTransaction: (e) => this.sql.withTransaction(e),
|
|
615
628
|
runPromiseExit: (e) => this.runtime.runPromiseExit(e),
|
|
616
|
-
isRetryable:
|
|
629
|
+
isRetryable: W,
|
|
617
630
|
span: {
|
|
618
631
|
name: "store.transactional",
|
|
619
632
|
attributes: {
|
|
@@ -632,7 +645,7 @@ var L = {
|
|
|
632
645
|
return this.changeStrategy === "cdc" ? "fleet" : "local";
|
|
633
646
|
}
|
|
634
647
|
injectExternalChange(e) {
|
|
635
|
-
|
|
648
|
+
E(e.table) && this.emitter.emit("change", T(e));
|
|
636
649
|
}
|
|
637
650
|
run(e) {
|
|
638
651
|
return this.runtime.runPromise(e);
|
|
@@ -645,7 +658,7 @@ var L = {
|
|
|
645
658
|
if (this.inflightTxns > 0) {
|
|
646
659
|
let t = Date.now() + e;
|
|
647
660
|
for (; this.inflightTxns > 0 && Date.now() < t;) await new Promise((e) => setTimeout(e, 25));
|
|
648
|
-
this.inflightTxns > 0 &&
|
|
661
|
+
this.inflightTxns > 0 && Z.warn("close: grace period expired with in-flight transactions", {
|
|
649
662
|
gracePeriodMs: e,
|
|
650
663
|
inflight: this.inflightTxns
|
|
651
664
|
});
|
|
@@ -655,12 +668,12 @@ var L = {
|
|
|
655
668
|
async ping() {
|
|
656
669
|
await this.runtime.runPromise(this.sql`SELECT 1`);
|
|
657
670
|
}
|
|
658
|
-
},
|
|
671
|
+
}, be = class {
|
|
659
672
|
parent;
|
|
660
673
|
txn;
|
|
661
674
|
attr;
|
|
662
675
|
events = [];
|
|
663
|
-
aborts =
|
|
676
|
+
aborts = ie((e) => W(e));
|
|
664
677
|
committed = !1;
|
|
665
678
|
constructor(e, t, n = void 0) {
|
|
666
679
|
this.parent = e, this.txn = t, this.attr = n;
|
|
@@ -735,7 +748,7 @@ var L = {
|
|
|
735
748
|
this.events.length = 0;
|
|
736
749
|
}
|
|
737
750
|
}
|
|
738
|
-
}, $ = (e) => e.__mssqlReplicationFriend ?? null,
|
|
751
|
+
}, $ = (e) => e.__mssqlReplicationFriend ?? null, xe = (e, t) => e === t ? 0 : e < t ? -1 : 1, Se = () => ({
|
|
739
752
|
async capturePrimaryPosition(e) {
|
|
740
753
|
let t = $(e);
|
|
741
754
|
if (t === null) throw Error("mssqlReplicationAdapter: primary is not an MssqlStore (missing __mssqlReplicationFriend).");
|
|
@@ -762,14 +775,14 @@ var L = {
|
|
|
762
775
|
}));
|
|
763
776
|
},
|
|
764
777
|
compare(e, t) {
|
|
765
|
-
return
|
|
778
|
+
return xe(t, e) >= 0 ? "caught-up" : "behind";
|
|
766
779
|
}
|
|
767
|
-
}),
|
|
780
|
+
}), Ce = {
|
|
768
781
|
id: "mssql",
|
|
769
|
-
makeSqlLayer: (e) =>
|
|
770
|
-
makeStore: (e) =>
|
|
782
|
+
makeSqlLayer: (e) => H(e),
|
|
783
|
+
makeStore: (e) => Q(e),
|
|
771
784
|
compileContains: (e, t, n) => n`${e} LIKE ${`%${t.replace(/[\\%_[\]]/g, (e) => `\\${e}`)}%`} ESCAPE '\\'`,
|
|
772
|
-
retryFilter:
|
|
785
|
+
retryFilter: K
|
|
773
786
|
};
|
|
774
787
|
//#endregion
|
|
775
|
-
export { l as CDC_OFFSETS_TABLE, e as MssqlClient, p as _voltroMssqlCdcOffsetsTable,
|
|
788
|
+
export { l as CDC_OFFSETS_TABLE, e as MssqlClient, p as _voltroMssqlCdcOffsetsTable, V as connectionFromConfig, q as ensureChangeTracking, B as makeMssqlSqlLayer, H as makeMssqlSqlLayerFromConfig, Q as makeMssqlStore, Ce as mssqlDialect, Se as mssqlReplicationAdapter, K as mssqlRetryFilter, X as startChangeTrackingCdc };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/sql-mssql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.82.0",
|
|
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.1",
|
|
37
37
|
"@effect/sql-mssql": "^0.54.0",
|
|
38
|
-
"@voltro/database": "0.
|
|
39
|
-
"@voltro/logger": "0.
|
|
38
|
+
"@voltro/database": "0.82.0",
|
|
39
|
+
"@voltro/logger": "0.82.0",
|
|
40
40
|
"tedious": "18.6.2"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|