@voltro/sql-mssql 0.83.0 → 0.84.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 +717 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +106 -78
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -289,7 +289,7 @@ export declare class MssqlStore implements DataStore {
|
|
|
289
289
|
* — every value binds as a parameter (no interpolation), `$action`
|
|
290
290
|
* distinguishes the insert vs update branch so the change event is
|
|
291
291
|
* emitted with the right `op`, and `INSERTED.*` returns the post-image
|
|
292
|
-
*
|
|
292
|
+
* from that write. Only reached for the column-list / default
|
|
293
293
|
* `update` form; the function form can't express its patch in a MERGE.
|
|
294
294
|
*/
|
|
295
295
|
private mergeUpsert;
|
package/dist/index.js
CHANGED
|
@@ -1,35 +1,41 @@
|
|
|
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 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
|
|
5
|
-
import { EventEmitter as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
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 se, recordsTable as O, requireTable as ce, rowKeyColumns as k, runSavepoint as le, runStoreTransaction as ue, runWriteRecorders as de, stampGeneratedId as A, stampGeneratedIds as fe, upsertUpdatePatch as j, upsertUpdateValues as M, withCapturedAttribution as pe } from "@voltro/database";
|
|
5
|
+
import { EventEmitter as me } from "node:events";
|
|
6
|
+
import { SqlError as he } from "@effect/sql";
|
|
7
|
+
import { createLogger as N } from "@voltro/logger";
|
|
8
|
+
import { SqlClient as P, TransactionConnection as F } from "@effect/sql/SqlClient";
|
|
8
9
|
//#region src/numberParameter.ts
|
|
9
|
-
var
|
|
10
|
+
var I = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.isSafeInteger(e) ? e >= -2147483648 && e <= 2147483647 ? t.Int : t.BigInt : t.Float, ge = {
|
|
10
11
|
...t.Int,
|
|
11
|
-
declaration: (e) =>
|
|
12
|
-
generateTypeInfo: (e, t) =>
|
|
13
|
-
generateParameterLength: (e, t) =>
|
|
14
|
-
generateParameterData: (e, t) =>
|
|
12
|
+
declaration: (e) => I(e.value).declaration(e),
|
|
13
|
+
generateTypeInfo: (e, t) => I(e.value).generateTypeInfo(e, t),
|
|
14
|
+
generateParameterLength: (e, t) => I(e.value).generateParameterLength(e, t),
|
|
15
|
+
generateParameterData: (e, t) => I(e.value).generateParameterData(e, t),
|
|
15
16
|
validate: (e, t, n) => {
|
|
16
17
|
if (typeof e == "number" && !Number.isFinite(e)) throw TypeError("SQL Server numeric parameters must be finite.");
|
|
17
|
-
return
|
|
18
|
+
return I(e).validate(e, t, n);
|
|
18
19
|
}
|
|
19
|
-
},
|
|
20
|
+
}, _e = {
|
|
21
|
+
...t.VarBinary,
|
|
22
|
+
resolveLength: (e) => Math.max(1, t.VarBinary.resolveLength(e)),
|
|
23
|
+
validate: (e, n, r) => t.VarBinary.validate(e instanceof Uint8Array && !Buffer.isBuffer(e) ? Buffer.from(e.buffer, e.byteOffset, e.byteLength) : e, n, r)
|
|
24
|
+
}, ve = {
|
|
20
25
|
...e.defaultParameterTypes,
|
|
21
26
|
null: t.NVarChar,
|
|
22
27
|
Date: t.DateTime2,
|
|
23
28
|
string: t.NVarChar,
|
|
24
|
-
number:
|
|
25
|
-
|
|
29
|
+
number: ge,
|
|
30
|
+
Uint8Array: _e
|
|
31
|
+
}, ye = (e) => {
|
|
26
32
|
let t = e.acquireTimeoutMs ?? u;
|
|
27
33
|
return t > 0 ? t : void 0;
|
|
28
|
-
},
|
|
29
|
-
let i =
|
|
34
|
+
}, L = (t) => {
|
|
35
|
+
let i = ye(t);
|
|
30
36
|
return e.layerConfig({
|
|
31
37
|
server: n.succeed(t.server),
|
|
32
|
-
parameterTypes: n.succeed(
|
|
38
|
+
parameterTypes: n.succeed(ve),
|
|
33
39
|
...i === void 0 ? {} : { connectTimeout: n.succeed(r.millis(i)) },
|
|
34
40
|
...t.port === void 0 ? {} : { port: n.succeed(t.port) },
|
|
35
41
|
...t.database === void 0 ? {} : { database: n.succeed(t.database) },
|
|
@@ -39,7 +45,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
39
45
|
...t.trustServer === void 0 ? {} : { trustServer: n.succeed(t.trustServer) },
|
|
40
46
|
...t.maxConnections === void 0 ? {} : { maxConnections: n.succeed(t.maxConnections) }
|
|
41
47
|
});
|
|
42
|
-
},
|
|
48
|
+
}, be = (e) => {
|
|
43
49
|
let t = e.get("sslmode");
|
|
44
50
|
if (t !== null) {
|
|
45
51
|
if (t === "require") return !0;
|
|
@@ -54,7 +60,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
54
60
|
throw Error(`DB_URL '?${t}=${n}' is not supported by the mssql dialect — use 'true'/'1' or 'false'/'0'.`);
|
|
55
61
|
}
|
|
56
62
|
}
|
|
57
|
-
},
|
|
63
|
+
}, R = (e) => {
|
|
58
64
|
let t = e.acquireTimeoutMs === void 0 ? {} : { acquireTimeoutMs: e.acquireTimeoutMs }, n = (e) => e === void 0 ? {} : {
|
|
59
65
|
encrypt: e,
|
|
60
66
|
...e ? { trustServer: !0 } : {}
|
|
@@ -67,7 +73,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
67
73
|
username: decodeURIComponent(r.username || "sa"),
|
|
68
74
|
password: decodeURIComponent(r.password || ""),
|
|
69
75
|
database: r.pathname.replace(/^\//, "") || "master",
|
|
70
|
-
...n(e.ssl ??
|
|
76
|
+
...n(e.ssl ?? be(r.searchParams)),
|
|
71
77
|
...e.maxConnections === void 0 ? {} : { maxConnections: e.maxConnections },
|
|
72
78
|
...t
|
|
73
79
|
};
|
|
@@ -82,7 +88,29 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
82
88
|
...e.maxConnections === void 0 ? {} : { maxConnections: e.maxConnections },
|
|
83
89
|
...t
|
|
84
90
|
};
|
|
85
|
-
},
|
|
91
|
+
}, z = (e) => L(R(e)), B = (e, t) => i.gen(function* () {
|
|
92
|
+
let n = yield* e`
|
|
93
|
+
SELECT name, system_type_id FROM sys.columns
|
|
94
|
+
WHERE object_id = OBJECT_ID(${e`${e(t)}`.compile()[0]}, 'U')
|
|
95
|
+
ORDER BY column_id
|
|
96
|
+
`.withoutTransform;
|
|
97
|
+
return n.length === 0 ? yield* new he.SqlError({ message: `Cannot inspect result columns for ${t}` }) : n;
|
|
98
|
+
}), V = (e, t, n) => e.join(", ", !1)(t.map((t) => {
|
|
99
|
+
let r = e.literal(`[${t.name.replaceAll("]", "]]")}]`), i = n ? e`${e(n)}.${r}` : r;
|
|
100
|
+
return t.system_type_id === 106 || t.system_type_id === 108 ? e`CONVERT(varchar(80), ${i}) AS ${r}` : i;
|
|
101
|
+
})), H = (e, t, n, r = !1) => i.uninterruptible(i.gen(function* () {
|
|
102
|
+
let i = e.literal("[#voltro_write_output]"), a = yield* B(e, t), o = e.join(", ", !1)(a.map((t) => {
|
|
103
|
+
let n = e.literal(`[${t.name.replaceAll("]", "]]")}]`);
|
|
104
|
+
return t.system_type_id === 189 ? e`CONVERT(binary(8), ${n}) AS ${n}` : n;
|
|
105
|
+
})), s = V(e, a);
|
|
106
|
+
return yield* e`
|
|
107
|
+
SELECT TOP (0) ${r ? e.literal("CAST(NULL AS nvarchar(10)) AS [__action],") : e.literal("")} source.* INTO ${i}
|
|
108
|
+
FROM (SELECT ${o} FROM ${e(t)} UNION ALL SELECT ${o} FROM ${e(t)}) AS source;
|
|
109
|
+
${n(i)};
|
|
110
|
+
SELECT ${r ? e.literal("[__action],") : e.literal("")}${s} FROM ${i};
|
|
111
|
+
DROP TABLE ${i};
|
|
112
|
+
`;
|
|
113
|
+
})), xe = f, U = (e) => {
|
|
86
114
|
let t = e;
|
|
87
115
|
for (let e = 0; e < 5 && typeof t == "object" && t; e++) {
|
|
88
116
|
let e = t.number;
|
|
@@ -93,16 +121,16 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
93
121
|
}
|
|
94
122
|
}, W = (e) => _(e).some((e) => {
|
|
95
123
|
let t = U(e);
|
|
96
|
-
return t !== void 0 &&
|
|
97
|
-
}),
|
|
124
|
+
return t !== void 0 && xe.has(t);
|
|
125
|
+
}), Se = /* @__PURE__ */ new Set(["2601", "2627"]), G = (e) => _(e).some((e) => {
|
|
98
126
|
let t = U(e);
|
|
99
|
-
return t !== void 0 &&
|
|
100
|
-
}), K = (e) => W(e) ? "retry" : "noRetry",
|
|
127
|
+
return t !== void 0 && Se.has(t);
|
|
128
|
+
}), K = (e) => W(e) ? "retry" : "noRetry", Ce = {
|
|
101
129
|
I: "insert",
|
|
102
130
|
U: "update",
|
|
103
131
|
D: "delete"
|
|
104
132
|
}, q = (e, t) => e(i.gen(function* () {
|
|
105
|
-
let e = yield*
|
|
133
|
+
let e = yield* P;
|
|
106
134
|
if (((yield* e`
|
|
107
135
|
SELECT COUNT(*) AS ${e("on")}
|
|
108
136
|
FROM sys.change_tracking_databases
|
|
@@ -122,11 +150,11 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
122
150
|
}
|
|
123
151
|
return n;
|
|
124
152
|
})), J = (e) => `'${e.replace(/'/g, "''")}'`, Y = (e) => `[${e.replace(/\]/g, "]]")}]`, X = async (e) => {
|
|
125
|
-
let t =
|
|
126
|
-
return yield* (yield*
|
|
153
|
+
let t = N({ 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* () {
|
|
154
|
+
return yield* (yield* P)`SELECT CONVERT(VARCHAR(40), CHANGE_TRACKING_CURRENT_VERSION()) AS v`;
|
|
127
155
|
})))[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) => {
|
|
128
156
|
let c = await e.run(i.gen(function* () {
|
|
129
|
-
let e = yield*
|
|
157
|
+
let e = yield* P, t = e.unsafe(Y(n)), i = (yield* e`
|
|
130
158
|
SELECT CONVERT(VARCHAR(40), CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(${e.unsafe(J(n))}))) AS floor`)[0]?.floor, o = r;
|
|
131
159
|
if (i != null && BigInt(r) < BigInt(i)) {
|
|
132
160
|
if (!a.has(n)) return {
|
|
@@ -138,7 +166,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
138
166
|
return {
|
|
139
167
|
resync: !1,
|
|
140
168
|
rows: yield* e`
|
|
141
|
-
SELECT ct.SYS_CHANGE_OPERATION AS __ct_op, ct.id AS __ct_id, t
|
|
169
|
+
SELECT ct.SYS_CHANGE_OPERATION AS __ct_op, ct.id AS __ct_id, ${V(e, yield* B(e, n), "t")}
|
|
142
170
|
FROM CHANGETABLE(CHANGES ${t}, ${BigInt(o)}) AS ct
|
|
143
171
|
LEFT JOIN ${t} AS t ON t.id = ct.id
|
|
144
172
|
ORDER BY ct.SYS_CHANGE_VERSION`.unprepared
|
|
@@ -149,7 +177,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
149
177
|
return;
|
|
150
178
|
}
|
|
151
179
|
for (let t of c.rows) {
|
|
152
|
-
let r =
|
|
180
|
+
let r = Ce[t.__ct_op];
|
|
153
181
|
if (!r) continue;
|
|
154
182
|
let { __ct_op: i, __ct_id: a, ...o } = t;
|
|
155
183
|
if (r === "delete") e.onChange({
|
|
@@ -188,7 +216,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
188
216
|
s = d(t, s) ? t : s, e.onVersion?.(s);
|
|
189
217
|
}
|
|
190
218
|
} catch (n) {
|
|
191
|
-
t.warn("cdc: poll cycle failed — retrying next tick", {}, n), e.onError?.(n);
|
|
219
|
+
c || (t.warn("cdc: poll cycle failed — retrying next tick", {}, n), e.onError?.(n));
|
|
192
220
|
} finally {
|
|
193
221
|
u = !1, c || (l = setTimeout(() => {
|
|
194
222
|
p();
|
|
@@ -207,12 +235,12 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
207
235
|
},
|
|
208
236
|
currentVersion: () => s
|
|
209
237
|
};
|
|
210
|
-
}, Z =
|
|
238
|
+
}, Z = N({ scope: "voltro:mssql" }), Q = async (e) => {
|
|
211
239
|
let t = e.changeStrategy ?? "inline", n = t;
|
|
212
240
|
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
|
|
241
|
+
let r = e.tracerLayer ? a.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, i = o.make(r), s = new we(await i.runPromise(P), i, n);
|
|
214
242
|
return n === "cdc" && e.cdcConfig && await s.startCdcConsumer(e.cdcConfig), s;
|
|
215
|
-
},
|
|
243
|
+
}, we = class e {
|
|
216
244
|
sql;
|
|
217
245
|
runtime;
|
|
218
246
|
changeStrategy;
|
|
@@ -226,7 +254,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
226
254
|
cdcReplicaId = "";
|
|
227
255
|
cdcStreamName = "default";
|
|
228
256
|
constructor(e, t, n = "inline", r = null, i) {
|
|
229
|
-
this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new
|
|
257
|
+
this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new me(), se(this.emitter);
|
|
230
258
|
}
|
|
231
259
|
get inlineEmit() {
|
|
232
260
|
return this.changeStrategy === "inline";
|
|
@@ -239,15 +267,15 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
239
267
|
}
|
|
240
268
|
__mssqlReplicationFriend = { runEffect: (e) => this.runtime.runPromise(e) };
|
|
241
269
|
async executeQuery(e, t) {
|
|
242
|
-
let n = ee(e, this.sql, this.namespace), r = t ? i.provideService(n,
|
|
270
|
+
let n = ee(e, this.sql, this.namespace), r = t ? i.provideService(n, F, t) : n, a = await D("mssql", "select", () => this.runtime.runPromise(r));
|
|
243
271
|
return C(a, e.table, "mssql");
|
|
244
272
|
}
|
|
245
273
|
decodeWritten(e, t) {
|
|
246
274
|
return C([t], e, "mssql")[0] ?? t;
|
|
247
275
|
}
|
|
248
276
|
async executeInsert(e, t, n, r, a) {
|
|
249
|
-
t =
|
|
250
|
-
let o = this.sql, s = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(w(t, e)).returning(
|
|
277
|
+
t = A(e, t);
|
|
278
|
+
let o = this.sql, s = H(o, this.nsT(e), (n) => o`INSERT INTO ${o(this.nsT(e))} ${o.insert(w(t, e)).returning(o`INSERTED.* INTO ${n}`)}`), c = n ? i.provideService(s, F, n) : s, l = (await this.runtime.runPromise(c))[0];
|
|
251
279
|
if (!l) throw Error(`MssqlStore.insert: row not returned post-insert in '${e}'`);
|
|
252
280
|
let u = this.decodeWritten(e, l);
|
|
253
281
|
return await this.routeEvent({
|
|
@@ -258,7 +286,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
258
286
|
}, r, n, a), u;
|
|
259
287
|
}
|
|
260
288
|
async executeUpdate(e, t, n, r, a, o) {
|
|
261
|
-
let s = this.sql, c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(w(n, e)).returning(
|
|
289
|
+
let s = this.sql, c = H(s, this.nsT(e), (r) => s`UPDATE ${s(this.nsT(e))} SET ${s.update(w(n, e)).returning(s`INSERTED.* INTO ${r}`)} WHERE ${s.and(k(t).map(([e, t]) => s`${s(e)} = ${t}`))}`), l = r ? i.provideService(c, F, r) : c, u = (await this.runtime.runPromise(l))[0];
|
|
262
290
|
if (!u) return null;
|
|
263
291
|
let d = this.decodeWritten(e, u);
|
|
264
292
|
return await this.routeEvent({
|
|
@@ -269,14 +297,14 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
269
297
|
}, a, r, o), d;
|
|
270
298
|
}
|
|
271
299
|
async executeInsertMany(e, t, n, r, a) {
|
|
272
|
-
if (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(
|
|
300
|
+
if (t = fe(e, t), t.length === 0) return [];
|
|
301
|
+
let o = this.sql, s = v(t, g("mssql")), c = (t) => H(o, this.nsT(e), (n) => o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t.map((t) => w(t, e))).returning(o`INSERTED.* INTO ${n}`)}`), l;
|
|
274
302
|
if (s.length === 1) {
|
|
275
|
-
let e = c(s[0]), t = n ? i.provideService(e,
|
|
303
|
+
let e = c(s[0]), t = n ? i.provideService(e, F, n) : e;
|
|
276
304
|
l = await this.runtime.runPromise(t);
|
|
277
305
|
} else if (n) {
|
|
278
306
|
let e = [];
|
|
279
|
-
for (let t of s) e.push(...await this.runtime.runPromise(i.provideService(c(t),
|
|
307
|
+
for (let t of s) e.push(...await this.runtime.runPromise(i.provideService(c(t), F, n)));
|
|
280
308
|
l = e;
|
|
281
309
|
} else l = await this.runtime.runPromise(o.withTransaction(i.map(i.forEach(s, c, { concurrency: 1 }), (e) => e.flat())));
|
|
282
310
|
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;
|
|
@@ -289,7 +317,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
289
317
|
return m;
|
|
290
318
|
}
|
|
291
319
|
async executePatchJson(e, t, n, r, a, o, s, c) {
|
|
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(
|
|
320
|
+
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 = H(l, this.nsT(e), (n) => l`UPDATE ${l(this.nsT(e))} SET ${d} OUTPUT INSERTED.* INTO ${n} WHERE ${l.and(k(t).map(([e, t]) => l`${l(e)} = ${t}`))}`), p = a ? i.provideService(f, F, a) : f, m = (await this.runtime.runPromise(p))[0];
|
|
293
321
|
if (!m) return null;
|
|
294
322
|
let h = this.decodeWritten(e, m);
|
|
295
323
|
return await this.routeEvent({
|
|
@@ -300,7 +328,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
300
328
|
}, o, a, s), h;
|
|
301
329
|
}
|
|
302
330
|
async executeDelete(e, t, n, r, a) {
|
|
303
|
-
let o = this.sql, s = o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* WHERE ${o.and(
|
|
331
|
+
let o = this.sql, s = H(o, this.nsT(e), (n) => o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* INTO ${n} WHERE ${o.and(k(t).map(([e, t]) => o`${o(e)} = ${t}`))}`), c = n ? i.provideService(s, F, n) : s, l = (await this.runtime.runPromise(c))[0];
|
|
304
332
|
if (!l) return !1;
|
|
305
333
|
let u = this.decodeWritten(e, l);
|
|
306
334
|
return await this.routeEvent({
|
|
@@ -312,17 +340,17 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
312
340
|
}
|
|
313
341
|
async appendInTxn(e, t, n) {
|
|
314
342
|
let r = this.sql, a = r`INSERT INTO ${r(this.nsT(e))} ${r.insert(w(t, e))}`;
|
|
315
|
-
await this.runtime.runPromise(n ? i.provideService(a,
|
|
343
|
+
await this.runtime.runPromise(n ? i.provideService(a, F, n) : a);
|
|
316
344
|
}
|
|
317
345
|
async maxInTxn(e, t, n, r) {
|
|
318
|
-
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(r ? i.provideService(s,
|
|
346
|
+
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(r ? i.provideService(s, F, r) : s))[0]?.m;
|
|
319
347
|
return c == null ? null : Number(c);
|
|
320
348
|
}
|
|
321
349
|
async routeEvent(e, t, n = null, r) {
|
|
322
350
|
e = {
|
|
323
351
|
...h(r),
|
|
324
352
|
...e
|
|
325
|
-
},
|
|
353
|
+
}, O(e.table) && await de({
|
|
326
354
|
append: (e, t) => this.appendInTxn(e, t, n),
|
|
327
355
|
maxOf: (e, t, r) => this.maxInTxn(e, t, r, n)
|
|
328
356
|
}, {
|
|
@@ -341,14 +369,14 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
341
369
|
return this.rawOn(e, null);
|
|
342
370
|
}
|
|
343
371
|
rawOn(e, t) {
|
|
344
|
-
let n = S(e, this.sql), r = t ? i.provideService(n,
|
|
372
|
+
let n = S(e, this.sql), r = t ? i.provideService(n, F, t) : n;
|
|
345
373
|
return D("mssql", "raw", () => this.runtime.runPromise(r));
|
|
346
374
|
}
|
|
347
375
|
async runWithEager(e, t) {
|
|
348
376
|
if (!te(e)) return this.executeQuery(e, t);
|
|
349
377
|
let n = this.namespace === null ? y(e, this.sql, "mssql") : null;
|
|
350
378
|
if (n !== null) try {
|
|
351
|
-
let e = t ? i.provideService(n.fragment,
|
|
379
|
+
let e = t ? i.provideService(n.fragment, F, t) : n.fragment, r = await D("mssql", "select", () => this.runtime.runPromise(e));
|
|
352
380
|
return n.decode(r);
|
|
353
381
|
} catch (t) {
|
|
354
382
|
if (t instanceof d) throw t;
|
|
@@ -365,17 +393,17 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
365
393
|
reason: "not-compilable"
|
|
366
394
|
});
|
|
367
395
|
let r = await this.executeQuery(e, t);
|
|
368
|
-
return m(r, e.eager, e.sourceTable ??
|
|
396
|
+
return m(r, e.eager, e.sourceTable ?? ce(e.table), (e) => this.executeQuery(e, t));
|
|
369
397
|
}
|
|
370
398
|
getInternalRunWithEager() {
|
|
371
399
|
return this.runWithEager.bind(this);
|
|
372
400
|
}
|
|
373
401
|
localWrite(e, t, n) {
|
|
374
|
-
let r = (e) =>
|
|
375
|
-
return D("mssql", e, () =>
|
|
402
|
+
let r = (e) => O(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
|
|
403
|
+
return D("mssql", e, () => pe(r));
|
|
376
404
|
}
|
|
377
405
|
async writeWithRecorders(e, t) {
|
|
378
|
-
let n = [], r = this.sql, a = await this.runtime.runPromise(r.withTransaction(i.flatMap(i.serviceOption(
|
|
406
|
+
let n = [], r = this.sql, a = await this.runtime.runPromise(r.withTransaction(i.flatMap(i.serviceOption(F), (r) => s.isNone(r) ? i.fail(/* @__PURE__ */ Error("MssqlStore.write: TransactionConnection missing.")) : i.tryPromise({
|
|
379
407
|
try: () => e(t, r.value, n),
|
|
380
408
|
catch: (e) => e
|
|
381
409
|
}))));
|
|
@@ -404,7 +432,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
404
432
|
return this.executeDeleteMany(e, t, null, null);
|
|
405
433
|
}
|
|
406
434
|
async executeUpdateMany(e, t, n, r, a, o) {
|
|
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}
|
|
435
|
+
let s = this.sql, c = x(n.where, s, this.namespace), l = H(s, this.nsT(e), (n) => s`UPDATE ${s(this.nsT(e))} SET ${s.update(w(t, e))} OUTPUT INSERTED.* INTO ${n} WHERE ${c}`), u = r ? i.provideService(l, F, r) : l, d = await D("mssql", "update", () => this.runtime.runPromise(u));
|
|
408
436
|
for (let t of C(d, e, "mssql")) await this.routeEvent({
|
|
409
437
|
table: e,
|
|
410
438
|
op: "update",
|
|
@@ -414,7 +442,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
414
442
|
return d.length;
|
|
415
443
|
}
|
|
416
444
|
async executeDeleteMany(e, t, n, r, a) {
|
|
417
|
-
let o = this.sql, s = x(t.where, o, this.namespace), c = o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* WHERE ${s}
|
|
445
|
+
let o = this.sql, s = x(t.where, o, this.namespace), c = H(o, this.nsT(e), (t) => o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* INTO ${t} WHERE ${s}`), l = n ? i.provideService(c, F, n) : c, u = await D("mssql", "delete", () => this.runtime.runPromise(l));
|
|
418
446
|
for (let t of C(u, e, "mssql")) await this.routeEvent({
|
|
419
447
|
table: e,
|
|
420
448
|
op: "delete",
|
|
@@ -433,32 +461,32 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
433
461
|
return this.localWrite("upsert", e, (r, i, a) => this.executeInsertIgnore(e, t, n, i, a, r));
|
|
434
462
|
}
|
|
435
463
|
async executeUpsert(e, t, n, r, i, a) {
|
|
436
|
-
if (
|
|
464
|
+
if (M(n), t = A(e, t), typeof n.update != "function" && n.conflictColumns.length > 0) return this.mergeUpsert(e, t, {
|
|
437
465
|
conflictColumns: n.conflictColumns,
|
|
438
466
|
...n.update === void 0 ? {} : { update: n.update },
|
|
439
467
|
...n.updateValues === void 0 ? {} : { updateValues: n.updateValues }
|
|
440
468
|
}, r, i, a);
|
|
441
469
|
let o = await this.findByConflict(e, t, n.conflictColumns, r);
|
|
442
|
-
if (o) return await this.executeUpdate(e,
|
|
470
|
+
if (o) return await this.executeUpdate(e, Object.fromEntries(n.conflictColumns.map((e) => [e, o[e]])), j(t, o, n), r, i, a) ?? o;
|
|
443
471
|
try {
|
|
444
472
|
return await this.executeInsert(e, t, r, i, a);
|
|
445
473
|
} catch (o) {
|
|
446
474
|
if (!G(o)) throw o;
|
|
447
475
|
let s = await this.findByConflict(e, t, n.conflictColumns, r);
|
|
448
476
|
if (!s) throw o;
|
|
449
|
-
return await this.executeUpdate(e,
|
|
477
|
+
return await this.executeUpdate(e, Object.fromEntries(n.conflictColumns.map((e) => [e, s[e]])), j(t, s, n), r, i, a) ?? s;
|
|
450
478
|
}
|
|
451
479
|
}
|
|
452
480
|
async mergeUpsert(e, t, n, r, a, o) {
|
|
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 =
|
|
481
|
+
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 = M(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}`)];
|
|
454
482
|
v.length === 0 && v.push(s`tgt.${s(n.conflictColumns[0])} = src.${s(n.conflictColumns[0])}`);
|
|
455
|
-
let y = s`
|
|
483
|
+
let y = H(s, this.nsT(e), (t) => s`
|
|
456
484
|
MERGE ${s(this.nsT(e))} WITH (HOLDLOCK) AS tgt
|
|
457
485
|
USING (VALUES (${s.csv(d)})) AS src (${s.csv(f)})
|
|
458
486
|
ON ${s.and(p)}
|
|
459
487
|
WHEN MATCHED THEN UPDATE SET ${s.csv(v)}
|
|
460
488
|
WHEN NOT MATCHED THEN INSERT (${s.csv(m)}) VALUES (${s.csv(h)})
|
|
461
|
-
OUTPUT $action AS ${s("__action")}, INSERTED
|
|
489
|
+
OUTPUT $action AS ${s("__action")}, INSERTED.* INTO ${t};`, !0), b = r ? i.provideService(y, F, r) : y, x = (await this.runtime.runPromise(b))[0];
|
|
462
490
|
if (!x) throw Error(`MssqlStore.upsert: MERGE returned no row for '${e}'`);
|
|
463
491
|
let S = x.__action, { __action: ee, ...C } = x, T = this.decodeWritten(e, C);
|
|
464
492
|
return await this.routeEvent({
|
|
@@ -469,7 +497,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
469
497
|
}, a, r, o), T;
|
|
470
498
|
}
|
|
471
499
|
async executeInsertIgnore(e, t, n, r, i, a) {
|
|
472
|
-
t =
|
|
500
|
+
t = A(e, t);
|
|
473
501
|
let o = await this.findByConflict(e, t, n.conflictColumns, r);
|
|
474
502
|
if (o) return {
|
|
475
503
|
row: o,
|
|
@@ -492,7 +520,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
492
520
|
}
|
|
493
521
|
async findByConflict(e, t, n, r) {
|
|
494
522
|
if (n.length === 0) return;
|
|
495
|
-
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 = r ? i.provideService(s,
|
|
523
|
+
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 = r ? i.provideService(s, F, r) : s, l = (await this.runtime.runPromise(c))[0];
|
|
496
524
|
return l ? this.decodeWritten(e, l) : void 0;
|
|
497
525
|
}
|
|
498
526
|
emitChange(e) {
|
|
@@ -605,16 +633,16 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
605
633
|
}
|
|
606
634
|
async emptyTablesOn(e, t) {
|
|
607
635
|
if (e.length === 0) return;
|
|
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,
|
|
636
|
+
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, F, t);
|
|
609
637
|
await this.runtime.runPromise(s);
|
|
610
638
|
}
|
|
611
639
|
async transactional(e) {
|
|
612
640
|
this.inflightTxns++;
|
|
613
641
|
try {
|
|
614
|
-
return await
|
|
642
|
+
return await ue({
|
|
615
643
|
...this.txnSpec("MssqlStore.transactional"),
|
|
616
644
|
work: e,
|
|
617
|
-
makeView: (e, t) => new
|
|
645
|
+
makeView: (e, t) => new Te(this, e, t)
|
|
618
646
|
});
|
|
619
647
|
} finally {
|
|
620
648
|
this.inflightTxns--;
|
|
@@ -668,7 +696,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
668
696
|
async ping() {
|
|
669
697
|
await this.runtime.runPromise(this.sql`SELECT 1`);
|
|
670
698
|
}
|
|
671
|
-
},
|
|
699
|
+
}, Te = class {
|
|
672
700
|
parent;
|
|
673
701
|
txn;
|
|
674
702
|
attr;
|
|
@@ -679,16 +707,16 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
679
707
|
this.parent = e, this.txn = t, this.attr = n;
|
|
680
708
|
}
|
|
681
709
|
savepoint(e) {
|
|
682
|
-
return
|
|
710
|
+
return le({
|
|
683
711
|
tracker: this.aborts,
|
|
684
712
|
name: `voltro_sp_${++this.savepointCounter}`,
|
|
685
713
|
spelling: "mssql",
|
|
686
|
-
exec: (e) => this.parent.run(i.provideService(
|
|
714
|
+
exec: (e) => this.parent.run(i.provideService(P.pipe(i.flatMap((t) => t.unsafe(e))), F, this.txn))
|
|
687
715
|
}, e);
|
|
688
716
|
}
|
|
689
717
|
savepointCounter = 0;
|
|
690
718
|
run(e) {
|
|
691
|
-
return this.aborts.track(() => this.parent.run(i.provideService(e,
|
|
719
|
+
return this.aborts.track(() => this.parent.run(i.provideService(e, F, this.txn)));
|
|
692
720
|
}
|
|
693
721
|
abortedBy() {
|
|
694
722
|
return this.aborts.abortedBy();
|
|
@@ -748,12 +776,12 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
748
776
|
this.events.length = 0;
|
|
749
777
|
}
|
|
750
778
|
}
|
|
751
|
-
}, $ = (e) => e.__mssqlReplicationFriend ?? null,
|
|
779
|
+
}, $ = (e) => e.__mssqlReplicationFriend ?? null, Ee = (e, t) => e === t ? 0 : e < t ? -1 : 1, De = () => ({
|
|
752
780
|
async capturePrimaryPosition(e) {
|
|
753
781
|
let t = $(e);
|
|
754
782
|
if (t === null) throw Error("mssqlReplicationAdapter: primary is not an MssqlStore (missing __mssqlReplicationFriend).");
|
|
755
783
|
return t.runEffect(i.gen(function* () {
|
|
756
|
-
return (yield* (yield*
|
|
784
|
+
return (yield* (yield* P)`
|
|
757
785
|
SELECT CONVERT(VARCHAR(40), end_of_log_lsn) AS lsn
|
|
758
786
|
FROM sys.dm_hadr_database_replica_states
|
|
759
787
|
WHERE database_id = DB_ID()
|
|
@@ -766,7 +794,7 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
766
794
|
let t = $(e);
|
|
767
795
|
if (t === null) throw Error("mssqlReplicationAdapter: replica is not an MssqlStore.");
|
|
768
796
|
return t.runEffect(i.gen(function* () {
|
|
769
|
-
return (yield* (yield*
|
|
797
|
+
return (yield* (yield* P)`
|
|
770
798
|
SELECT CONVERT(VARCHAR(40), last_hardened_lsn) AS lsn
|
|
771
799
|
FROM sys.dm_hadr_database_replica_states
|
|
772
800
|
WHERE database_id = DB_ID()
|
|
@@ -775,14 +803,14 @@ var L = (e) => typeof e == "bigint" ? t.BigInt : typeof e == "number" && Number.
|
|
|
775
803
|
}));
|
|
776
804
|
},
|
|
777
805
|
compare(e, t) {
|
|
778
|
-
return
|
|
806
|
+
return Ee(t, e) >= 0 ? "caught-up" : "behind";
|
|
779
807
|
}
|
|
780
|
-
}),
|
|
808
|
+
}), Oe = {
|
|
781
809
|
id: "mssql",
|
|
782
|
-
makeSqlLayer: (e) =>
|
|
810
|
+
makeSqlLayer: (e) => z(e),
|
|
783
811
|
makeStore: (e) => Q(e),
|
|
784
812
|
compileContains: (e, t, n) => n`${e} LIKE ${`%${t.replace(/[\\%_[\]]/g, (e) => `\\${e}`)}%`} ESCAPE '\\'`,
|
|
785
813
|
retryFilter: K
|
|
786
814
|
};
|
|
787
815
|
//#endregion
|
|
788
|
-
export { l as CDC_OFFSETS_TABLE, e as MssqlClient, p as _voltroMssqlCdcOffsetsTable,
|
|
816
|
+
export { l as CDC_OFFSETS_TABLE, e as MssqlClient, p as _voltroMssqlCdcOffsetsTable, R as connectionFromConfig, q as ensureChangeTracking, L as makeMssqlSqlLayer, z as makeMssqlSqlLayerFromConfig, Q as makeMssqlStore, Oe as mssqlDialect, De 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.84.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.84.0",
|
|
39
|
+
"@voltro/logger": "0.84.0",
|
|
40
40
|
"tedious": "18.6.2"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|