@voltro/sql-mssql 0.86.0 → 0.87.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 +5321 -0
- package/THIRD-PARTY-NOTICES.md +2 -226
- package/dist/index.d.ts +9 -1
- package/dist/store.js +100 -77
- package/package.json +3 -3
package/dist/store.js
CHANGED
|
@@ -3,31 +3,31 @@ import { isDuplicateKeyMssqlFailure as t, isRetryableMssqlFailure as n } from ".
|
|
|
3
3
|
import { startChangeTrackingCdc as r } from "./changeTrackingCdc.js";
|
|
4
4
|
import { CDC_OFFSETS_TABLE as i } from "./cdcOffsetsTable.js";
|
|
5
5
|
import { Effect as a, Layer as o, ManagedRuntime as s, Option as c } from "effect";
|
|
6
|
-
import { EagerCardinalityError as l, attachEagerLoads as u, attributionFields as d, bulkInsertLimitsFor as f, chunkRowsForInsert as p, compileEagerJson as m, compileJsonPatch as h, compilePredicate as g, compileRawFragment as _, compileSelect as v, decodeRowsFromSchema as y,
|
|
7
|
-
import { EventEmitter as
|
|
8
|
-
import { createLogger as
|
|
9
|
-
import { SqlClient as
|
|
6
|
+
import { EagerCardinalityError as l, attachEagerLoads as u, attributionFields as d, bulkInsertLimitsFor as f, chunkRowsForInsert as p, compileEagerJson as m, compileJsonPatch as h, compilePredicate as g, compileRawFragment as _, compileSelect as v, decodeRowsFromSchema as y, decodeSelectRows as b, emitCommittedChanges as x, encodeRowForSchema as S, externalChangeEvent as C, hasEagerLoads as w, isTableReactive as T, jsonPatchAssignments as E, makeEagerFallbackReporter as D, makeTransactionAbortTracker as O, observeDbOp as k, onTransaction as A, qualifyTable as j, quoteIdent as M, raiseChangeListenerCeiling as N, recordsTable as P, requireTable as F, rowKeyColumns as I, runSavepoint as L, runStoreTransaction as R, runWriteRecorders as z, stampGeneratedId as B, stampGeneratedIds as V, upsertUpdatePatch as H, upsertUpdateValues as U, withCapturedAttribution as W, writeImagesObserved as G } from "@voltro/database";
|
|
7
|
+
import { EventEmitter as K } from "node:events";
|
|
8
|
+
import { createLogger as q } from "@voltro/logger";
|
|
9
|
+
import { SqlClient as J } from "effect/sql/SqlClient";
|
|
10
10
|
//#region src/store.ts
|
|
11
|
-
var
|
|
11
|
+
var Y = q({ scope: "voltro:mssql" }), X = async (e) => {
|
|
12
12
|
let t = e.changeStrategy ?? "inline", n = t;
|
|
13
|
-
t === "cdc" && !e.cdcConfig && (
|
|
14
|
-
let r = e.tracerLayer ? o.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, i = s.make(r), a = new
|
|
13
|
+
t === "cdc" && !e.cdcConfig && (Y.warn("changeStrategy='cdc' requires cdcConfig (replicaId + includeTables); falling back to 'inline'."), n = "inline");
|
|
14
|
+
let r = e.tracerLayer ? o.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, i = s.make(r), a = new Z(await i.runPromise(J), i, n);
|
|
15
15
|
return n === "cdc" && e.cdcConfig && await a.startCdcConsumer(e.cdcConfig), a;
|
|
16
|
-
},
|
|
16
|
+
}, Z = class o {
|
|
17
17
|
sql;
|
|
18
18
|
runtime;
|
|
19
19
|
changeStrategy;
|
|
20
20
|
namespace;
|
|
21
21
|
emitter;
|
|
22
22
|
inflightTxns = 0;
|
|
23
|
-
reportEagerFallback =
|
|
23
|
+
reportEagerFallback = D(Y);
|
|
24
24
|
cdcHandle = null;
|
|
25
25
|
cdcCheckpointTimer = null;
|
|
26
26
|
cdcPendingVersion = null;
|
|
27
27
|
cdcReplicaId = "";
|
|
28
28
|
cdcStreamName = "default";
|
|
29
29
|
constructor(e, t, n = "inline", r = null, i) {
|
|
30
|
-
this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new
|
|
30
|
+
this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new K(), N(this.emitter);
|
|
31
31
|
}
|
|
32
32
|
get inlineEmit() {
|
|
33
33
|
return this.changeStrategy === "inline";
|
|
@@ -36,19 +36,19 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
36
36
|
return e === this.namespace ? this : new o(this.sql, this.runtime, this.changeStrategy, e, this.emitter);
|
|
37
37
|
}
|
|
38
38
|
nsT(e) {
|
|
39
|
-
return
|
|
39
|
+
return j(this.namespace, e);
|
|
40
40
|
}
|
|
41
41
|
__mssqlReplicationFriend = { runEffect: (e) => this.runtime.runPromise(e) };
|
|
42
42
|
async executeQuery(e, t) {
|
|
43
|
-
let n = v(e, this.sql, this.namespace), r = t ? a.provideService(n, this.sql.transactionService, t) : n, i = await
|
|
44
|
-
return
|
|
43
|
+
let n = v(e, this.sql, this.namespace), r = t ? a.provideService(n, this.sql.transactionService, t) : n, i = await k("mssql", "select", () => this.runtime.runPromise(r));
|
|
44
|
+
return b(i, e, "mssql");
|
|
45
45
|
}
|
|
46
46
|
decodeWritten(e, t) {
|
|
47
47
|
return y([t], e, "mssql")[0] ?? t;
|
|
48
48
|
}
|
|
49
49
|
async executeInsert(t, n, r, i, o) {
|
|
50
|
-
n =
|
|
51
|
-
let s = this.sql, c = e(s, this.nsT(t), (e) => s`INSERT INTO ${s(this.nsT(t))} ${s.insert(
|
|
50
|
+
n = B(t, n);
|
|
51
|
+
let s = this.sql, c = e(s, this.nsT(t), (e) => s`INSERT INTO ${s(this.nsT(t))} ${s.insert(S(n, t)).returning(s`INSERTED.* INTO ${e}`)}`), l = r ? a.provideService(c, this.sql.transactionService, r) : c, u = (await this.runtime.runPromise(l))[0];
|
|
52
52
|
if (!u) throw Error(`MssqlStore.insert: row not returned post-insert in '${t}'`);
|
|
53
53
|
let d = this.decodeWritten(t, u);
|
|
54
54
|
return await this.routeEvent({
|
|
@@ -59,7 +59,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
59
59
|
}, i, r, o), d;
|
|
60
60
|
}
|
|
61
61
|
async executeUpdate(t, n, r, i, o, s) {
|
|
62
|
-
let c = this.sql, l = e(c, this.nsT(t), (e) => c`UPDATE ${c(this.nsT(t))} SET ${c.update(
|
|
62
|
+
let c = this.sql, l = e(c, this.nsT(t), (e) => c`UPDATE ${c(this.nsT(t))} SET ${c.update(S(r, t)).returning(c`INSERTED.* INTO ${e}`)} WHERE ${c.and(I(n).map(([e, t]) => c`${c(e)} = ${t}`))}`), u = i ? a.provideService(l, this.sql.transactionService, i) : l, d = (await this.runtime.runPromise(u))[0];
|
|
63
63
|
if (!d) return null;
|
|
64
64
|
let f = this.decodeWritten(t, d);
|
|
65
65
|
return await this.routeEvent({
|
|
@@ -69,28 +69,32 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
69
69
|
new: f
|
|
70
70
|
}, o, i, s), f;
|
|
71
71
|
}
|
|
72
|
-
async executeInsertMany(t, n, r, i, o) {
|
|
73
|
-
if (n =
|
|
74
|
-
let
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
async executeInsertMany(t, n, r, i, o, s) {
|
|
73
|
+
if (n = V(t, n), n.length === 0) return [];
|
|
74
|
+
let c = this.sql, l = p(n, f("mssql")), u = s?.returning === "none", d = u && !G(t), m = (n) => {
|
|
75
|
+
let r = c.insert(n.map((e) => S(e, t)));
|
|
76
|
+
return d ? a.as(c`INSERT INTO ${c(this.nsT(t))} ${r}`, []) : e(c, this.nsT(t), (e) => c`INSERT INTO ${c(this.nsT(t))} ${r.returning(c`INSERTED.* INTO ${e}`)}`);
|
|
77
|
+
}, h;
|
|
78
|
+
if (l.length === 1) {
|
|
79
|
+
let e = m(l[0]), t = r ? a.provideService(e, this.sql.transactionService, r) : e;
|
|
80
|
+
h = await this.runtime.runPromise(t);
|
|
78
81
|
} else if (r) {
|
|
79
82
|
let e = [];
|
|
80
|
-
for (let t of
|
|
81
|
-
|
|
82
|
-
} else
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
for (let t of l) e.push(...await this.runtime.runPromise(a.provideService(m(t), this.sql.transactionService, r)));
|
|
84
|
+
h = e;
|
|
85
|
+
} else h = await this.runtime.runPromise(c.withTransaction(a.map(a.forEach(l, m, { concurrency: 1 }), (e) => e.flat())));
|
|
86
|
+
if (d) return [];
|
|
87
|
+
let g = n.map((e) => e.id), _ = y(h, t, "mssql"), v = new Map(_.map((e) => [e.id, e])), b = g.map((e) => v.get(e)).filter((e) => e !== void 0), x = b.length === h.length ? b : _;
|
|
88
|
+
for (let e of x) await this.routeEvent({
|
|
85
89
|
table: t,
|
|
86
90
|
op: "insert",
|
|
87
91
|
old: null,
|
|
88
92
|
new: e
|
|
89
93
|
}, i, r, o);
|
|
90
|
-
return
|
|
94
|
+
return u ? [] : x;
|
|
91
95
|
}
|
|
92
96
|
async executePatchJson(t, n, r, i, o, s, c, l) {
|
|
93
|
-
let u = this.sql, d =
|
|
97
|
+
let u = this.sql, d = S(E(n, r, l), t), f = u.csv([h(u, "mssql", r, i), ...Object.entries(d).map(([e, t]) => u`${u(e)} = ${t}`)]), p = e(u, this.nsT(t), (e) => u`UPDATE ${u(this.nsT(t))} SET ${f} OUTPUT INSERTED.* INTO ${e} WHERE ${u.and(I(n).map(([e, t]) => u`${u(e)} = ${t}`))}`), m = o ? a.provideService(p, this.sql.transactionService, o) : p, g = (await this.runtime.runPromise(m))[0];
|
|
94
98
|
if (!g) return null;
|
|
95
99
|
let _ = this.decodeWritten(t, g);
|
|
96
100
|
return await this.routeEvent({
|
|
@@ -101,7 +105,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
101
105
|
}, s, o, c), _;
|
|
102
106
|
}
|
|
103
107
|
async executeDelete(t, n, r, i, o) {
|
|
104
|
-
let s = this.sql, c = e(s, this.nsT(t), (e) => s`DELETE FROM ${s(this.nsT(t))} OUTPUT DELETED.* INTO ${e} WHERE ${s.and(
|
|
108
|
+
let s = this.sql, c = e(s, this.nsT(t), (e) => s`DELETE FROM ${s(this.nsT(t))} OUTPUT DELETED.* INTO ${e} WHERE ${s.and(I(n).map(([e, t]) => s`${s(e)} = ${t}`))}`), l = r ? a.provideService(c, this.sql.transactionService, r) : c, u = (await this.runtime.runPromise(l))[0];
|
|
105
109
|
if (!u) return !1;
|
|
106
110
|
let d = this.decodeWritten(t, u);
|
|
107
111
|
return await this.routeEvent({
|
|
@@ -112,7 +116,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
112
116
|
}, i, r, o), !0;
|
|
113
117
|
}
|
|
114
118
|
async appendInTxn(e, t, n) {
|
|
115
|
-
let r = this.sql, i = r`INSERT INTO ${r(this.nsT(e))} ${r.insert(
|
|
119
|
+
let r = this.sql, i = r`INSERT INTO ${r(this.nsT(e))} ${r.insert(S(t, e))}`;
|
|
116
120
|
await this.runtime.runPromise(n ? a.provideService(i, this.sql.transactionService, n) : i);
|
|
117
121
|
}
|
|
118
122
|
async maxInTxn(e, t, n, r) {
|
|
@@ -123,7 +127,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
123
127
|
e = {
|
|
124
128
|
...d(r),
|
|
125
129
|
...e
|
|
126
|
-
},
|
|
130
|
+
}, P(e.table) && await z({
|
|
127
131
|
append: (e, t) => this.appendInTxn(e, t, n),
|
|
128
132
|
maxOf: (e, t, r) => this.maxInTxn(e, t, r, n)
|
|
129
133
|
}, {
|
|
@@ -133,7 +137,10 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
133
137
|
prev: e.old,
|
|
134
138
|
traceId: e.traceId,
|
|
135
139
|
subjectId: e.subjectId
|
|
136
|
-
}),
|
|
140
|
+
}), T(e.table) && (t === null ? this.inlineEmit && this.emitter.emit("change", e) : t.push(e));
|
|
141
|
+
}
|
|
142
|
+
integrityQuery(e) {
|
|
143
|
+
return this.query(e);
|
|
137
144
|
}
|
|
138
145
|
query(e) {
|
|
139
146
|
return this.runWithEager(e, null);
|
|
@@ -143,13 +150,13 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
143
150
|
}
|
|
144
151
|
rawOn(e, t) {
|
|
145
152
|
let n = _(e, this.sql), r = t ? a.provideService(n, this.sql.transactionService, t) : n;
|
|
146
|
-
return
|
|
153
|
+
return k("mssql", "raw", () => this.runtime.runPromise(r));
|
|
147
154
|
}
|
|
148
155
|
async runWithEager(e, t) {
|
|
149
|
-
if (!
|
|
156
|
+
if (!w(e)) return this.executeQuery(e, t);
|
|
150
157
|
let n = this.namespace === null ? m(e, this.sql, "mssql") : null;
|
|
151
158
|
if (n !== null) try {
|
|
152
|
-
let e = t ? a.provideService(n.fragment, this.sql.transactionService, t) : n.fragment, r = await
|
|
159
|
+
let e = t ? a.provideService(n.fragment, this.sql.transactionService, t) : n.fragment, r = await k("mssql", "select", () => this.runtime.runPromise(e));
|
|
153
160
|
return n.decode(r);
|
|
154
161
|
} catch (t) {
|
|
155
162
|
if (t instanceof l) throw t;
|
|
@@ -166,27 +173,27 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
166
173
|
reason: "not-compilable"
|
|
167
174
|
});
|
|
168
175
|
let r = await this.executeQuery(e, t);
|
|
169
|
-
return u(r, e.eager, e.sourceTable ??
|
|
176
|
+
return u(r, e.eager, e.sourceTable ?? F(e.table), (e) => this.executeQuery(e, t));
|
|
170
177
|
}
|
|
171
178
|
getInternalRunWithEager() {
|
|
172
179
|
return this.runWithEager.bind(this);
|
|
173
180
|
}
|
|
174
181
|
localWrite(e, t, n) {
|
|
175
|
-
let r = (e) =>
|
|
176
|
-
return
|
|
182
|
+
let r = (e) => P(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
|
|
183
|
+
return k("mssql", e, () => W(r));
|
|
177
184
|
}
|
|
178
185
|
async writeWithRecorders(e, t) {
|
|
179
186
|
let n = [], r = this.sql, i = await this.runtime.runPromise(r.withTransaction(a.flatMap(a.serviceOption(this.sql.transactionService), (r) => c.isNone(r) ? a.fail(/* @__PURE__ */ Error("MssqlStore.write: TransactionConnection missing.")) : a.tryPromise({
|
|
180
187
|
try: () => e(t, r.value, n),
|
|
181
188
|
catch: (e) => e
|
|
182
189
|
}))));
|
|
183
|
-
return
|
|
190
|
+
return x(n, (e) => this.emitChange(e)), i;
|
|
184
191
|
}
|
|
185
192
|
insert(e, t) {
|
|
186
193
|
return this.localWrite("insert", e, (n, r, i) => this.executeInsert(e, t, r, i, n));
|
|
187
194
|
}
|
|
188
|
-
insertMany(e, t) {
|
|
189
|
-
return this.localWrite("insert", e, (
|
|
195
|
+
insertMany(e, t, n) {
|
|
196
|
+
return this.localWrite("insert", e, (r, i, a) => this.executeInsertMany(e, t, i, a, r, n));
|
|
190
197
|
}
|
|
191
198
|
patchJson(e, t, n, r, i) {
|
|
192
199
|
return this.localWrite("update", e, (a, o, s) => this.executePatchJson(e, t, n, r, o, s, a, i));
|
|
@@ -204,17 +211,25 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
204
211
|
return this.executeDeleteMany(e, t, null, null);
|
|
205
212
|
}
|
|
206
213
|
async executeUpdateMany(t, n, r, i, o, s) {
|
|
207
|
-
let c = this.sql, l = g(r.where, c, this.namespace), u =
|
|
208
|
-
|
|
214
|
+
let c = this.sql, l = g(r.where, c, this.namespace), u = c.update(S(n, t));
|
|
215
|
+
if (!G(t)) return this.countWritten(c`UPDATE ${c(this.nsT(t))} SET ${u} WHERE ${l}`, "update", i);
|
|
216
|
+
let d = e(c, this.nsT(t), (e) => c`UPDATE ${c(this.nsT(t))} SET ${u} OUTPUT INSERTED.* INTO ${e} WHERE ${l}`), f = i ? a.provideService(d, this.sql.transactionService, i) : d, p = await k("mssql", "update", () => this.runtime.runPromise(f));
|
|
217
|
+
for (let e of y(p, t, "mssql")) await this.routeEvent({
|
|
209
218
|
table: t,
|
|
210
219
|
op: "update",
|
|
211
220
|
old: null,
|
|
212
221
|
new: e
|
|
213
222
|
}, o, i, s);
|
|
214
|
-
return
|
|
223
|
+
return p.length;
|
|
224
|
+
}
|
|
225
|
+
async countWritten(e, t, n) {
|
|
226
|
+
let r = this.sql`${e}; SELECT @@ROWCOUNT AS n`, i = n ? a.provideService(r, this.sql.transactionService, n) : r, [o] = await k("mssql", t, () => this.runtime.runPromise(i));
|
|
227
|
+
return Number(o?.n ?? 0);
|
|
215
228
|
}
|
|
216
229
|
async executeDeleteMany(t, n, r, i, o) {
|
|
217
|
-
let s = this.sql, c = g(n.where, s, this.namespace)
|
|
230
|
+
let s = this.sql, c = g(n.where, s, this.namespace);
|
|
231
|
+
if (!G(t)) return this.countWritten(s`DELETE FROM ${s(this.nsT(t))} WHERE ${c}`, "delete", r);
|
|
232
|
+
let l = e(s, this.nsT(t), (e) => s`DELETE FROM ${s(this.nsT(t))} OUTPUT DELETED.* INTO ${e} WHERE ${c}`), u = r ? a.provideService(l, this.sql.transactionService, r) : l, d = await k("mssql", "delete", () => this.runtime.runPromise(u));
|
|
218
233
|
for (let e of y(d, t, "mssql")) await this.routeEvent({
|
|
219
234
|
table: t,
|
|
220
235
|
op: "delete",
|
|
@@ -233,24 +248,24 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
233
248
|
return this.localWrite("upsert", e, (r, i, a) => this.executeInsertIgnore(e, t, n, i, a, r));
|
|
234
249
|
}
|
|
235
250
|
async executeUpsert(e, n, r, i, a, o) {
|
|
236
|
-
if (
|
|
251
|
+
if (U(r), n = B(e, n), typeof r.update != "function" && r.conflictColumns.length > 0) return this.mergeUpsert(e, n, {
|
|
237
252
|
conflictColumns: r.conflictColumns,
|
|
238
253
|
...r.update === void 0 ? {} : { update: r.update },
|
|
239
254
|
...r.updateValues === void 0 ? {} : { updateValues: r.updateValues }
|
|
240
255
|
}, i, a, o);
|
|
241
256
|
let s = await this.findByConflict(e, n, r.conflictColumns, i);
|
|
242
|
-
if (s) return await this.executeUpdate(e, Object.fromEntries(r.conflictColumns.map((e) => [e, s[e]])),
|
|
257
|
+
if (s) return await this.executeUpdate(e, Object.fromEntries(r.conflictColumns.map((e) => [e, s[e]])), H(n, s, r), i, a, o) ?? s;
|
|
243
258
|
try {
|
|
244
259
|
return await this.executeInsert(e, n, i, a, o);
|
|
245
260
|
} catch (s) {
|
|
246
261
|
if (!t(s)) throw s;
|
|
247
262
|
let c = await this.findByConflict(e, n, r.conflictColumns, i);
|
|
248
263
|
if (!c) throw s;
|
|
249
|
-
return await this.executeUpdate(e, Object.fromEntries(r.conflictColumns.map((e) => [e, c[e]])),
|
|
264
|
+
return await this.executeUpdate(e, Object.fromEntries(r.conflictColumns.map((e) => [e, c[e]])), H(n, c, r), i, a, o) ?? c;
|
|
250
265
|
}
|
|
251
266
|
}
|
|
252
267
|
async mergeUpsert(t, n, r, i, o, s) {
|
|
253
|
-
let c = this.sql, l = Object.keys(n), u = Array.isArray(r.update) ? r.update.filter((e) => l.includes(e)) : l.filter((e) => e !== "id" && !r.conflictColumns.includes(e)), d =
|
|
268
|
+
let c = this.sql, l = Object.keys(n), u = Array.isArray(r.update) ? r.update.filter((e) => l.includes(e)) : l.filter((e) => e !== "id" && !r.conflictColumns.includes(e)), d = S(n, t), f = l.map((e) => c`${d[e]}`), p = l.map((e) => c`${c(e)}`), m = r.conflictColumns.map((e) => c`tgt.${c(e)} = src.${c(e)}`), h = l.map((e) => c`${c(e)}`), g = l.map((e) => c`src.${c(e)}`), _ = U(r), v = S(_, t), y = [...u.filter((e) => !Object.hasOwn(_, e)).map((e) => c`tgt.${c(e)} = src.${c(e)}`), ...Object.entries(v).map(([e, t]) => c`tgt.${c(e)} = ${t}`)];
|
|
254
269
|
y.length === 0 && y.push(c`tgt.${c(r.conflictColumns[0])} = src.${c(r.conflictColumns[0])}`);
|
|
255
270
|
let b = e(c, this.nsT(t), (e) => c`
|
|
256
271
|
MERGE ${c(this.nsT(t))} WITH (HOLDLOCK) AS tgt
|
|
@@ -258,7 +273,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
258
273
|
ON ${c.and(m)}
|
|
259
274
|
WHEN MATCHED THEN UPDATE SET ${c.csv(y)}
|
|
260
275
|
WHEN NOT MATCHED THEN INSERT (${c.csv(h)}) VALUES (${c.csv(g)})
|
|
261
|
-
OUTPUT $action AS ${c("__action")}, INSERTED.* INTO ${e};`, !0),
|
|
276
|
+
OUTPUT $action AS ${c("__action")}, INSERTED.* INTO ${e};`, !0), x = i ? a.provideService(b, this.sql.transactionService, i) : b, C = (await this.runtime.runPromise(x))[0];
|
|
262
277
|
if (!C) throw Error(`MssqlStore.upsert: MERGE returned no row for '${t}'`);
|
|
263
278
|
let w = C.__action, { __action: T, ...E } = C, D = this.decodeWritten(t, E);
|
|
264
279
|
return await this.routeEvent({
|
|
@@ -269,7 +284,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
269
284
|
}, o, i, s), D;
|
|
270
285
|
}
|
|
271
286
|
async executeInsertIgnore(e, n, r, i, a, o) {
|
|
272
|
-
n =
|
|
287
|
+
n = B(e, n);
|
|
273
288
|
let s = await this.findByConflict(e, n, r.conflictColumns, i);
|
|
274
289
|
if (s) return {
|
|
275
290
|
row: s,
|
|
@@ -302,7 +317,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
302
317
|
if (this.cdcHandle) return;
|
|
303
318
|
this.cdcReplicaId = e.replicaId;
|
|
304
319
|
let t = e.includeTables ?? [];
|
|
305
|
-
t.length === 0 &&
|
|
320
|
+
t.length === 0 && Y.warn("cdc: no reactive tables to tail; Change Tracking reader idle. Set includeTables to enable.");
|
|
306
321
|
let n = await this.readCdcOffset(e.replicaId);
|
|
307
322
|
this.cdcHandle = await r({
|
|
308
323
|
run: this.__mssqlReplicationFriend.runEffect,
|
|
@@ -312,9 +327,9 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
312
327
|
onVersion: (e) => {
|
|
313
328
|
this.cdcPendingVersion = e;
|
|
314
329
|
},
|
|
315
|
-
onError: (e) =>
|
|
330
|
+
onError: (e) => Y.warn("cdc: consumer error", {}, e),
|
|
316
331
|
onResync: () => {
|
|
317
|
-
|
|
332
|
+
Y.warn("cdc: resynced to current CT version after retention gap — subscriptions self-heal on the next change");
|
|
318
333
|
}
|
|
319
334
|
}), this.cdcCheckpointTimer = setInterval(() => {
|
|
320
335
|
this.flushCdcOffset();
|
|
@@ -325,12 +340,12 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
325
340
|
let t = this.sql, n = (await this.runtime.runPromise(t`
|
|
326
341
|
SELECT TOP 1 ${t("ctVersion")} FROM ${t(i)}
|
|
327
342
|
WHERE ${t("id")} = ${e}`))[0]?.ctVersion;
|
|
328
|
-
return n ? (
|
|
343
|
+
return n ? (Y.info("cdc: resuming from persisted CT version", {
|
|
329
344
|
replicaId: e,
|
|
330
345
|
version: n
|
|
331
346
|
}), n) : null;
|
|
332
347
|
} catch (t) {
|
|
333
|
-
return
|
|
348
|
+
return Y.warn("cdc: no readable offset; starting at current CT version", { replicaId: e }, t), null;
|
|
334
349
|
}
|
|
335
350
|
}
|
|
336
351
|
async flushCdcOffset() {
|
|
@@ -350,7 +365,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
350
365
|
update: ["ctVersion", "updatedAt"]
|
|
351
366
|
}, null, null);
|
|
352
367
|
} catch (t) {
|
|
353
|
-
this.cdcPendingVersion = e,
|
|
368
|
+
this.cdcPendingVersion = e, Y.warn("cdc: checkpoint write failed", {}, t);
|
|
354
369
|
}
|
|
355
370
|
}
|
|
356
371
|
}
|
|
@@ -405,16 +420,16 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
405
420
|
}
|
|
406
421
|
async emptyTablesOn(e, t) {
|
|
407
422
|
if (e.length === 0) return;
|
|
408
|
-
let n = this.sql, r = (e) => this.nsT(e), i = (e, t) => n.unsafe(`ALTER TABLE ${
|
|
423
|
+
let n = this.sql, r = (e) => this.nsT(e), i = (e, t) => n.unsafe(`ALTER TABLE ${M(r(e), "mssql")} ${t ? "WITH CHECK CHECK" : "NOCHECK"} CONSTRAINT ALL`), o = a.acquireUseRelease(a.forEach(e, (e) => i(e, !1), { discard: !0 }), () => a.forEach(e, (e) => n`DELETE FROM ${n(r(e))}`, { discard: !0 }), () => a.orDie(a.ignore(a.forEach(e, (e) => i(e, !0), { discard: !0 })))), s = t === null ? n.withTransaction(o) : a.provideService(o, this.sql.transactionService, t);
|
|
409
424
|
await this.runtime.runPromise(s);
|
|
410
425
|
}
|
|
411
426
|
async transactional(e) {
|
|
412
427
|
this.inflightTxns++;
|
|
413
428
|
try {
|
|
414
|
-
return await
|
|
429
|
+
return await R({
|
|
415
430
|
...this.txnSpec("MssqlStore.transactional"),
|
|
416
431
|
work: e,
|
|
417
|
-
makeView: (e, t) => new
|
|
432
|
+
makeView: (e, t) => new Q(this, e, t)
|
|
418
433
|
});
|
|
419
434
|
} finally {
|
|
420
435
|
this.inflightTxns--;
|
|
@@ -449,7 +464,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
449
464
|
return this.changeStrategy === "cdc" ? "fleet" : "local";
|
|
450
465
|
}
|
|
451
466
|
injectExternalChange(e) {
|
|
452
|
-
|
|
467
|
+
T(e.table) && this.emitter.emit("change", C(e));
|
|
453
468
|
}
|
|
454
469
|
run(e) {
|
|
455
470
|
return this.runtime.runPromise(e);
|
|
@@ -462,7 +477,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
462
477
|
if (this.inflightTxns > 0) {
|
|
463
478
|
let t = Date.now() + e;
|
|
464
479
|
for (; this.inflightTxns > 0 && Date.now() < t;) await new Promise((e) => setTimeout(e, 25));
|
|
465
|
-
this.inflightTxns > 0 &&
|
|
480
|
+
this.inflightTxns > 0 && Y.warn("close: grace period expired with in-flight transactions", {
|
|
466
481
|
gracePeriodMs: e,
|
|
467
482
|
inflight: this.inflightTxns
|
|
468
483
|
});
|
|
@@ -472,27 +487,32 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
472
487
|
async ping() {
|
|
473
488
|
await this.runtime.runPromise(this.sql`SELECT 1`);
|
|
474
489
|
}
|
|
475
|
-
},
|
|
490
|
+
}, Q = class {
|
|
476
491
|
parent;
|
|
477
492
|
txn;
|
|
478
493
|
attr;
|
|
479
494
|
events = [];
|
|
480
|
-
aborts =
|
|
495
|
+
aborts = O((e) => n(e));
|
|
481
496
|
committed = !1;
|
|
482
497
|
constructor(e, t, n = void 0) {
|
|
483
498
|
this.parent = e, this.txn = t, this.attr = n;
|
|
484
499
|
}
|
|
485
|
-
savepoint(e) {
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
500
|
+
async savepoint(e) {
|
|
501
|
+
let t = this.events.length;
|
|
502
|
+
try {
|
|
503
|
+
return await L({
|
|
504
|
+
tracker: this.aborts,
|
|
505
|
+
name: `voltro_sp_${++this.savepointCounter}`,
|
|
506
|
+
spelling: "mssql",
|
|
507
|
+
exec: (e) => this.parent.run(a.provideService(J.pipe(a.flatMap((t) => t.unsafe(e))), this.parent.transactionService, this.txn))
|
|
508
|
+
}, e);
|
|
509
|
+
} catch (e) {
|
|
510
|
+
throw this.events.length = t, e;
|
|
511
|
+
}
|
|
492
512
|
}
|
|
493
513
|
savepointCounter = 0;
|
|
494
514
|
run(e) {
|
|
495
|
-
return this.aborts.track(() => this.parent.run(
|
|
515
|
+
return this.aborts.track(() => this.parent.run(A(e, this.parent.transactionService, this.txn)));
|
|
496
516
|
}
|
|
497
517
|
abortedBy() {
|
|
498
518
|
return this.aborts.abortedBy();
|
|
@@ -500,6 +520,9 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
500
520
|
raw(e, t) {
|
|
501
521
|
return this.aborts.track(() => this.parent.rawOn(e, this.txn));
|
|
502
522
|
}
|
|
523
|
+
integrityQuery(e) {
|
|
524
|
+
return this.query(e);
|
|
525
|
+
}
|
|
503
526
|
query(e) {
|
|
504
527
|
return this.aborts.track(() => this.parent.getInternalRunWithEager()(e, this.txn));
|
|
505
528
|
}
|
|
@@ -509,8 +532,8 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
509
532
|
insert(e, t) {
|
|
510
533
|
return this.aborts.track(() => this.parent.getInternalExecuteInsert()(e, t, this.txn, this.events, this.attr));
|
|
511
534
|
}
|
|
512
|
-
insertMany(e, t) {
|
|
513
|
-
return this.aborts.track(() => this.parent.getInternalExecuteInsertMany()(e, t, this.txn, this.events, this.attr));
|
|
535
|
+
insertMany(e, t, n) {
|
|
536
|
+
return this.aborts.track(() => this.parent.getInternalExecuteInsertMany()(e, t, this.txn, this.events, this.attr, n));
|
|
514
537
|
}
|
|
515
538
|
patchJson(e, t, n, r, i) {
|
|
516
539
|
return this.aborts.track(() => this.parent.getInternalExecutePatchJson()(e, t, n, r, this.txn, this.events, this.attr, i));
|
|
@@ -546,8 +569,8 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
546
569
|
throw Error("MssqlTransactionalView.injectExternalChange: not supported inside a transaction.");
|
|
547
570
|
}
|
|
548
571
|
commitEvents() {
|
|
549
|
-
this.committed || (this.committed = !0,
|
|
572
|
+
this.committed || (this.committed = !0, x(this.events, (e) => this.parent.emitChange(e)), this.events.length = 0);
|
|
550
573
|
}
|
|
551
574
|
};
|
|
552
575
|
//#endregion
|
|
553
|
-
export {
|
|
576
|
+
export { Z as MssqlStore, X as makeMssqlStore };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/sql-mssql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.87.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",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@effect/sql-mssql": "4.0.1",
|
|
37
|
-
"@voltro/database": "0.
|
|
38
|
-
"@voltro/logger": "0.
|
|
37
|
+
"@voltro/database": "0.87.0",
|
|
38
|
+
"@voltro/logger": "0.87.0",
|
|
39
39
|
"tedious": "20.3.3"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|