@voltro/sql-mssql 0.86.0 → 0.88.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 +5484 -0
- package/THIRD-PARTY-NOTICES.md +90 -285
- package/dist/binaryParameter.js +1 -2
- package/dist/changeTrackingCdc.js +1 -2
- package/dist/index.d.ts +9 -1
- package/dist/index.js +1 -2
- package/dist/numberParameter.js +1 -2
- package/dist/replicationAdapter.js +1 -2
- package/dist/retry.js +1 -2
- package/dist/rowResultProjection.js +1 -2
- package/dist/sqlLayer.js +1 -2
- package/dist/store.js +134 -112
- package/dist/writeOutput.js +1 -2
- package/package.json +6 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect as e } from "effect";
|
|
2
2
|
import { SqlClient as t } from "effect/sql/SqlClient";
|
|
3
|
-
|
|
3
|
+
// src/replicationAdapter.ts
|
|
4
4
|
var n = (e) => e.__mssqlReplicationFriend ?? null, r = (e, t) => e === t ? 0 : e < t ? -1 : 1, i = () => ({
|
|
5
5
|
async capturePrimaryPosition(r) {
|
|
6
6
|
let i = n(r);
|
|
@@ -31,5 +31,4 @@ var n = (e) => e.__mssqlReplicationFriend ?? null, r = (e, t) => e === t ? 0 : e
|
|
|
31
31
|
return r(t, e) >= 0 ? "caught-up" : "behind";
|
|
32
32
|
}
|
|
33
33
|
});
|
|
34
|
-
//#endregion
|
|
35
34
|
export { i as mssqlReplicationAdapter };
|
package/dist/retry.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MSSQL_TRANSIENT_NUMBERS as e, causeBranches as t } from "@voltro/database";
|
|
2
|
-
|
|
2
|
+
// src/retry.ts
|
|
3
3
|
var n = e, r = (e) => {
|
|
4
4
|
let t = e;
|
|
5
5
|
for (let e = 0; e < 5 && typeof t == "object" && t; e++) {
|
|
@@ -16,5 +16,4 @@ var n = e, r = (e) => {
|
|
|
16
16
|
let t = r(e);
|
|
17
17
|
return t !== void 0 && a.has(t);
|
|
18
18
|
}), s = (e) => i(e) ? "retry" : "noRetry";
|
|
19
|
-
//#endregion
|
|
20
19
|
export { o as isDuplicateKeyMssqlFailure, i as isRetryableMssqlFailure, s as mssqlRetryFilter };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect as e } from "effect";
|
|
2
2
|
import { sqlError as t } from "@voltro/database";
|
|
3
|
-
|
|
3
|
+
// src/rowResultProjection.ts
|
|
4
4
|
var n = (n, r) => e.gen(function* () {
|
|
5
5
|
let e = yield* n`
|
|
6
6
|
SELECT name, system_type_id FROM sys.columns
|
|
@@ -12,5 +12,4 @@ var n = (n, r) => e.gen(function* () {
|
|
|
12
12
|
let r = e.literal(`[${t.name.replaceAll("]", "]]")}]`), i = n ? e`${e(n)}.${r}` : r;
|
|
13
13
|
return t.system_type_id === 106 || t.system_type_id === 108 ? e`CONVERT(varchar(80), ${i}) AS ${r}` : i;
|
|
14
14
|
}));
|
|
15
|
-
//#endregion
|
|
16
15
|
export { r as mssqlRowResultProjection, n as readMssqlPhysicalColumns };
|
package/dist/sqlLayer.js
CHANGED
|
@@ -4,7 +4,7 @@ import { MssqlClient as n } from "@effect/sql-mssql";
|
|
|
4
4
|
import { TYPES as r } from "tedious";
|
|
5
5
|
import { Config as i, Duration as a, Redacted as o } from "effect";
|
|
6
6
|
import { DEFAULT_ACQUIRE_TIMEOUT_MS as s, SHARED_TRANSACTION_SERVICE as c } from "@voltro/database";
|
|
7
|
-
|
|
7
|
+
// src/sqlLayer.ts
|
|
8
8
|
var l = {
|
|
9
9
|
...n.defaultParameterTypes,
|
|
10
10
|
null: r.NVarChar,
|
|
@@ -74,5 +74,4 @@ var l = {
|
|
|
74
74
|
...t
|
|
75
75
|
};
|
|
76
76
|
}, m = (e) => d(p(e));
|
|
77
|
-
//#endregion
|
|
78
77
|
export { n as MssqlClient, p as connectionFromConfig, d as makeMssqlSqlLayer, m as makeMssqlSqlLayerFromConfig, u as resolveAcquireTimeoutMs, f as sslFromUrlQuery };
|
package/dist/store.js
CHANGED
|
@@ -2,53 +2,53 @@ import { writeOutput as e } from "./writeOutput.js";
|
|
|
2
2
|
import { isDuplicateKeyMssqlFailure as t, isRetryableMssqlFailure as n } from "./retry.js";
|
|
3
3
|
import { startChangeTrackingCdc as r } from "./changeTrackingCdc.js";
|
|
4
4
|
import { CDC_OFFSETS_TABLE as i } from "./cdcOffsetsTable.js";
|
|
5
|
-
import {
|
|
6
|
-
import { EagerCardinalityError as
|
|
7
|
-
import { EventEmitter as
|
|
8
|
-
import { createLogger as
|
|
9
|
-
import { SqlClient as
|
|
10
|
-
|
|
11
|
-
var
|
|
5
|
+
import { Array as a, Effect as o, Layer as s, ManagedRuntime as c, Option as l } from "effect";
|
|
6
|
+
import { EagerCardinalityError as u, attachEagerLoads as d, attributionFields as f, bulkInsertLimitsFor as p, chunkRowsForInsert as m, compileEagerJson as h, compileJsonPatch as g, compilePredicate as _, compileRawFragment as v, compileSelect as y, decodeRowsFromSchema as b, decodeSelectRows as x, emitCommittedChanges as S, encodeRowForSchema as C, externalChangeEvent as w, hasEagerLoads as T, isTableReactive as E, jsonPatchAssignments as D, makeEagerFallbackReporter as O, makeTransactionAbortTracker as k, observeDbOp as A, onTransaction as j, qualifyTable as M, quoteIdent as N, raiseChangeListenerCeiling as P, recordsTable as F, requireTable as I, rowKeyColumns as L, runSavepoint as R, runStoreTransaction as z, runWriteRecorders as B, stampGeneratedId as V, stampGeneratedIds as H, upsertUpdatePatch as U, upsertUpdateValues as W, withCapturedAttribution as G, writeImagesObserved as K } from "@voltro/database";
|
|
7
|
+
import { EventEmitter as q } from "node:events";
|
|
8
|
+
import { createLogger as J } from "@voltro/logger";
|
|
9
|
+
import { SqlClient as Y } from "effect/sql/SqlClient";
|
|
10
|
+
// src/store.ts
|
|
11
|
+
var X = J({ scope: "voltro:mssql" }), Z = async (e) => {
|
|
12
12
|
let t = e.changeStrategy ?? "inline", n = t;
|
|
13
|
-
t === "cdc" && !e.cdcConfig && (
|
|
14
|
-
let r = e.tracerLayer ?
|
|
13
|
+
t === "cdc" && !e.cdcConfig && (X.warn("changeStrategy='cdc' requires cdcConfig (replicaId + includeTables); falling back to 'inline'."), n = "inline");
|
|
14
|
+
let r = e.tracerLayer ? s.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, i = c.make(r), a = new Q(await i.runPromise(Y), i, n);
|
|
15
15
|
return n === "cdc" && e.cdcConfig && await a.startCdcConsumer(e.cdcConfig), a;
|
|
16
|
-
},
|
|
16
|
+
}, Q = class s {
|
|
17
17
|
sql;
|
|
18
18
|
runtime;
|
|
19
19
|
changeStrategy;
|
|
20
20
|
namespace;
|
|
21
21
|
emitter;
|
|
22
22
|
inflightTxns = 0;
|
|
23
|
-
reportEagerFallback =
|
|
23
|
+
reportEagerFallback = O(X);
|
|
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 q(), P(this.emitter);
|
|
31
31
|
}
|
|
32
32
|
get inlineEmit() {
|
|
33
33
|
return this.changeStrategy === "inline";
|
|
34
34
|
}
|
|
35
35
|
withNamespace(e) {
|
|
36
|
-
return e === this.namespace ? this : new
|
|
36
|
+
return e === this.namespace ? this : new s(this.sql, this.runtime, this.changeStrategy, e, this.emitter);
|
|
37
37
|
}
|
|
38
38
|
nsT(e) {
|
|
39
|
-
return
|
|
39
|
+
return M(this.namespace, e);
|
|
40
40
|
}
|
|
41
41
|
__mssqlReplicationFriend = { runEffect: (e) => this.runtime.runPromise(e) };
|
|
42
42
|
async executeQuery(e, t) {
|
|
43
|
-
let n =
|
|
44
|
-
return
|
|
43
|
+
let n = y(e, this.sql, this.namespace), r = t ? o.provideService(n, this.sql.transactionService, t) : n, i = await A("mssql", "select", () => this.runtime.runPromise(r));
|
|
44
|
+
return x(i, e, "mssql");
|
|
45
45
|
}
|
|
46
46
|
decodeWritten(e, t) {
|
|
47
|
-
return
|
|
47
|
+
return b([t], e, "mssql")[0] ?? t;
|
|
48
48
|
}
|
|
49
|
-
async executeInsert(t, n, r, i,
|
|
50
|
-
n =
|
|
51
|
-
let s = this.sql, c = e(s, this.nsT(t), (e) => s`INSERT INTO ${s(this.nsT(t))} ${s.insert(
|
|
49
|
+
async executeInsert(t, n, r, i, a) {
|
|
50
|
+
n = V(t, n);
|
|
51
|
+
let s = this.sql, c = e(s, this.nsT(t), (e) => s`INSERT INTO ${s(this.nsT(t))} ${s.insert(C(n, t)).returning(s`INSERTED.* INTO ${e}`)}`), l = r ? o.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({
|
|
@@ -56,10 +56,10 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
56
56
|
op: "insert",
|
|
57
57
|
old: null,
|
|
58
58
|
new: d
|
|
59
|
-
}, i, r,
|
|
59
|
+
}, i, r, a), d;
|
|
60
60
|
}
|
|
61
|
-
async executeUpdate(t, n, r, i,
|
|
62
|
-
let c = this.sql, l = e(c, this.nsT(t), (e) => c`UPDATE ${c(this.nsT(t))} SET ${c.update(
|
|
61
|
+
async executeUpdate(t, n, r, i, a, s) {
|
|
62
|
+
let c = this.sql, l = e(c, this.nsT(t), (e) => c`UPDATE ${c(this.nsT(t))} SET ${c.update(C(r, t)).returning(c`INSERTED.* INTO ${e}`)} WHERE ${c.and(L(n).map(([e, t]) => c`${c(e)} = ${t}`))}`), u = i ? o.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({
|
|
@@ -67,41 +67,45 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
67
67
|
op: "update",
|
|
68
68
|
old: null,
|
|
69
69
|
new: f
|
|
70
|
-
},
|
|
71
|
-
}
|
|
72
|
-
async executeInsertMany(t, n, r, i,
|
|
73
|
-
if (n =
|
|
74
|
-
let
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
}, a, i, s), f;
|
|
71
|
+
}
|
|
72
|
+
async executeInsertMany(t, n, r, i, s, c) {
|
|
73
|
+
if (n = H(t, n), n.length === 0) return [];
|
|
74
|
+
let l = this.sql, u = m(n, p("mssql")), d = c?.returning === "none", f = d && !K(t), h = (n) => {
|
|
75
|
+
let r = l.insert(a.map(n, (e) => C(e, t)));
|
|
76
|
+
return f ? o.as(l`INSERT INTO ${l(this.nsT(t))} ${r}`, []) : e(l, this.nsT(t), (e) => l`INSERT INTO ${l(this.nsT(t))} ${r.returning(l`INSERTED.* INTO ${e}`)}`);
|
|
77
|
+
}, g;
|
|
78
|
+
if (u.length === 1) {
|
|
79
|
+
let e = h(u[0]), t = r ? o.provideService(e, this.sql.transactionService, r) : e;
|
|
80
|
+
g = 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 u) e.push(...await this.runtime.runPromise(o.provideService(h(t), this.sql.transactionService, r)));
|
|
84
|
+
g = e;
|
|
85
|
+
} else g = await this.runtime.runPromise(l.withTransaction(o.map(o.forEach(u, h, { concurrency: 1 }), (e) => e.flat())));
|
|
86
|
+
if (f) return [];
|
|
87
|
+
let _ = n.map((e) => e.id), v = b(g, t, "mssql"), y = new Map(v.map((e) => [e.id, e])), x = _.map((e) => y.get(e)).filter((e) => e !== void 0), S = x.length === g.length ? x : v;
|
|
88
|
+
for (let e of S) await this.routeEvent({
|
|
85
89
|
table: t,
|
|
86
90
|
op: "insert",
|
|
87
91
|
old: null,
|
|
88
92
|
new: e
|
|
89
|
-
}, i, r,
|
|
90
|
-
return
|
|
93
|
+
}, i, r, s);
|
|
94
|
+
return d ? [] : S;
|
|
91
95
|
}
|
|
92
|
-
async executePatchJson(t, n, r, i,
|
|
93
|
-
let u = this.sql, d =
|
|
94
|
-
if (!
|
|
95
|
-
let _ = this.decodeWritten(t,
|
|
96
|
+
async executePatchJson(t, n, r, i, a, s, c, l) {
|
|
97
|
+
let u = this.sql, d = C(D(n, r, l), t), f = u.csv([g(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(L(n).map(([e, t]) => u`${u(e)} = ${t}`))}`), m = a ? o.provideService(p, this.sql.transactionService, a) : p, h = (await this.runtime.runPromise(m))[0];
|
|
98
|
+
if (!h) return null;
|
|
99
|
+
let _ = this.decodeWritten(t, h);
|
|
96
100
|
return await this.routeEvent({
|
|
97
101
|
table: t,
|
|
98
102
|
op: "update",
|
|
99
103
|
old: null,
|
|
100
104
|
new: _
|
|
101
|
-
}, s,
|
|
105
|
+
}, s, a, c), _;
|
|
102
106
|
}
|
|
103
|
-
async executeDelete(t, n, r, i,
|
|
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(
|
|
107
|
+
async executeDelete(t, n, r, i, a) {
|
|
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(L(n).map(([e, t]) => s`${s(e)} = ${t}`))}`), l = r ? o.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({
|
|
@@ -109,21 +113,21 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
109
113
|
op: "delete",
|
|
110
114
|
old: d,
|
|
111
115
|
new: null
|
|
112
|
-
}, i, r,
|
|
116
|
+
}, i, r, a), !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(
|
|
116
|
-
await this.runtime.runPromise(n ?
|
|
119
|
+
let r = this.sql, i = r`INSERT INTO ${r(this.nsT(e))} ${r.insert(C(t, e))}`;
|
|
120
|
+
await this.runtime.runPromise(n ? o.provideService(i, this.sql.transactionService, n) : i);
|
|
117
121
|
}
|
|
118
122
|
async maxInTxn(e, t, n, r) {
|
|
119
|
-
let i = this.sql,
|
|
123
|
+
let i = this.sql, a = Object.entries(n).map(([e, t]) => i`${i(e)} = ${t}`), s = i`SELECT MAX(${i(t)}) AS ${i("m")} FROM ${i(this.nsT(e))} WHERE ${i.and(a)}`, c = (await this.runtime.runPromise(r ? o.provideService(s, this.sql.transactionService, r) : s))[0]?.m;
|
|
120
124
|
return c == null ? null : Number(c);
|
|
121
125
|
}
|
|
122
126
|
async routeEvent(e, t, n = null, r) {
|
|
123
127
|
e = {
|
|
124
|
-
...
|
|
128
|
+
...f(r),
|
|
125
129
|
...e
|
|
126
|
-
},
|
|
130
|
+
}, F(e.table) && await B({
|
|
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
|
+
}), E(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);
|
|
@@ -142,17 +149,17 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
142
149
|
return this.rawOn(e, null);
|
|
143
150
|
}
|
|
144
151
|
rawOn(e, t) {
|
|
145
|
-
let n =
|
|
146
|
-
return
|
|
152
|
+
let n = v(e, this.sql), r = t ? o.provideService(n, this.sql.transactionService, t) : n;
|
|
153
|
+
return A("mssql", "raw", () => this.runtime.runPromise(r));
|
|
147
154
|
}
|
|
148
155
|
async runWithEager(e, t) {
|
|
149
|
-
if (!
|
|
150
|
-
let n = this.namespace === null ?
|
|
156
|
+
if (!T(e)) return this.executeQuery(e, t);
|
|
157
|
+
let n = this.namespace === null ? h(e, this.sql, "mssql") : null;
|
|
151
158
|
if (n !== null) try {
|
|
152
|
-
let e = t ?
|
|
159
|
+
let e = t ? o.provideService(n.fragment, this.sql.transactionService, t) : n.fragment, r = await A("mssql", "select", () => this.runtime.runPromise(e));
|
|
153
160
|
return n.decode(r);
|
|
154
161
|
} catch (t) {
|
|
155
|
-
if (t instanceof
|
|
162
|
+
if (t instanceof u) throw t;
|
|
156
163
|
this.reportEagerFallback({
|
|
157
164
|
dialect: "mssql",
|
|
158
165
|
table: e.table,
|
|
@@ -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
|
|
176
|
+
return d(r, e.eager, e.sourceTable ?? I(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) => F(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
|
|
183
|
+
return A("mssql", e, () => G(r));
|
|
177
184
|
}
|
|
178
185
|
async writeWithRecorders(e, t) {
|
|
179
|
-
let n = [], r = this.sql, i = await this.runtime.runPromise(r.withTransaction(
|
|
186
|
+
let n = [], r = this.sql, i = await this.runtime.runPromise(r.withTransaction(o.flatMap(o.serviceOption(this.sql.transactionService), (r) => l.isNone(r) ? o.fail(/* @__PURE__ */ Error("MssqlStore.write: TransactionConnection missing.")) : o.tryPromise({
|
|
180
187
|
try: () => e(t, r.value, n),
|
|
181
188
|
catch: (e) => e
|
|
182
189
|
}))));
|
|
183
|
-
return
|
|
190
|
+
return S(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));
|
|
@@ -203,24 +210,32 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
203
210
|
deleteMany(e, t) {
|
|
204
211
|
return this.executeDeleteMany(e, t, null, null);
|
|
205
212
|
}
|
|
206
|
-
async executeUpdateMany(t, n, r, i,
|
|
207
|
-
let c = this.sql, l =
|
|
208
|
-
|
|
213
|
+
async executeUpdateMany(t, n, r, i, a, s) {
|
|
214
|
+
let c = this.sql, l = _(r.where, c, this.namespace), u = c.update(C(n, t));
|
|
215
|
+
if (!K(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 ? o.provideService(d, this.sql.transactionService, i) : d, p = await A("mssql", "update", () => this.runtime.runPromise(f));
|
|
217
|
+
for (let e of b(p, t, "mssql")) await this.routeEvent({
|
|
209
218
|
table: t,
|
|
210
219
|
op: "update",
|
|
211
220
|
old: null,
|
|
212
221
|
new: e
|
|
213
|
-
},
|
|
214
|
-
return
|
|
215
|
-
}
|
|
216
|
-
async
|
|
217
|
-
let
|
|
218
|
-
|
|
222
|
+
}, a, i, s);
|
|
223
|
+
return p.length;
|
|
224
|
+
}
|
|
225
|
+
async countWritten(e, t, n) {
|
|
226
|
+
let r = (0, this.sql)`${e}; SELECT @@ROWCOUNT AS n`, i = n ? o.provideService(r, this.sql.transactionService, n) : r, [a] = await A("mssql", t, () => this.runtime.runPromise(i));
|
|
227
|
+
return Number(a?.n ?? 0);
|
|
228
|
+
}
|
|
229
|
+
async executeDeleteMany(t, n, r, i, a) {
|
|
230
|
+
let s = this.sql, c = _(n.where, s, this.namespace);
|
|
231
|
+
if (!K(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 ? o.provideService(l, this.sql.transactionService, r) : l, d = await A("mssql", "delete", () => this.runtime.runPromise(u));
|
|
233
|
+
for (let e of b(d, t, "mssql")) await this.routeEvent({
|
|
219
234
|
table: t,
|
|
220
235
|
op: "delete",
|
|
221
236
|
old: e,
|
|
222
237
|
new: null
|
|
223
|
-
}, i, r,
|
|
238
|
+
}, i, r, a);
|
|
224
239
|
return d.length;
|
|
225
240
|
}
|
|
226
241
|
upsert(e, t, n) {
|
|
@@ -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 (W(r), n = V(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]])), U(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]])), U(n, c, r), i, a, o) ?? c;
|
|
250
265
|
}
|
|
251
266
|
}
|
|
252
|
-
async mergeUpsert(t, n, r, i,
|
|
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 =
|
|
267
|
+
async mergeUpsert(t, n, r, i, a, s) {
|
|
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 = C(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)}`), _ = W(r), v = C(_, 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,18 +273,18 @@ 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),
|
|
262
|
-
if (!
|
|
263
|
-
let w =
|
|
276
|
+
OUTPUT $action AS ${c("__action")}, INSERTED.* INTO ${e};`, !0), x = i ? o.provideService(b, this.sql.transactionService, i) : b, S = (await this.runtime.runPromise(x))[0];
|
|
277
|
+
if (!S) throw Error(`MssqlStore.upsert: MERGE returned no row for '${t}'`);
|
|
278
|
+
let w = S.__action, { __action: T, ...E } = S, D = this.decodeWritten(t, E);
|
|
264
279
|
return await this.routeEvent({
|
|
265
280
|
table: t,
|
|
266
281
|
op: w === "INSERT" ? "insert" : "update",
|
|
267
282
|
old: null,
|
|
268
283
|
new: D
|
|
269
|
-
},
|
|
284
|
+
}, a, i, s), D;
|
|
270
285
|
}
|
|
271
286
|
async executeInsertIgnore(e, n, r, i, a, o) {
|
|
272
|
-
n =
|
|
287
|
+
n = V(e, n);
|
|
273
288
|
let s = await this.findByConflict(e, n, r.conflictColumns, i);
|
|
274
289
|
if (s) return {
|
|
275
290
|
row: s,
|
|
@@ -292,7 +307,7 @@ var q = G({ scope: "voltro:mssql" }), J = async (e) => {
|
|
|
292
307
|
}
|
|
293
308
|
async findByConflict(e, t, n, r) {
|
|
294
309
|
if (n.length === 0) return;
|
|
295
|
-
let i = this.sql,
|
|
310
|
+
let i = this.sql, a = n.map((e) => i`${i(e)} = ${t[e]}`), s = i`SELECT TOP 1 * FROM ${i(this.nsT(e))} WHERE ${i.and(a)}`, c = r ? o.provideService(s, this.sql.transactionService, r) : s, l = (await this.runtime.runPromise(c))[0];
|
|
296
311
|
return l ? this.decodeWritten(e, l) : void 0;
|
|
297
312
|
}
|
|
298
313
|
emitChange(e) {
|
|
@@ -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 && X.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) => X.warn("cdc: consumer error", {}, e),
|
|
316
331
|
onResync: () => {
|
|
317
|
-
|
|
332
|
+
X.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 ? (X.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 X.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, X.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 ${N(r(e), "mssql")} ${t ? "WITH CHECK CHECK" : "NOCHECK"} CONSTRAINT ALL`), a = o.acquireUseRelease(o.forEach(e, (e) => i(e, !1), { discard: !0 }), () => o.forEach(e, (e) => n`DELETE FROM ${n(r(e))}`, { discard: !0 }), () => o.orDie(o.ignore(o.forEach(e, (e) => i(e, !0), { discard: !0 })))), s = t === null ? n.withTransaction(a) : o.provideService(a, 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 z({
|
|
415
430
|
...this.txnSpec("MssqlStore.transactional"),
|
|
416
431
|
work: e,
|
|
417
|
-
makeView: (e, t) => new
|
|
432
|
+
makeView: (e, t) => new $(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
|
+
E(e.table) && this.emitter.emit("change", w(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 && X.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
|
+
}, $ = class {
|
|
476
491
|
parent;
|
|
477
492
|
txn;
|
|
478
493
|
attr;
|
|
479
494
|
events = [];
|
|
480
|
-
aborts =
|
|
495
|
+
aborts = k((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 R({
|
|
504
|
+
tracker: this.aborts,
|
|
505
|
+
name: `voltro_sp_${++this.savepointCounter}`,
|
|
506
|
+
spelling: "mssql",
|
|
507
|
+
exec: (e) => this.parent.run(o.provideService(Y.pipe(o.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(j(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,7 @@ 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, S(this.events, (e) => this.parent.emitChange(e)), this.events.length = 0);
|
|
550
573
|
}
|
|
551
574
|
};
|
|
552
|
-
|
|
553
|
-
export { Y as MssqlStore, J as makeMssqlStore };
|
|
575
|
+
export { Q as MssqlStore, Z as makeMssqlStore };
|
package/dist/writeOutput.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mssqlRowResultProjection as e, readMssqlPhysicalColumns as t } from "./rowResultProjection.js";
|
|
2
2
|
import { Effect as n } from "effect";
|
|
3
|
-
|
|
3
|
+
// src/writeOutput.ts
|
|
4
4
|
var r = (r, i, a, o = !1) => n.uninterruptible(n.gen(function* () {
|
|
5
5
|
let n = r.literal("[#voltro_write_output]"), s = yield* t(r, i), c = r.join(", ", !1)(s.map((e) => {
|
|
6
6
|
let t = r.literal(`[${e.name.replaceAll("]", "]]")}]`);
|
|
@@ -14,5 +14,4 @@ var r = (r, i, a, o = !1) => n.uninterruptible(n.gen(function* () {
|
|
|
14
14
|
DROP TABLE ${n};
|
|
15
15
|
`;
|
|
16
16
|
}));
|
|
17
|
-
//#endregion
|
|
18
17
|
export { r as writeOutput };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/sql-mssql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.88.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",
|
|
@@ -33,13 +33,13 @@
|
|
|
33
33
|
"node": ">=24.0.0"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@effect/sql-mssql": "4.0
|
|
37
|
-
"@voltro/database": "0.
|
|
38
|
-
"@voltro/logger": "0.
|
|
39
|
-
"tedious": "20.3.
|
|
36
|
+
"@effect/sql-mssql": "4.1.0",
|
|
37
|
+
"@voltro/database": "0.88.0",
|
|
38
|
+
"@voltro/logger": "0.88.0",
|
|
39
|
+
"tedious": "20.3.8"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"effect": "4.0
|
|
42
|
+
"effect": "4.1.0"
|
|
43
43
|
},
|
|
44
44
|
"publishConfig": {
|
|
45
45
|
"access": "public"
|