orez-lite 0.13.0 → 0.13.1
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/cf-do/lite-data-worker.d.ts +1 -0
- package/dist/cf-do/lite-data-worker.d.ts.map +1 -1
- package/dist/cf-do/lite-data-worker.js.map +1 -1
- package/dist/cf-do/tx-journal.d.ts +13 -11
- package/dist/cf-do/tx-journal.d.ts.map +1 -1
- package/dist/cf-do/tx-journal.js +13 -11
- package/dist/cf-do/tx-journal.js.map +1 -1
- package/dist/cf-do/worker.d.ts +42 -1
- package/dist/cf-do/worker.d.ts.map +1 -1
- package/dist/cf-do/worker.js +197 -32
- package/dist/cf-do/worker.js.map +1 -1
- package/dist/do-sql-tracking.d.ts +4 -4
- package/dist/do-sql-tracking.js +4 -4
- package/package.json +4 -4
package/dist/cf-do/worker.js
CHANGED
|
@@ -18,6 +18,7 @@ const SCHEMA_PROVISIONING_WAIT_MS = 20_000;
|
|
|
18
18
|
const SCHEMA_PROVISIONING_MAX_DELAY_MS = 500;
|
|
19
19
|
const APPLICATION_SQL_TURN_WAIT_MS = 30_000;
|
|
20
20
|
const WRITE_GRANT_WAIT_SAMPLE_CAPACITY = 4_096;
|
|
21
|
+
const DEFAULT_SQL_TELEMETRY_SAMPLE_RATE = 0.01;
|
|
21
22
|
const DEFAULT_SNAPSHOT_PAGE_ROWS = 2_000;
|
|
22
23
|
const MAX_SNAPSHOT_PAGE_ROWS = 10_000;
|
|
23
24
|
const TRANSACTION_CONTROL_SQL = /^\s*(?:BEGIN|COMMIT|ROLLBACK|SAVEPOINT|RELEASE)(?=\s|;|$)/i;
|
|
@@ -61,6 +62,12 @@ function positiveEnvInteger(value, fallback) {
|
|
|
61
62
|
const parsed = Number(value);
|
|
62
63
|
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : fallback;
|
|
63
64
|
}
|
|
65
|
+
function probabilityEnv(value, fallback) {
|
|
66
|
+
if (value === undefined)
|
|
67
|
+
return fallback;
|
|
68
|
+
const parsed = Number(value);
|
|
69
|
+
return Number.isFinite(parsed) && parsed >= 0 && parsed <= 1 ? parsed : fallback;
|
|
70
|
+
}
|
|
64
71
|
function quoteIdent(name) {
|
|
65
72
|
return `"${name.replace(/"/g, '""')}"`;
|
|
66
73
|
}
|
|
@@ -137,14 +144,17 @@ class ApplicationSqlSessionTarget extends RpcTarget {
|
|
|
137
144
|
sessionID;
|
|
138
145
|
readOnly;
|
|
139
146
|
priority;
|
|
147
|
+
telemetry;
|
|
140
148
|
state = 'created';
|
|
141
149
|
mutated = false;
|
|
142
|
-
|
|
150
|
+
telemetryFinished = false;
|
|
151
|
+
constructor(owner, sessionID, readOnly, priority, telemetry) {
|
|
143
152
|
super();
|
|
144
153
|
this.owner = owner;
|
|
145
154
|
this.sessionID = sessionID;
|
|
146
155
|
this.readOnly = readOnly;
|
|
147
156
|
this.priority = priority;
|
|
157
|
+
this.telemetry = telemetry;
|
|
148
158
|
}
|
|
149
159
|
begin() {
|
|
150
160
|
return this.owner[APPLICATION_SQL_ACQUIRE](this);
|
|
@@ -182,6 +192,7 @@ export class ZeroDO extends DurableObject {
|
|
|
182
192
|
sqlStatements: 0,
|
|
183
193
|
};
|
|
184
194
|
sqlBillingSinceBoot = { rowsRead: 0, rowsWritten: 0 };
|
|
195
|
+
sqlTelemetrySampleRate;
|
|
185
196
|
writeGrantWaitMs = new RecentLatencySamples(WRITE_GRANT_WAIT_SAMPLE_CAPACITY);
|
|
186
197
|
sql;
|
|
187
198
|
watermarks;
|
|
@@ -205,6 +216,56 @@ export class ZeroDO extends DurableObject {
|
|
|
205
216
|
objectName: typeof this.ctx.id.name === 'string' ? this.ctx.id.name : null,
|
|
206
217
|
};
|
|
207
218
|
}
|
|
219
|
+
startSqlTelemetrySample() {
|
|
220
|
+
if (this.sqlTelemetrySampleRate <= 0 ||
|
|
221
|
+
(this.sqlTelemetrySampleRate < 1 && Math.random() >= this.sqlTelemetrySampleRate)) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
startedAt: performance.now(),
|
|
226
|
+
admittedAt: null,
|
|
227
|
+
rowsReturned: 0,
|
|
228
|
+
rowsChanged: 0,
|
|
229
|
+
statements: 0,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
recordSqlTelemetry(sample, result) {
|
|
233
|
+
sample.rowsReturned += result.rows.length;
|
|
234
|
+
sample.rowsChanged += result.changes;
|
|
235
|
+
}
|
|
236
|
+
emitSqlTelemetry(event, name, outcome, sample, error) {
|
|
237
|
+
if (!sample)
|
|
238
|
+
return;
|
|
239
|
+
try {
|
|
240
|
+
console.log(JSON.stringify({
|
|
241
|
+
event,
|
|
242
|
+
name: name.slice(0, 200),
|
|
243
|
+
outcome,
|
|
244
|
+
durationMs: Math.round((performance.now() - sample.startedAt) * 1_000) / 1_000,
|
|
245
|
+
...(sample.admittedAt === null
|
|
246
|
+
? null
|
|
247
|
+
: {
|
|
248
|
+
queueMs: Math.round((sample.admittedAt - sample.startedAt) * 1_000) / 1_000,
|
|
249
|
+
}),
|
|
250
|
+
rowsReturned: sample.rowsReturned,
|
|
251
|
+
rowsChanged: sample.rowsChanged,
|
|
252
|
+
statements: sample.statements,
|
|
253
|
+
sampleRate: this.sqlTelemetrySampleRate,
|
|
254
|
+
...(error
|
|
255
|
+
? {
|
|
256
|
+
errorName: (error instanceof Error ? error.name : typeof error).slice(0, 100),
|
|
257
|
+
}
|
|
258
|
+
: null),
|
|
259
|
+
}));
|
|
260
|
+
}
|
|
261
|
+
catch { }
|
|
262
|
+
}
|
|
263
|
+
finishApplicationSqlTelemetry(session, outcome, error) {
|
|
264
|
+
if (session.telemetryFinished)
|
|
265
|
+
return;
|
|
266
|
+
session.telemetryFinished = true;
|
|
267
|
+
this.emitSqlTelemetry('orez_sql_transaction_sample', session.readOnly ? 'application_sql_read' : 'application_sql_write', outcome, session.telemetry, error);
|
|
268
|
+
}
|
|
208
269
|
recordWriteBudgetRows(rows, statement) {
|
|
209
270
|
const wasTripped = this.writeBudget.status().tripped;
|
|
210
271
|
try {
|
|
@@ -291,6 +352,7 @@ export class ZeroDO extends DurableObject {
|
|
|
291
352
|
this.sql = ctx.storage.sql;
|
|
292
353
|
this.writeBudgetDisabled = /^(?:1|true)$/i.test(env.OREZ_DO_WRITE_BUDGET_DISABLED ?? '');
|
|
293
354
|
this.writeBudgetAdminToken = env.OREZ_DO_WRITE_BUDGET_ADMIN_TOKEN;
|
|
355
|
+
this.sqlTelemetrySampleRate = probabilityEnv(env.OREZ_SQL_TELEMETRY_SAMPLE_RATE, DEFAULT_SQL_TELEMETRY_SAMPLE_RATE);
|
|
294
356
|
this.writeBudget = new RollingRowWriteBudget({
|
|
295
357
|
budgetRows: positiveEnvInteger(env.OREZ_DO_WRITE_BUDGET_ROWS, DEFAULT_WRITE_BUDGET_ROWS),
|
|
296
358
|
windowMs: positiveEnvInteger(env.OREZ_DO_WRITE_BUDGET_WINDOW_MS, DEFAULT_WRITE_BUDGET_WINDOW_MS),
|
|
@@ -339,6 +401,10 @@ export class ZeroDO extends DurableObject {
|
|
|
339
401
|
});
|
|
340
402
|
if (recovered.length)
|
|
341
403
|
this.invalidateSchemaCaches();
|
|
404
|
+
// after recovery, which may still restore journal rows or re-create the
|
|
405
|
+
// residual triggers from a pre-cleanup schema snapshot, and before the
|
|
406
|
+
// trip restore, so the one-time drops run against a fresh write budget.
|
|
407
|
+
this.dropZeroHttpJournalResidue();
|
|
342
408
|
if (!this.writeBudgetDisabled) {
|
|
343
409
|
const persisted = await ctx.storage.get(WRITE_BUDGET_TRIPPED_KEY);
|
|
344
410
|
if (persisted) {
|
|
@@ -349,6 +415,66 @@ export class ZeroDO extends DurableObject {
|
|
|
349
415
|
}
|
|
350
416
|
});
|
|
351
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* Drop what the retired zero-http full-projection engine left in this
|
|
420
|
+
* database. That engine's mount installed `_zsync_tr_<table>_{i,u,d}` AFTER
|
|
421
|
+
* triggers on every synced table, appending a change envelope to
|
|
422
|
+
* `_zsync_changes` per write plus a `_zsync_meta` marker row per UPDATE. The
|
|
423
|
+
* engine was deleted on 2026-07-29, its drop logic with it, and nothing has
|
|
424
|
+
* read either table since the packed ledger replaced that pull path. The
|
|
425
|
+
* triggers stayed installed, though, so every synced write on a namespace
|
|
426
|
+
* mounted before the deletion still paid one or two billable journal rows
|
|
427
|
+
* forever (86,082 rows and ~2,600/day measured on the largest production
|
|
428
|
+
* namespace).
|
|
429
|
+
*
|
|
430
|
+
* Order matters for crash safety, and every step is idempotent:
|
|
431
|
+
*
|
|
432
|
+
* 1. preserve the journal's high watermark in `_zsync_watermark`, which
|
|
433
|
+
* `initializePackedLedger` already consults, so a namespace whose packed
|
|
434
|
+
* ledger has not initialized yet still seeds above every cookie it ever
|
|
435
|
+
* issued after the journal is gone;
|
|
436
|
+
* 2. drop every trigger whose body references `_zsync_changes`; `_zsync_*`
|
|
437
|
+
* is orez's reserved namespace, so no application trigger can
|
|
438
|
+
* legitimately write it;
|
|
439
|
+
* 3. drop both tables and the journal's rollback-capture registration.
|
|
440
|
+
*
|
|
441
|
+
* Steady state costs one sqlite_master read per boot.
|
|
442
|
+
*/
|
|
443
|
+
dropZeroHttpJournalResidue() {
|
|
444
|
+
const residue = this.sql
|
|
445
|
+
.exec('SELECT name, type FROM sqlite_master ' +
|
|
446
|
+
"WHERE (type = 'trigger' AND sql LIKE '%\\_zsync\\_changes%' ESCAPE '\\') " +
|
|
447
|
+
`OR (type = 'table' AND name IN ('${ZSYNC_CHANGES_TABLE}', '_zsync_meta'))`)
|
|
448
|
+
.toArray()
|
|
449
|
+
.map((row) => ({ name: String(row.name), type: String(row.type) }));
|
|
450
|
+
if (residue.length === 0)
|
|
451
|
+
return;
|
|
452
|
+
if (residue.some((row) => row.type === 'table' && row.name === ZSYNC_CHANGES_TABLE)) {
|
|
453
|
+
const high = Number(this.sql
|
|
454
|
+
.exec(`SELECT COALESCE(MAX(watermark), 0) AS high FROM ${quoteIdent(ZSYNC_CHANGES_TABLE)}`)
|
|
455
|
+
.toArray()[0]?.high ?? 0);
|
|
456
|
+
if (high > 0) {
|
|
457
|
+
this.sql.exec('CREATE TABLE IF NOT EXISTS _zsync_watermark (' +
|
|
458
|
+
'lock INTEGER PRIMARY KEY CHECK (lock = 1), high INTEGER NOT NULL)');
|
|
459
|
+
this.sql.exec('INSERT INTO _zsync_watermark (lock, high) VALUES (1, ?) ' +
|
|
460
|
+
'ON CONFLICT (lock) DO UPDATE SET high = MAX(high, excluded.high)', high);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
for (const row of residue) {
|
|
464
|
+
if (row.type === 'trigger') {
|
|
465
|
+
this.sql.exec(`DROP TRIGGER IF EXISTS ${quoteIdent(row.name)}`);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
this.sql.exec(`DROP TABLE IF EXISTS ${quoteIdent(ZSYNC_CHANGES_TABLE)}`);
|
|
469
|
+
this.sql.exec('DROP TABLE IF EXISTS _zsync_meta');
|
|
470
|
+
const cdcRegistry = this.sql
|
|
471
|
+
.exec("SELECT 1 AS ok FROM sqlite_master WHERE type = 'table' AND name = '_orez_cdc_tables' LIMIT 1")
|
|
472
|
+
.toArray();
|
|
473
|
+
if (cdcRegistry.length > 0) {
|
|
474
|
+
this.sql.exec('DELETE FROM _orez_cdc_tables WHERE physical_table = ?', ZSYNC_CHANGES_TABLE);
|
|
475
|
+
this.cdc.reload();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
352
478
|
async fetch(request) {
|
|
353
479
|
this.requestsSinceBoot.fetch++;
|
|
354
480
|
const url = new URL(request.url);
|
|
@@ -1138,6 +1264,9 @@ export class ZeroDO extends DurableObject {
|
|
|
1138
1264
|
this.applicationSqlQueue.shift();
|
|
1139
1265
|
clearTimeout(waiter.timer);
|
|
1140
1266
|
waiter.session.state = 'active';
|
|
1267
|
+
if (waiter.session.telemetry) {
|
|
1268
|
+
waiter.session.telemetry.admittedAt = performance.now();
|
|
1269
|
+
}
|
|
1141
1270
|
if (waiter.session.readOnly)
|
|
1142
1271
|
this.applicationSqlReaders.add(waiter.session);
|
|
1143
1272
|
else {
|
|
@@ -1326,7 +1455,7 @@ export class ZeroDO extends DurableObject {
|
|
|
1326
1455
|
this.requestsSinceBoot.applicationSqlReadSessions++;
|
|
1327
1456
|
else
|
|
1328
1457
|
this.requestsSinceBoot.applicationSqlWriteSessions++;
|
|
1329
|
-
return new ApplicationSqlSessionTarget(this, sessionID, options.readOnly === true, priority);
|
|
1458
|
+
return new ApplicationSqlSessionTarget(this, sessionID, options.readOnly === true, priority, this.startSqlTelemetrySample());
|
|
1330
1459
|
}
|
|
1331
1460
|
/**
|
|
1332
1461
|
* Run one read statement end to end in a single round trip.
|
|
@@ -1385,7 +1514,7 @@ export class ZeroDO extends DurableObject {
|
|
|
1385
1514
|
if (this.prepareApplicationSqlMutation(session.sessionID, sql)) {
|
|
1386
1515
|
session.mutated = true;
|
|
1387
1516
|
}
|
|
1388
|
-
return this.executeSQL(sql, [...params], undefined, session.sessionID).rows;
|
|
1517
|
+
return this.executeSQL(sql, [...params], undefined, session.sessionID, session.telemetry).rows;
|
|
1389
1518
|
});
|
|
1390
1519
|
}
|
|
1391
1520
|
async [APPLICATION_SQL_EXEC](session, sql, params = [], metadata) {
|
|
@@ -1394,16 +1523,26 @@ export class ZeroDO extends DurableObject {
|
|
|
1394
1523
|
if (this.prepareApplicationSqlMutation(session.sessionID, sql)) {
|
|
1395
1524
|
session.mutated = true;
|
|
1396
1525
|
}
|
|
1397
|
-
const result = this.executeSQL(sql, [...params], applicationSqlTrack(metadata), session.sessionID);
|
|
1526
|
+
const result = this.executeSQL(sql, [...params], applicationSqlTrack(metadata), session.sessionID, session.telemetry);
|
|
1398
1527
|
return { changes: result.changes };
|
|
1399
1528
|
});
|
|
1400
1529
|
}
|
|
1401
1530
|
async [APPLICATION_SQL_QUERY_PLAN](session, plan, queryName, queryBudget) {
|
|
1402
1531
|
this.assertApplicationSqlSession(session);
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1532
|
+
const sample = this.startSqlTelemetrySample();
|
|
1533
|
+
const name = queryName?.trim() || `${plan.rootTable}:${plan.planHash}`;
|
|
1534
|
+
try {
|
|
1535
|
+
const result = await this.atomically(() => executeTransactionQueryPlan(plan, (sql, params) => {
|
|
1536
|
+
this.assertApplicationSqlStatement(session, sql);
|
|
1537
|
+
return this.executeSQL(sql, params, undefined, session.sessionID, session.telemetry, sample).rows;
|
|
1538
|
+
}, { queryName, budget: queryBudget }));
|
|
1539
|
+
this.emitSqlTelemetry('orez_sql_query_sample', name, 'success', sample);
|
|
1540
|
+
return result;
|
|
1541
|
+
}
|
|
1542
|
+
catch (error) {
|
|
1543
|
+
this.emitSqlTelemetry('orez_sql_query_sample', name, 'error', sample, error);
|
|
1544
|
+
throw error;
|
|
1545
|
+
}
|
|
1407
1546
|
}
|
|
1408
1547
|
async [APPLICATION_SQL_REGISTER_TABLES](session, tables) {
|
|
1409
1548
|
this.assertApplicationSqlSession(session);
|
|
@@ -1424,10 +1563,21 @@ export class ZeroDO extends DurableObject {
|
|
|
1424
1563
|
});
|
|
1425
1564
|
}
|
|
1426
1565
|
}
|
|
1566
|
+
catch (error) {
|
|
1567
|
+
this.finishApplicationSqlTelemetry(session, 'error', error);
|
|
1568
|
+
throw error;
|
|
1569
|
+
}
|
|
1427
1570
|
finally {
|
|
1428
1571
|
this.releaseApplicationSqlTurn(session);
|
|
1429
1572
|
}
|
|
1430
|
-
|
|
1573
|
+
try {
|
|
1574
|
+
this.applicationSqlDidCommit(published, session.mutated);
|
|
1575
|
+
this.finishApplicationSqlTelemetry(session, 'committed');
|
|
1576
|
+
}
|
|
1577
|
+
catch (error) {
|
|
1578
|
+
this.finishApplicationSqlTelemetry(session, 'error', error);
|
|
1579
|
+
throw error;
|
|
1580
|
+
}
|
|
1431
1581
|
}
|
|
1432
1582
|
/**
|
|
1433
1583
|
* Undo whatever this session wrote and hand its turn on.
|
|
@@ -1454,10 +1604,24 @@ export class ZeroDO extends DurableObject {
|
|
|
1454
1604
|
this.releaseApplicationSqlTurn(session);
|
|
1455
1605
|
}
|
|
1456
1606
|
async [APPLICATION_SQL_ROLLBACK](session) {
|
|
1457
|
-
|
|
1607
|
+
try {
|
|
1608
|
+
this.closeApplicationSqlSession(session);
|
|
1609
|
+
this.finishApplicationSqlTelemetry(session, 'rolled_back');
|
|
1610
|
+
}
|
|
1611
|
+
catch (error) {
|
|
1612
|
+
this.finishApplicationSqlTelemetry(session, 'error', error);
|
|
1613
|
+
throw error;
|
|
1614
|
+
}
|
|
1458
1615
|
}
|
|
1459
1616
|
[APPLICATION_SQL_DISPOSE](session) {
|
|
1460
|
-
|
|
1617
|
+
try {
|
|
1618
|
+
this.closeApplicationSqlSession(session);
|
|
1619
|
+
this.finishApplicationSqlTelemetry(session, 'rolled_back');
|
|
1620
|
+
}
|
|
1621
|
+
catch (error) {
|
|
1622
|
+
this.finishApplicationSqlTelemetry(session, 'error', error);
|
|
1623
|
+
throw error;
|
|
1624
|
+
}
|
|
1461
1625
|
}
|
|
1462
1626
|
atomicallySync(work) {
|
|
1463
1627
|
try {
|
|
@@ -1541,7 +1705,12 @@ export class ZeroDO extends DurableObject {
|
|
|
1541
1705
|
return false;
|
|
1542
1706
|
}
|
|
1543
1707
|
}
|
|
1544
|
-
executeSQL(sql, params = [], track, transactionID) {
|
|
1708
|
+
executeSQL(sql, params = [], track, transactionID, transactionTelemetry = null, queryTelemetry = null) {
|
|
1709
|
+
if (transactionTelemetry)
|
|
1710
|
+
transactionTelemetry.statements++;
|
|
1711
|
+
if (queryTelemetry && queryTelemetry !== transactionTelemetry) {
|
|
1712
|
+
queryTelemetry.statements++;
|
|
1713
|
+
}
|
|
1545
1714
|
let capturesTrackedTable = false;
|
|
1546
1715
|
if (track?.physicalTableName) {
|
|
1547
1716
|
capturesTrackedTable = this.cdc.ensureTable({
|
|
@@ -1579,16 +1748,6 @@ export class ZeroDO extends DurableObject {
|
|
|
1579
1748
|
}
|
|
1580
1749
|
if (track && trackedTransactionID) {
|
|
1581
1750
|
const physicalTableName = track.physicalTableName || stripPublicPrefix(track.tableName);
|
|
1582
|
-
// the `_zsync_changes` journal is the one side-effect target orez owns,
|
|
1583
|
-
// so this path may register it directly: its identity is fixed and it
|
|
1584
|
-
// never publishes. registering it before the DML that fires the trigger,
|
|
1585
|
-
// in the same storage transaction, keeps the ordering safe. otherwise
|
|
1586
|
-
// `coversRowUndo` says no and the journal is snapshotted as before.
|
|
1587
|
-
this.cdc.ensureTable({
|
|
1588
|
-
physicalTableName: ZSYNC_CHANGES_TABLE,
|
|
1589
|
-
tableName: ZSYNC_CHANGES_TABLE,
|
|
1590
|
-
publish: false,
|
|
1591
|
-
});
|
|
1592
1751
|
for (const table of snapshotSideEffectWriteTables(this.sql, trackedTransactionID, physicalTableName, track.operation, (table) => this.cdc.coversRowUndo(table))) {
|
|
1593
1752
|
snapshotted.add(table);
|
|
1594
1753
|
}
|
|
@@ -1657,16 +1816,22 @@ export class ZeroDO extends DurableObject {
|
|
|
1657
1816
|
this.appendDerivedTrackedChanges(track, rows);
|
|
1658
1817
|
}
|
|
1659
1818
|
const publishedCaptured = captured.filter((change) => change.publish !== false).length;
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1819
|
+
const result = !track
|
|
1820
|
+
? { rows, columns, changes, capturedChanges: publishedCaptured }
|
|
1821
|
+
: {
|
|
1822
|
+
rows: track.returnRows ? rows : [],
|
|
1823
|
+
columns: track.returnRows ? columns : [],
|
|
1824
|
+
changes,
|
|
1825
|
+
affectedRows: rows.length,
|
|
1826
|
+
capturedChanges: publishedCaptured ||
|
|
1827
|
+
(capturesTrackedTable || track.publish === false ? 0 : rows.length),
|
|
1828
|
+
};
|
|
1829
|
+
if (transactionTelemetry)
|
|
1830
|
+
this.recordSqlTelemetry(transactionTelemetry, result);
|
|
1831
|
+
if (queryTelemetry && queryTelemetry !== transactionTelemetry) {
|
|
1832
|
+
this.recordSqlTelemetry(queryTelemetry, result);
|
|
1833
|
+
}
|
|
1834
|
+
return result;
|
|
1670
1835
|
}
|
|
1671
1836
|
cursorRows(cursor, columns) {
|
|
1672
1837
|
const cols = Array.isArray(columns) && columns.length > 0 ? columns : null;
|