@voltro/sql-mssql 0.70.0 → 0.71.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/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ import { DataStore } from '@voltro/database';
9
9
  import { DialectReplicationAdapter } from '@voltro/database';
10
10
  import { Effect } from 'effect';
11
11
  import { EventEmitter } from 'node:events';
12
+ import { InsertIgnoreResult } from '@voltro/database';
12
13
  import { Layer } from 'effect';
13
14
  import { ManagedRuntime } from 'effect';
14
15
  import { MssqlClient } from '@effect/sql-mssql';
@@ -269,6 +270,9 @@ export declare class MssqlStore implements DataStore {
269
270
  insertIgnore(t: string, r: Row, options: {
270
271
  conflictColumns: ReadonlyArray<string>;
271
272
  }): Promise<Readonly<Record<string, unknown>>>;
273
+ insertIgnoreWithOutcome(t: string, r: Row, options: {
274
+ conflictColumns: ReadonlyArray<string>;
275
+ }): Promise<InsertIgnoreResult>;
272
276
  private executeUpsert;
273
277
  /**
274
278
  * Single-statement native MERGE upsert. Builds a parameterised
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
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 ee, compileSelect as S, decodeRowsFromSchema as C, encodeRowForSchema as w, externalChangeEvent as te, hasEagerLoads as ne, isTableReactive as T, jsonPatchAssignments as re, makeEagerFallbackReporter as E, observeDbOp as D, qualifyTable as ie, quoteIdent as ae, raiseChangeListenerCeiling as oe, recordsTable as O, requireTable as se, rowKeyColumns as k, runStoreTransaction as A, runWriteRecorders as j, stampGeneratedId as M, stampGeneratedIds as ce, upsertUpdatePatch as N, upsertUpdateValues as P, withCapturedAttribution as le } from "@voltro/database";
5
- import { EventEmitter as ue } from "node:events";
6
- import { createLogger as F } from "@voltro/logger";
7
- import { SqlClient as I, TransactionConnection as L } from "@effect/sql/SqlClient";
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 C, decodeRowsFromSchema as w, encodeRowForSchema as T, externalChangeEvent as E, hasEagerLoads as ee, isTableReactive as D, jsonPatchAssignments as te, makeEagerFallbackReporter as ne, observeDbOp as O, qualifyTable as k, quoteIdent as re, raiseChangeListenerCeiling as ie, recordsTable as A, requireTable as ae, rowKeyColumns as j, runStoreTransaction as oe, runWriteRecorders as M, stampGeneratedId as N, stampGeneratedIds as se, upsertUpdatePatch as P, upsertUpdateValues as F, withCapturedAttribution as ce } from "@voltro/database";
5
+ import { EventEmitter as le } from "node:events";
6
+ import { createLogger as I } from "@voltro/logger";
7
+ import { SqlClient as L, TransactionConnection as R } from "@effect/sql/SqlClient";
8
8
  //#region src/sqlLayer.ts
9
- var R = {
9
+ var ue = {
10
10
  ...e.defaultParameterTypes,
11
11
  null: t.NVarChar,
12
12
  Date: t.DateTime2,
@@ -18,7 +18,7 @@ var R = {
18
18
  let i = de(t);
19
19
  return e.layerConfig({
20
20
  server: n.succeed(t.server),
21
- parameterTypes: n.succeed(R),
21
+ parameterTypes: n.succeed(ue),
22
22
  ...i === void 0 ? {} : { connectTimeout: n.succeed(r.millis(i)) },
23
23
  ...t.port === void 0 ? {} : { port: n.succeed(t.port) },
24
24
  ...t.database === void 0 ? {} : { database: n.succeed(t.database) },
@@ -83,15 +83,15 @@ var R = {
83
83
  }, W = (e) => _(e).some((e) => {
84
84
  let t = U(e);
85
85
  return t !== void 0 && fe.has(t);
86
- }), pe = /* @__PURE__ */ new Set(["2601", "2627"]), G = (e) => {
86
+ }), pe = /* @__PURE__ */ new Set(["2601", "2627"]), G = (e) => _(e).some((e) => {
87
87
  let t = U(e);
88
88
  return t !== void 0 && pe.has(t);
89
- }, K = (e) => W(e) ? "retry" : "noRetry", me = {
89
+ }), K = (e) => W(e) ? "retry" : "noRetry", me = {
90
90
  I: "insert",
91
91
  U: "update",
92
92
  D: "delete"
93
93
  }, q = (e, t) => e(i.gen(function* () {
94
- let e = yield* I;
94
+ let e = yield* L;
95
95
  if (((yield* e`
96
96
  SELECT COUNT(*) AS ${e("on")}
97
97
  FROM sys.change_tracking_databases
@@ -102,13 +102,13 @@ var R = {
102
102
  )
103
103
  ALTER TABLE ${Y(n)} ENABLE CHANGE_TRACKING WITH (TRACK_COLUMNS_UPDATED = OFF)`);
104
104
  })).then(() => void 0), J = (e) => `'${e.replace(/'/g, "''")}'`, Y = (e) => `[${e.replace(/\]/g, "]]")}]`, X = async (e) => {
105
- let t = F({ scope: "voltro:mssql:cdc" }), n = e.pollIntervalMs ?? 500;
105
+ let t = I({ scope: "voltro:mssql:cdc" }), n = e.pollIntervalMs ?? 500;
106
106
  await q(e.run, e.tables);
107
107
  let r = async () => (await e.run(i.gen(function* () {
108
- return yield* (yield* I)`SELECT CONVERT(VARCHAR(40), CHANGE_TRACKING_CURRENT_VERSION()) AS v`;
108
+ return yield* (yield* L)`SELECT CONVERT(VARCHAR(40), CHANGE_TRACKING_CURRENT_VERSION()) AS v`;
109
109
  })))[0]?.v ?? "0", a = e.startVersion ?? await r(), o = !1, s = null, c = !1, l = (e, t) => BigInt(e) > BigInt(t), u = async (n, o) => {
110
110
  let s = await e.run(i.gen(function* () {
111
- let e = yield* I, t = e.unsafe(Y(n)), r = (yield* e`
111
+ let e = yield* L, t = e.unsafe(Y(n)), r = (yield* e`
112
112
  SELECT CONVERT(VARCHAR(40), CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(${e.unsafe(J(n))}))) AS floor`)[0]?.floor;
113
113
  return r != null && BigInt(o) < BigInt(r) ? {
114
114
  resync: !0,
@@ -137,7 +137,7 @@ var R = {
137
137
  new: null
138
138
  });
139
139
  else {
140
- let t = C([o], n, "mssql")[0];
140
+ let t = w([o], n, "mssql")[0];
141
141
  e.onChange({
142
142
  table: n,
143
143
  op: r,
@@ -178,10 +178,10 @@ var R = {
178
178
  },
179
179
  currentVersion: () => a
180
180
  };
181
- }, Z = F({ scope: "voltro:mssql" }), Q = async (e) => {
181
+ }, Z = I({ scope: "voltro:mssql" }), Q = async (e) => {
182
182
  let t = e.changeStrategy ?? "inline", n = t;
183
183
  t === "cdc" && !e.cdcConfig && (Z.warn("changeStrategy='cdc' requires cdcConfig (replicaId + includeTables); falling back to 'inline'."), n = "inline");
184
- let r = e.tracerLayer ? a.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, i = o.make(r), s = new he(await i.runPromise(I), i, n);
184
+ let r = e.tracerLayer ? a.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, i = o.make(r), s = new he(await i.runPromise(L), i, n);
185
185
  return n === "cdc" && e.cdcConfig && await s.startCdcConsumer(e.cdcConfig), s;
186
186
  }, he = class e {
187
187
  sql;
@@ -190,14 +190,14 @@ var R = {
190
190
  namespace;
191
191
  emitter;
192
192
  inflightTxns = 0;
193
- reportEagerFallback = E(Z);
193
+ reportEagerFallback = ne(Z);
194
194
  cdcHandle = null;
195
195
  cdcCheckpointTimer = null;
196
196
  cdcPendingVersion = null;
197
197
  cdcReplicaId = "";
198
198
  cdcStreamName = "default";
199
199
  constructor(e, t, n = "inline", r = null, i) {
200
- this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new ue(), oe(this.emitter);
200
+ this.sql = e, this.runtime = t, this.changeStrategy = n, this.namespace = r, this.emitter = i ?? new le(), ie(this.emitter);
201
201
  }
202
202
  get inlineEmit() {
203
203
  return this.changeStrategy === "inline";
@@ -206,19 +206,19 @@ var R = {
206
206
  return t === this.namespace ? this : new e(this.sql, this.runtime, this.changeStrategy, t, this.emitter);
207
207
  }
208
208
  nsT(e) {
209
- return ie(this.namespace, e);
209
+ return k(this.namespace, e);
210
210
  }
211
211
  __mssqlReplicationFriend = { runEffect: (e) => this.runtime.runPromise(e) };
212
212
  async executeQuery(e, t) {
213
- let n = S(e, this.sql, this.namespace), r = t ? i.provideService(n, L, t) : n, a = await D("mssql", "select", () => this.runtime.runPromise(r));
214
- return C(a, e.table, "mssql");
213
+ let n = C(e, this.sql, this.namespace), r = t ? i.provideService(n, R, t) : n, a = await O("mssql", "select", () => this.runtime.runPromise(r));
214
+ return w(a, e.table, "mssql");
215
215
  }
216
216
  decodeWritten(e, t) {
217
- return C([t], e, "mssql")[0] ?? t;
217
+ return w([t], e, "mssql")[0] ?? t;
218
218
  }
219
219
  async executeInsert(e, t, n, r, a) {
220
- t = M(e, t);
221
- let o = this.sql, s = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(w(t, e)).returning("*")}`, c = n ? i.provideService(s, L, n) : s, l = (await this.runtime.runPromise(c))[0];
220
+ t = N(e, t);
221
+ let o = this.sql, s = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(T(t, e)).returning("*")}`, c = n ? i.provideService(s, R, n) : s, l = (await this.runtime.runPromise(c))[0];
222
222
  if (!l) throw Error(`MssqlStore.insert: row not returned post-insert in '${e}'`);
223
223
  let u = this.decodeWritten(e, l);
224
224
  return await this.routeEvent({
@@ -229,7 +229,7 @@ var R = {
229
229
  }, r, n, a), u;
230
230
  }
231
231
  async executeUpdate(e, t, n, r, a, o) {
232
- let s = this.sql, c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(w(n, e)).returning("*")} WHERE ${s.and(k(t).map(([e, t]) => s`${s(e)} = ${t}`))}`, l = r ? i.provideService(c, L, r) : c, u = (await this.runtime.runPromise(l))[0];
232
+ let s = this.sql, c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(T(n, e)).returning("*")} WHERE ${s.and(j(t).map(([e, t]) => s`${s(e)} = ${t}`))}`, l = r ? i.provideService(c, R, r) : c, u = (await this.runtime.runPromise(l))[0];
233
233
  if (!u) return null;
234
234
  let d = this.decodeWritten(e, u);
235
235
  return await this.routeEvent({
@@ -240,36 +240,38 @@ var R = {
240
240
  }, a, r, o), d;
241
241
  }
242
242
  async executeInsertMany(e, t, n, r, a) {
243
- if (t = ce(e, t), t.length === 0) return [];
244
- let o = this.sql, s = v(t, g("mssql")), c = (t) => o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t.map((t) => w(t, e))).returning("*")}`, l;
243
+ if (t = se(e, t), t.length === 0) return [];
244
+ let o = this.sql, s = v(t, g("mssql")), c = (t) => o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t.map((t) => T(t, e))).returning("*")}`, l;
245
245
  if (s.length === 1) {
246
- let e = c(s[0]), t = n ? i.provideService(e, L, n) : e;
246
+ let e = c(s[0]), t = n ? i.provideService(e, R, n) : e;
247
247
  l = await this.runtime.runPromise(t);
248
248
  } else if (n) {
249
249
  let e = [];
250
- for (let t of s) e.push(...await this.runtime.runPromise(i.provideService(c(t), L, n)));
250
+ for (let t of s) e.push(...await this.runtime.runPromise(i.provideService(c(t), R, n)));
251
251
  l = e;
252
252
  } else l = await this.runtime.runPromise(o.withTransaction(i.map(i.forEach(s, c, { concurrency: 1 }), (e) => e.flat())));
253
- let u = t.map((e) => e.id), d = new Map(C(l, e, "mssql").map((e) => [e.id, e])), f = u.map((e) => d.get(e)).filter((e) => e !== void 0), p = f.length === l.length ? f : [...l];
254
- for (let t of p) await this.routeEvent({
253
+ let u = t.map((e) => e.id), d = w(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;
254
+ for (let t of m) await this.routeEvent({
255
255
  table: e,
256
256
  op: "insert",
257
257
  old: null,
258
258
  new: t
259
259
  }, r, n, a);
260
- return p;
260
+ return m;
261
261
  }
262
262
  async executePatchJson(e, t, n, r, a, o, s, c) {
263
- let l = this.sql, u = w(re(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(k(t).map(([e, t]) => l`${l(e)} = ${t}`))}`, p = a ? i.provideService(f, L, a) : f, m = (await this.runtime.runPromise(p))[0];
264
- return m ? (await this.routeEvent({
263
+ let l = this.sql, u = T(te(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(j(t).map(([e, t]) => l`${l(e)} = ${t}`))}`, p = a ? i.provideService(f, R, a) : f, m = (await this.runtime.runPromise(p))[0];
264
+ if (!m) return null;
265
+ let h = this.decodeWritten(e, m);
266
+ return await this.routeEvent({
265
267
  table: e,
266
268
  op: "update",
267
269
  old: null,
268
- new: m
269
- }, o, a, s), m) : null;
270
+ new: h
271
+ }, o, a, s), h;
270
272
  }
271
273
  async executeDelete(e, t, n, r, a) {
272
- let o = this.sql, s = o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* WHERE ${o.and(k(t).map(([e, t]) => o`${o(e)} = ${t}`))}`, c = n ? i.provideService(s, L, n) : s, l = (await this.runtime.runPromise(c))[0];
274
+ let o = this.sql, s = o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* WHERE ${o.and(j(t).map(([e, t]) => o`${o(e)} = ${t}`))}`, c = n ? i.provideService(s, R, n) : s, l = (await this.runtime.runPromise(c))[0];
273
275
  if (!l) return !1;
274
276
  let u = this.decodeWritten(e, l);
275
277
  return await this.routeEvent({
@@ -280,18 +282,18 @@ var R = {
280
282
  }, r, n, a), !0;
281
283
  }
282
284
  async appendInTxn(e, t, n) {
283
- let r = this.sql, a = r`INSERT INTO ${r(this.nsT(e))} ${r.insert(w(t, e))}`;
284
- await this.runtime.runPromise(n ? i.provideService(a, L, n) : a);
285
+ let r = this.sql, a = r`INSERT INTO ${r(this.nsT(e))} ${r.insert(T(t, e))}`;
286
+ await this.runtime.runPromise(n ? i.provideService(a, R, n) : a);
285
287
  }
286
288
  async maxInTxn(e, t, n, r) {
287
- 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, L, r) : s))[0]?.m;
289
+ 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, R, r) : s))[0]?.m;
288
290
  return c == null ? null : Number(c);
289
291
  }
290
292
  async routeEvent(e, t, n = null, r) {
291
293
  e = {
292
294
  ...h(r),
293
295
  ...e
294
- }, O(e.table) && await j({
296
+ }, A(e.table) && await M({
295
297
  append: (e, t) => this.appendInTxn(e, t, n),
296
298
  maxOf: (e, t, r) => this.maxInTxn(e, t, r, n)
297
299
  }, {
@@ -301,7 +303,7 @@ var R = {
301
303
  prev: e.old,
302
304
  traceId: e.traceId,
303
305
  subjectId: e.subjectId
304
- }), T(e.table) && (t === null ? this.inlineEmit && this.emitter.emit("change", e) : t.push(e));
306
+ }), D(e.table) && (t === null ? this.inlineEmit && this.emitter.emit("change", e) : t.push(e));
305
307
  }
306
308
  query(e) {
307
309
  return this.runWithEager(e, null);
@@ -310,14 +312,14 @@ var R = {
310
312
  return this.rawOn(e, null);
311
313
  }
312
314
  rawOn(e, t) {
313
- let n = ee(e, this.sql), r = t ? i.provideService(n, L, t) : n;
314
- return D("mssql", "raw", () => this.runtime.runPromise(r));
315
+ let n = S(e, this.sql), r = t ? i.provideService(n, R, t) : n;
316
+ return O("mssql", "raw", () => this.runtime.runPromise(r));
315
317
  }
316
318
  async runWithEager(e, t) {
317
- if (!ne(e)) return this.executeQuery(e, t);
319
+ if (!ee(e)) return this.executeQuery(e, t);
318
320
  let n = this.namespace === null ? y(e, this.sql, "mssql") : null;
319
321
  if (n !== null) try {
320
- let e = t ? i.provideService(n.fragment, L, t) : n.fragment, r = await D("mssql", "select", () => this.runtime.runPromise(e));
322
+ let e = t ? i.provideService(n.fragment, R, t) : n.fragment, r = await O("mssql", "select", () => this.runtime.runPromise(e));
321
323
  return n.decode(r);
322
324
  } catch (t) {
323
325
  if (t instanceof d) throw t;
@@ -334,17 +336,17 @@ var R = {
334
336
  reason: "not-compilable"
335
337
  });
336
338
  let r = await this.executeQuery(e, t);
337
- return m(r, e.eager, e.sourceTable ?? se(e.table), (e) => this.executeQuery(e, t));
339
+ return m(r, e.eager, e.sourceTable ?? ae(e.table), (e) => this.executeQuery(e, t));
338
340
  }
339
341
  getInternalRunWithEager() {
340
342
  return this.runWithEager.bind(this);
341
343
  }
342
344
  localWrite(e, t, n) {
343
- let r = (e) => O(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
344
- return D("mssql", e, () => le(r));
345
+ let r = (e) => A(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
346
+ return O("mssql", e, () => ce(r));
345
347
  }
346
348
  async writeWithRecorders(e, t) {
347
- let n = [], r = this.sql, a = await this.runtime.runPromise(r.withTransaction(i.flatMap(i.serviceOption(L), (r) => s.isNone(r) ? i.fail(/* @__PURE__ */ Error("MssqlStore.write: TransactionConnection missing.")) : i.tryPromise({
349
+ let n = [], r = this.sql, a = await this.runtime.runPromise(r.withTransaction(i.flatMap(i.serviceOption(R), (r) => s.isNone(r) ? i.fail(/* @__PURE__ */ Error("MssqlStore.write: TransactionConnection missing.")) : i.tryPromise({
348
350
  try: () => e(t, r.value, n),
349
351
  catch: (e) => e
350
352
  }))));
@@ -373,8 +375,8 @@ var R = {
373
375
  return this.executeDeleteMany(e, t, null, null);
374
376
  }
375
377
  async executeUpdateMany(e, t, n, r, a, o) {
376
- let s = this.sql, c = x(n.where, s, this.namespace), l = s`UPDATE ${s(this.nsT(e))} SET ${s.update(w(t, e))} OUTPUT INSERTED.* WHERE ${c}`, u = r ? i.provideService(l, L, r) : l, d = await D("mssql", "update", () => this.runtime.runPromise(u));
377
- for (let t of d) await this.routeEvent({
378
+ let s = this.sql, c = x(n.where, s, this.namespace), l = s`UPDATE ${s(this.nsT(e))} SET ${s.update(T(t, e))} OUTPUT INSERTED.* WHERE ${c}`, u = r ? i.provideService(l, R, r) : l, d = await O("mssql", "update", () => this.runtime.runPromise(u));
379
+ for (let t of w(d, e, "mssql")) await this.routeEvent({
378
380
  table: e,
379
381
  op: "update",
380
382
  old: null,
@@ -383,8 +385,8 @@ var R = {
383
385
  return d.length;
384
386
  }
385
387
  async executeDeleteMany(e, t, n, r, a) {
386
- let o = this.sql, s = x(t.where, o, this.namespace), c = o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* WHERE ${s}`, l = n ? i.provideService(c, L, n) : c, u = await D("mssql", "delete", () => this.runtime.runPromise(l));
387
- for (let t of u) await this.routeEvent({
388
+ let o = this.sql, s = x(t.where, o, this.namespace), c = o`DELETE FROM ${o(this.nsT(e))} OUTPUT DELETED.* WHERE ${s}`, l = n ? i.provideService(c, R, n) : c, u = await O("mssql", "delete", () => this.runtime.runPromise(l));
389
+ for (let t of w(u, e, "mssql")) await this.routeEvent({
388
390
  table: e,
389
391
  op: "delete",
390
392
  old: t,
@@ -396,61 +398,73 @@ var R = {
396
398
  return this.localWrite("upsert", e, (r, i, a) => this.executeUpsert(e, t, n, i, a, r));
397
399
  }
398
400
  insertIgnore(e, t, n) {
401
+ return this.insertIgnoreWithOutcome(e, t, n).then((e) => e.row);
402
+ }
403
+ insertIgnoreWithOutcome(e, t, n) {
399
404
  return this.localWrite("upsert", e, (r, i, a) => this.executeInsertIgnore(e, t, n, i, a, r));
400
405
  }
401
406
  async executeUpsert(e, t, n, r, i, a) {
402
- if (P(n), t = M(e, t), typeof n.update != "function" && n.conflictColumns.length > 0) return this.mergeUpsert(e, t, {
407
+ if (F(n), t = N(e, t), typeof n.update != "function" && n.conflictColumns.length > 0) return this.mergeUpsert(e, t, {
403
408
  conflictColumns: n.conflictColumns,
404
409
  ...n.update === void 0 ? {} : { update: n.update },
405
410
  ...n.updateValues === void 0 ? {} : { updateValues: n.updateValues }
406
- }, r, i);
411
+ }, r, i, a);
407
412
  let o = await this.findByConflict(e, t, n.conflictColumns, r);
408
- if (o) return await this.executeUpdate(e, o.id, N(t, o, n), r, i) ?? o;
413
+ if (o) return await this.executeUpdate(e, o.id, P(t, o, n), r, i, a) ?? o;
409
414
  try {
410
- return await this.executeInsert(e, t, r, i);
411
- } catch (a) {
412
- if (!G(a)) throw a;
413
- let o = await this.findByConflict(e, t, n.conflictColumns, r);
414
- if (!o) throw a;
415
- return await this.executeUpdate(e, o.id, N(t, o, n), r, i) ?? o;
415
+ return await this.executeInsert(e, t, r, i, a);
416
+ } catch (o) {
417
+ if (!G(o)) throw o;
418
+ let s = await this.findByConflict(e, t, n.conflictColumns, r);
419
+ if (!s) throw o;
420
+ return await this.executeUpdate(e, s.id, P(t, s, n), r, i, a) ?? s;
416
421
  }
417
422
  }
418
- async mergeUpsert(e, t, n, r, a) {
419
- let o = this.sql, s = Object.keys(t), c = Array.isArray(n.update) ? n.update.filter((e) => s.includes(e)) : s.filter((e) => e !== "id" && !n.conflictColumns.includes(e)), l = w(t, e), u = s.map((e) => o`${l[e]}`), d = s.map((e) => o`${o(e)}`), f = n.conflictColumns.map((e) => o`tgt.${o(e)} = src.${o(e)}`), p = s.map((e) => o`${o(e)}`), m = s.map((e) => o`src.${o(e)}`), h = P(n), g = w(h, e), _ = [...c.filter((e) => !Object.hasOwn(h, e)).map((e) => o`tgt.${o(e)} = src.${o(e)}`), ...Object.entries(g).map(([e, t]) => o`tgt.${o(e)} = ${t}`)];
420
- _.length === 0 && _.push(o`tgt.${o(n.conflictColumns[0])} = src.${o(n.conflictColumns[0])}`);
421
- let v = o`
422
- MERGE ${o(this.nsT(e))} WITH (HOLDLOCK) AS tgt
423
- USING (VALUES (${o.csv(u)})) AS src (${o.csv(d)})
424
- ON ${o.and(f)}
425
- WHEN MATCHED THEN UPDATE SET ${o.csv(_)}
426
- WHEN NOT MATCHED THEN INSERT (${o.csv(p)}) VALUES (${o.csv(m)})
427
- OUTPUT $action AS ${o("__action")}, INSERTED.*;`, y = r ? i.provideService(v, L, r) : v, b = (await this.runtime.runPromise(y))[0];
428
- if (!b) throw Error(`MssqlStore.upsert: MERGE returned no row for '${e}'`);
429
- let x = b.__action, { __action: ee, ...S } = b, C = this.decodeWritten(e, S);
430
- return this.routeEvent({
423
+ async mergeUpsert(e, t, n, r, a, o) {
424
+ 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 = T(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 = F(n), _ = T(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}`)];
425
+ v.length === 0 && v.push(s`tgt.${s(n.conflictColumns[0])} = src.${s(n.conflictColumns[0])}`);
426
+ let y = s`
427
+ MERGE ${s(this.nsT(e))} WITH (HOLDLOCK) AS tgt
428
+ USING (VALUES (${s.csv(d)})) AS src (${s.csv(f)})
429
+ ON ${s.and(p)}
430
+ WHEN MATCHED THEN UPDATE SET ${s.csv(v)}
431
+ WHEN NOT MATCHED THEN INSERT (${s.csv(m)}) VALUES (${s.csv(h)})
432
+ OUTPUT $action AS ${s("__action")}, INSERTED.*;`, b = r ? i.provideService(y, R, r) : y, x = (await this.runtime.runPromise(b))[0];
433
+ if (!x) throw Error(`MssqlStore.upsert: MERGE returned no row for '${e}'`);
434
+ let S = x.__action, { __action: C, ...w } = x, E = this.decodeWritten(e, w);
435
+ return await this.routeEvent({
431
436
  table: e,
432
- op: x === "INSERT" ? "insert" : "update",
437
+ op: S === "INSERT" ? "insert" : "update",
433
438
  old: null,
434
- new: C
435
- }, a), C;
439
+ new: E
440
+ }, a, r, o), E;
436
441
  }
437
442
  async executeInsertIgnore(e, t, n, r, i, a) {
438
- t = M(e, t);
443
+ t = N(e, t);
439
444
  let o = await this.findByConflict(e, t, n.conflictColumns, r);
440
- if (o) return o;
445
+ if (o) return {
446
+ row: o,
447
+ outcome: "ignored"
448
+ };
441
449
  try {
442
- return await this.executeInsert(e, t, r, i);
450
+ return {
451
+ row: await this.executeInsert(e, t, r, i, a),
452
+ outcome: "inserted"
453
+ };
443
454
  } catch (i) {
444
455
  if (!G(i)) throw i;
445
456
  let a = await this.findByConflict(e, t, n.conflictColumns, r);
446
457
  if (!a) throw i;
447
- return a;
458
+ return {
459
+ row: a,
460
+ outcome: "ignored"
461
+ };
448
462
  }
449
463
  }
450
464
  async findByConflict(e, t, n, r) {
451
465
  if (n.length === 0) return;
452
- 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, L, r) : s;
453
- return (await this.runtime.runPromise(c))[0];
466
+ 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, R, r) : s, l = (await this.runtime.runPromise(c))[0];
467
+ return l ? this.decodeWritten(e, l) : void 0;
454
468
  }
455
469
  emitChange(e) {
456
470
  this.emitter.emit("change", e);
@@ -562,13 +576,13 @@ var R = {
562
576
  }
563
577
  async emptyTablesOn(e, t) {
564
578
  if (e.length === 0) return;
565
- let n = this.sql, r = (e) => this.nsT(e), a = (e, t) => n.unsafe(`ALTER TABLE ${ae(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, L, t);
579
+ let n = this.sql, r = (e) => this.nsT(e), a = (e, t) => n.unsafe(`ALTER TABLE ${re(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, R, t);
566
580
  await this.runtime.runPromise(s);
567
581
  }
568
582
  async transactional(e) {
569
583
  this.inflightTxns++;
570
584
  try {
571
- return await A({
585
+ return await oe({
572
586
  ...this.txnSpec("MssqlStore.transactional"),
573
587
  work: e,
574
588
  makeView: (e, t) => new ge(this, e, t)
@@ -602,7 +616,7 @@ var R = {
602
616
  return this.changeStrategy === "cdc" ? "fleet" : "local";
603
617
  }
604
618
  injectExternalChange(e) {
605
- T(e.table) && this.emitter.emit("change", te(e));
619
+ D(e.table) && this.emitter.emit("change", E(e));
606
620
  }
607
621
  run(e) {
608
622
  return this.runtime.runPromise(e);
@@ -668,6 +682,9 @@ var R = {
668
682
  return this.parent.getInternalExecuteUpsert()(e, t, n, this.txn, this.events, this.attr);
669
683
  }
670
684
  insertIgnore(e, t, n) {
685
+ return this.insertIgnoreWithOutcome(e, t, n).then((e) => e.row);
686
+ }
687
+ insertIgnoreWithOutcome(e, t, n) {
671
688
  return this.parent.getInternalExecuteInsertIgnore()(e, t, n, this.txn, this.events, this.attr);
672
689
  }
673
690
  transactional(e) {
@@ -691,7 +708,7 @@ var R = {
691
708
  let t = $(e);
692
709
  if (t === null) throw Error("mssqlReplicationAdapter: primary is not an MssqlStore (missing __mssqlReplicationFriend).");
693
710
  return t.runEffect(i.gen(function* () {
694
- return (yield* (yield* I)`
711
+ return (yield* (yield* L)`
695
712
  SELECT CONVERT(VARCHAR(40), end_of_log_lsn) AS lsn
696
713
  FROM sys.dm_hadr_database_replica_states
697
714
  WHERE database_id = DB_ID()
@@ -704,7 +721,7 @@ var R = {
704
721
  let t = $(e);
705
722
  if (t === null) throw Error("mssqlReplicationAdapter: replica is not an MssqlStore.");
706
723
  return t.runEffect(i.gen(function* () {
707
- return (yield* (yield* I)`
724
+ return (yield* (yield* L)`
708
725
  SELECT CONVERT(VARCHAR(40), last_hardened_lsn) AS lsn
709
726
  FROM sys.dm_hadr_database_replica_states
710
727
  WHERE database_id = DB_ID()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/sql-mssql",
3
- "version": "0.70.0",
3
+ "version": "0.71.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.70.0",
39
- "@voltro/logger": "0.70.0",
38
+ "@voltro/database": "0.71.0",
39
+ "@voltro/logger": "0.71.0",
40
40
  "tedious": "18.6.2"
41
41
  },
42
42
  "peerDependencies": {