@rex0220/kintone-sql-tools 3.72.0 → 3.74.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/README.md +9 -0
- package/dist-cli/ksql.js +340 -19
- package/dist-engine/index.cjs +14 -14
- package/dist-engine/index.mjs +14 -14
- package/dist-engine/ksql-engine.umd.js +14 -14
- package/dist-engine/meta/bundle-baseline.json +7 -7
- package/dist-engine/meta/cjs.json +9 -9
- package/dist-engine/meta/esm.json +9 -9
- package/dist-engine/meta/umd.json +9 -9
- package/dist-flow/flow-library/index.d.ts +1 -1
- package/dist-flow/flow-library/publicTypes.d.ts +31 -1
- package/dist-flow/index.cjs +12 -12
- package/dist-flow/index.mjs +12 -12
- package/dist-flow/meta/cjs.json +9 -9
- package/dist-flow/meta/esm.json +9 -9
- package/dist-mcp/ksql-mcp.js +317 -13
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -289,6 +289,15 @@ try {
|
|
|
289
289
|
}
|
|
290
290
|
```
|
|
291
291
|
|
|
292
|
+
読取上限は既定 10,000 件(`maxRecords`)です。一時テーブルの実体化には**独立の** `tempTableMaxRows`(既定 10,000 行・超過は常にエラー)が適用されるため、大きなバッチでは両方を併せて指定してください:
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
const ctx = createExecutionContext({ client, script: source, maxRecords: 25000, tempTableMaxRows: 25000 });
|
|
296
|
+
await explainScript(source, { client, maxRecords: 25000 }); // EXPLAIN 面にも同じ上限を渡せる
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
`executeStatement` / `previewStatement` は実行コンテキストの `maxRecords` を共有します(3 面同値)。詳細は[言語リファレンス §27.9](docs/ksql_language_reference.md)。
|
|
300
|
+
|
|
292
301
|
### エンジンバージョン × dialect 対応表
|
|
293
302
|
|
|
294
303
|
| エンジン | dialect 0(既定・宣言なし) | dialect 1(`-- @ksql dialect: 1`) | ksql-flow |
|
package/dist-cli/ksql.js
CHANGED
|
@@ -18466,6 +18466,24 @@ var materializedMetaBySelectResult = /* @__PURE__ */ new WeakMap();
|
|
|
18466
18466
|
var materializedMetaByValidationResult = /* @__PURE__ */ new WeakMap();
|
|
18467
18467
|
var importSourceByDmlStatement = /* @__PURE__ */ new WeakMap();
|
|
18468
18468
|
var statementEvaluationContextKey = /* @__PURE__ */ Symbol("statementEvaluationContext");
|
|
18469
|
+
var nativeUpsertExecutionKey = /* @__PURE__ */ Symbol("nativeUpsertExecution");
|
|
18470
|
+
var nativeUpsertExplainCapabilityKey = /* @__PURE__ */ Symbol("nativeUpsertExplainCapability");
|
|
18471
|
+
function withNativeUpsertExecutionOption(options, enabled, explainClientCapability) {
|
|
18472
|
+
return {
|
|
18473
|
+
...options,
|
|
18474
|
+
[nativeUpsertExecutionKey]: enabled,
|
|
18475
|
+
...explainClientCapability === void 0 ? {} : { [nativeUpsertExplainCapabilityKey]: explainClientCapability }
|
|
18476
|
+
};
|
|
18477
|
+
}
|
|
18478
|
+
function nativeUpsertExecutionEnabled(options) {
|
|
18479
|
+
return options[nativeUpsertExecutionKey] === true;
|
|
18480
|
+
}
|
|
18481
|
+
function hasNativeUpsertExecutionOption(options) {
|
|
18482
|
+
return nativeUpsertExecutionKey in options;
|
|
18483
|
+
}
|
|
18484
|
+
function nativeUpsertExplainClientCapability(options) {
|
|
18485
|
+
return options[nativeUpsertExplainCapabilityKey];
|
|
18486
|
+
}
|
|
18469
18487
|
function bindStatementEvaluationContext(options) {
|
|
18470
18488
|
const internal = options;
|
|
18471
18489
|
if (internal[statementEvaluationContextKey]) return options;
|
|
@@ -18530,6 +18548,7 @@ function createEmptyMetrics() {
|
|
|
18530
18548
|
getCalls: 0,
|
|
18531
18549
|
postCalls: 0,
|
|
18532
18550
|
putCalls: 0,
|
|
18551
|
+
nativeUpsertCalls: 0,
|
|
18533
18552
|
deleteCalls: 0,
|
|
18534
18553
|
fieldCalls: 0,
|
|
18535
18554
|
numberPrecisionCalls: 0,
|
|
@@ -18558,7 +18577,7 @@ function markLimitReached(client, appId) {
|
|
|
18558
18577
|
if (!metrics.limitReachedApps.includes(appId)) metrics.limitReachedApps.push(appId);
|
|
18559
18578
|
}
|
|
18560
18579
|
function wrapClientWithMetrics(client, metrics) {
|
|
18561
|
-
|
|
18580
|
+
const wrapped = {
|
|
18562
18581
|
[LIMIT_METRICS_SINK]: metrics,
|
|
18563
18582
|
getRecords: async (params) => {
|
|
18564
18583
|
metrics.getCalls += 1;
|
|
@@ -18637,6 +18656,14 @@ function wrapClientWithMetrics(client, metrics) {
|
|
|
18637
18656
|
return client.getProcessStatuses(appId);
|
|
18638
18657
|
}
|
|
18639
18658
|
};
|
|
18659
|
+
if (clientHasNativeUpsert(client)) {
|
|
18660
|
+
wrapped.upsertRecords = (params) => {
|
|
18661
|
+
metrics.putCalls += 1;
|
|
18662
|
+
metrics.nativeUpsertCalls += 1;
|
|
18663
|
+
return client.upsertRecords(params);
|
|
18664
|
+
};
|
|
18665
|
+
}
|
|
18666
|
+
return wrapped;
|
|
18640
18667
|
}
|
|
18641
18668
|
var SEARCH_ABORT_FAIL_CLOSED = /* @__PURE__ */ Symbol("searchAbortFailClosed");
|
|
18642
18669
|
function wrapClientWithSearchAbort(client, collector, failClosed) {
|
|
@@ -18809,7 +18836,13 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
|
18809
18836
|
relativeDatePlan,
|
|
18810
18837
|
options.recursiveCteMaxDepth,
|
|
18811
18838
|
options.recursiveCteMaxRows,
|
|
18812
|
-
options.recursiveCteMaxExpansions
|
|
18839
|
+
options.recursiveCteMaxExpansions,
|
|
18840
|
+
options.resolveMetadata !== false,
|
|
18841
|
+
hasNativeUpsertExecutionOption(options) ? {
|
|
18842
|
+
surface: "CLI",
|
|
18843
|
+
enableNativeUpsert: nativeUpsertExecutionEnabled(options),
|
|
18844
|
+
clientHasNativeUpsert: nativeUpsertExplainClientCapability(options) ?? clientHasNativeUpsert(client)
|
|
18845
|
+
} : { surface: "DOCUMENT_ONLY" }
|
|
18813
18846
|
);
|
|
18814
18847
|
// 一時テーブルはバッチスコープのため単文実行では拒否する(executeBatch を使う)
|
|
18815
18848
|
case "CREATE_TEMP_TABLE":
|
|
@@ -22813,6 +22846,206 @@ function upsertCompositeKey(parts) {
|
|
|
22813
22846
|
function upsertNormalizedKey(parts, numericKey) {
|
|
22814
22847
|
return JSON.stringify(parts.map((p, i) => numericKey[i] ? normalizeKeyPart(p) : p));
|
|
22815
22848
|
}
|
|
22849
|
+
var NATIVE_UPSERT_CONDITION_NAMES = {
|
|
22850
|
+
1: "CLIENT_CAPABILITY",
|
|
22851
|
+
2: "OPT_IN",
|
|
22852
|
+
3: "KEY_SCHEMA",
|
|
22853
|
+
4: "PLAIN_UPSERT",
|
|
22854
|
+
5: "EMPTY_KEY",
|
|
22855
|
+
6: "SOURCE_DUPLICATE"
|
|
22856
|
+
};
|
|
22857
|
+
function nativeUpsertExplainReason(condition, unknown, surface, unknownConditions = []) {
|
|
22858
|
+
if (unknown) {
|
|
22859
|
+
if (condition === 1) return "\u901A\u5E38\u5B9F\u884C client \u306E native \u80FD\u529B\u304C\u4E0D\u660E";
|
|
22860
|
+
if (condition === 2) return "native \u8A2D\u5B9A\u304C\u4E0D\u660E";
|
|
22861
|
+
if (condition === 3) return "\u30D5\u30A9\u30FC\u30E0\u30E1\u30BF\u30C7\u30FC\u30BF\u672A\u53D6\u5F97";
|
|
22862
|
+
if (condition === 5 || unknownConditions.includes(5)) return "\u30BD\u30FC\u30B9\u884C\u672A materialize";
|
|
22863
|
+
if (condition === 6) return "\u30AD\u30FC\u578B\u60C5\u5831\u304C\u672A\u78BA\u5B9A\u306E\u305F\u3081\u91CD\u8907\u5224\u5B9A\u4E0D\u80FD";
|
|
22864
|
+
}
|
|
22865
|
+
if (condition === 1) return "client \u304C upsertRecords \u80FD\u529B\u3092\u6301\u305F\u306A\u3044";
|
|
22866
|
+
if (condition === 2) return surface === "CLI" ? "--native-upsert \u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u306A\u3044" : "enableNativeUpsert \u304C false";
|
|
22867
|
+
if (condition === 3) return "\u30AD\u30FC\u9805\u76EE\u306F\u91CD\u8907\u7981\u6B62\u306E SINGLE_LINE_TEXT \u307E\u305F\u306F NUMBER \u3067\u306F\u306A\u3044";
|
|
22868
|
+
if (condition === 4) return "CHECK / APPLY / IMPORT / VALIDATE ONLY / ON ERROR SKIP \u3092\u4F34\u3046\u7D20\u3067\u306A\u3044 UPSERT";
|
|
22869
|
+
if (condition === 5) return "\u30BD\u30FC\u30B9\u306B\u7A7A\u6587\u5B57\u30AD\u30FC\u304C\u3042\u308B";
|
|
22870
|
+
return "\u30BD\u30FC\u30B9\u5185\u306B\u540C\u4E00\u30AD\u30FC\u304C\u3042\u308B";
|
|
22871
|
+
}
|
|
22872
|
+
function renderNativeUpsertEligibilityResult(label, result, surface) {
|
|
22873
|
+
if (result.status === "ELIGIBLE") {
|
|
22874
|
+
return ` ${label}: ELIGIBLE\uFF08${label.includes("statement/data") ? "\u6761\u4EF6 3\u301C6 \u3092" : "6 \u6761\u4EF6\u3092\u3059\u3079\u3066"}\u6E80\u305F\u3059\uFF09`;
|
|
22875
|
+
}
|
|
22876
|
+
if (result.status === "INELIGIBLE") {
|
|
22877
|
+
return ` ${label}: INELIGIBLE\uFF08\u6761\u4EF6 ${result.condition}: ${NATIVE_UPSERT_CONDITION_NAMES[result.condition]} \u2014 ${nativeUpsertExplainReason(result.condition, false, surface)}\uFF09`;
|
|
22878
|
+
}
|
|
22879
|
+
const unknownConditionNumbers = result.unknownConditions.map(({ condition }) => condition);
|
|
22880
|
+
const details = result.unknownConditions.map(
|
|
22881
|
+
({ condition }) => `\u6761\u4EF6 ${condition}: ${NATIVE_UPSERT_CONDITION_NAMES[condition]} \u2014 ${nativeUpsertExplainReason(condition, true, surface, unknownConditionNumbers)}`
|
|
22882
|
+
);
|
|
22883
|
+
return ` ${label}: UNKNOWN\uFF08${details.join("; ")}\uFF09`;
|
|
22884
|
+
}
|
|
22885
|
+
function renderNativeUpsertEligibility(evaluation, surface) {
|
|
22886
|
+
if (surface === "DOCUMENT_ONLY") {
|
|
22887
|
+
return [
|
|
22888
|
+
renderNativeUpsertEligibilityResult("native UPSERT statement/data eligibility", evaluation.statement, surface),
|
|
22889
|
+
` native UPSERT execution surface: NOT_APPLICABLE\uFF08\u3053\u306E\u9762\u3067\u306F\u5B9F\u884C\u3057\u306A\u3044${evaluation.statement.status === "ELIGIBLE" ? "\u3002/flow \u307E\u305F\u306F CLI --native-upsert \u3067\u306F native \u5019\u88DC" : ""}\uFF09`
|
|
22890
|
+
];
|
|
22891
|
+
}
|
|
22892
|
+
const lines = [renderNativeUpsertEligibilityResult("native UPSERT eligibility", evaluation.execution, surface)];
|
|
22893
|
+
if (evaluation.conditions[1].state === "FAIL" || evaluation.conditions[2].state === "FAIL") {
|
|
22894
|
+
lines.push(renderNativeUpsertEligibilityResult("native UPSERT statement/data eligibility", evaluation.statement, surface));
|
|
22895
|
+
}
|
|
22896
|
+
return lines;
|
|
22897
|
+
}
|
|
22898
|
+
function explainNativeUpsertStatement(statement) {
|
|
22899
|
+
const candidate = statement.type === "EXPLAIN" ? statement.query : statement;
|
|
22900
|
+
return candidate.type === "UPSERT" || candidate.type === "UPSERT_SELECT" ? candidate : null;
|
|
22901
|
+
}
|
|
22902
|
+
function nativeUpsertExplainEvaluation(statement, fieldInfos, options) {
|
|
22903
|
+
let rowKeyValues = null;
|
|
22904
|
+
if (statement.type === "UPSERT") {
|
|
22905
|
+
try {
|
|
22906
|
+
rowKeyValues = buildUpsertRowKeyValues(statement);
|
|
22907
|
+
} catch {
|
|
22908
|
+
}
|
|
22909
|
+
}
|
|
22910
|
+
return evaluateNativeUpsertEligibility({
|
|
22911
|
+
surface: options.surface === "DOCUMENT_ONLY" ? "DOCUMENT_ONLY" : "EXECUTION",
|
|
22912
|
+
clientCapability: options.surface === "DOCUMENT_ONLY" ? null : options.clientHasNativeUpsert ?? null,
|
|
22913
|
+
enabled: options.surface === "DOCUMENT_ONLY" ? null : options.surface === "FLOW" ? options.enableNativeUpsert !== false : options.enableNativeUpsert === true,
|
|
22914
|
+
statement: {
|
|
22915
|
+
kind: statement.type === "UPSERT" ? "VALUES" : "SELECT",
|
|
22916
|
+
keyFields: statement.keyFields,
|
|
22917
|
+
hasCheck: Boolean(statement.checkGroups?.length),
|
|
22918
|
+
hasApply: statement.type === "UPSERT" && Boolean(statement.onInsertApplyBlocks?.length || statement.onUpdateApplyBlocks?.length),
|
|
22919
|
+
validateOnly: statement.validateOnly === true,
|
|
22920
|
+
onErrorSkip: statement.onErrorSkip === true,
|
|
22921
|
+
importDerived: importSourceByDmlStatement.has(statement)
|
|
22922
|
+
},
|
|
22923
|
+
fieldInfos,
|
|
22924
|
+
rowKeyValues
|
|
22925
|
+
});
|
|
22926
|
+
}
|
|
22927
|
+
async function nativeUpsertExplainLines(statement, cacheContext, options) {
|
|
22928
|
+
const upsert = explainNativeUpsertStatement(statement);
|
|
22929
|
+
if (!upsert) return [];
|
|
22930
|
+
const fieldInfos = await getFieldsIfCached(upsert.appId, cacheContext);
|
|
22931
|
+
return renderNativeUpsertEligibility(
|
|
22932
|
+
nativeUpsertExplainEvaluation(upsert, fieldInfos, options),
|
|
22933
|
+
options.surface
|
|
22934
|
+
);
|
|
22935
|
+
}
|
|
22936
|
+
function evaluateNativeUpsertEligibility(input) {
|
|
22937
|
+
const keyField = input.statement.keyFields.length === 1 ? input.statement.keyFields[0] : void 0;
|
|
22938
|
+
const keyInfo = keyField === void 0 || input.fieldInfos === null ? void 0 : input.fieldInfos.find((field) => field.code === keyField);
|
|
22939
|
+
const supportedKeyType = keyInfo?.fieldType === "SINGLE_LINE_TEXT" || keyInfo?.fieldType === "NUMBER";
|
|
22940
|
+
const schemaPass = input.fieldInfos === null ? null : Boolean(
|
|
22941
|
+
keyField !== void 0 && keyInfo && supportedKeyType && keyInfo.isUnique === true
|
|
22942
|
+
);
|
|
22943
|
+
const plain = !input.statement.hasCheck && !input.statement.hasApply && !input.statement.validateOnly && !input.statement.onErrorSkip && !(input.statement.kind === "SELECT" && input.statement.importDerived);
|
|
22944
|
+
const rows = input.rowKeyValues;
|
|
22945
|
+
const noEmpty = rows === null ? null : rows.every((parts) => parts.every((part) => part !== ""));
|
|
22946
|
+
let noDuplicates = null;
|
|
22947
|
+
if (rows !== null && keyField !== void 0 && supportedKeyType) {
|
|
22948
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22949
|
+
noDuplicates = true;
|
|
22950
|
+
for (const parts of rows) {
|
|
22951
|
+
const normalized = upsertNormalizedKey([...parts], [keyInfo.fieldType === "NUMBER"]);
|
|
22952
|
+
if (seen.has(normalized)) {
|
|
22953
|
+
noDuplicates = false;
|
|
22954
|
+
break;
|
|
22955
|
+
}
|
|
22956
|
+
seen.add(normalized);
|
|
22957
|
+
}
|
|
22958
|
+
}
|
|
22959
|
+
const state = (value, reason) => ({
|
|
22960
|
+
state: value === null ? "UNKNOWN" : value ? "PASS" : "FAIL",
|
|
22961
|
+
reason
|
|
22962
|
+
});
|
|
22963
|
+
const conditions = {
|
|
22964
|
+
1: input.surface === "DOCUMENT_ONLY" ? { state: "NOT_APPLICABLE", reason: "client capability is not applicable on this surface" } : state(input.clientCapability, "client does not provide upsertRecords"),
|
|
22965
|
+
2: input.surface === "DOCUMENT_ONLY" ? { state: "NOT_APPLICABLE", reason: "native setting is not applicable on this surface" } : state(input.enabled, "native UPSERT is disabled"),
|
|
22966
|
+
3: state(schemaPass, "update key schema is not a single unique text or number field"),
|
|
22967
|
+
4: state(plain, "statement is not a plain UPSERT"),
|
|
22968
|
+
5: state(noEmpty, "source contains an empty update key"),
|
|
22969
|
+
6: state(noDuplicates, "source contains duplicate update keys")
|
|
22970
|
+
};
|
|
22971
|
+
const summarize = (ordered) => {
|
|
22972
|
+
const failed = ordered.find((condition) => conditions[condition].state === "FAIL");
|
|
22973
|
+
if (failed !== void 0) return { status: "INELIGIBLE", condition: failed, reason: conditions[failed].reason };
|
|
22974
|
+
const unknownConditions = ordered.filter((condition) => conditions[condition].state === "UNKNOWN").map((condition) => ({ condition, reason: conditions[condition].reason }));
|
|
22975
|
+
return unknownConditions.length > 0 ? { status: "UNKNOWN", unknownConditions } : { status: "ELIGIBLE" };
|
|
22976
|
+
};
|
|
22977
|
+
return {
|
|
22978
|
+
conditions,
|
|
22979
|
+
execution: summarize([1, 2, 3, 4, 5, 6]),
|
|
22980
|
+
statement: summarize([3, 4, 5, 6])
|
|
22981
|
+
};
|
|
22982
|
+
}
|
|
22983
|
+
function clientHasNativeUpsert(client) {
|
|
22984
|
+
return "upsertRecords" in client && typeof client.upsertRecords === "function";
|
|
22985
|
+
}
|
|
22986
|
+
function nativeEligibilityInput(stmt, client, options, fieldInfos, rowKeyValues) {
|
|
22987
|
+
return {
|
|
22988
|
+
surface: "EXECUTION",
|
|
22989
|
+
clientCapability: clientHasNativeUpsert(client),
|
|
22990
|
+
enabled: nativeUpsertExecutionEnabled(options),
|
|
22991
|
+
statement: {
|
|
22992
|
+
kind: stmt.type === "UPSERT" ? "VALUES" : "SELECT",
|
|
22993
|
+
keyFields: stmt.keyFields,
|
|
22994
|
+
hasCheck: Boolean(stmt.checkGroups?.length),
|
|
22995
|
+
hasApply: stmt.type === "UPSERT" && Boolean(stmt.onInsertApplyBlocks?.length || stmt.onUpdateApplyBlocks?.length),
|
|
22996
|
+
validateOnly: stmt.validateOnly === true,
|
|
22997
|
+
onErrorSkip: stmt.onErrorSkip === true,
|
|
22998
|
+
importDerived: importSourceByDmlStatement.has(stmt)
|
|
22999
|
+
},
|
|
23000
|
+
fieldInfos,
|
|
23001
|
+
rowKeyValues
|
|
23002
|
+
};
|
|
23003
|
+
}
|
|
23004
|
+
var NativeUpsertResponseError = class extends Error {
|
|
23005
|
+
constructor() {
|
|
23006
|
+
super("NativeUpsertResponseError: upsertRecords returned an invalid response.");
|
|
23007
|
+
this.name = "NativeUpsertResponseError";
|
|
23008
|
+
}
|
|
23009
|
+
};
|
|
23010
|
+
function validateNativeUpsertResponse(response, expectedRecords) {
|
|
23011
|
+
if (!response || !Array.isArray(response.records) || response.records.length !== expectedRecords) {
|
|
23012
|
+
throw new NativeUpsertResponseError();
|
|
23013
|
+
}
|
|
23014
|
+
let insertedCount = 0;
|
|
23015
|
+
let updatedCount = 0;
|
|
23016
|
+
for (const record of response.records) {
|
|
23017
|
+
if (!record || typeof record.id !== "string" || typeof record.revision !== "string" || record.operation !== "INSERT" && record.operation !== "UPDATE") {
|
|
23018
|
+
throw new NativeUpsertResponseError();
|
|
23019
|
+
}
|
|
23020
|
+
if (record.operation === "INSERT") insertedCount += 1;
|
|
23021
|
+
else updatedCount += 1;
|
|
23022
|
+
}
|
|
23023
|
+
return { insertedCount, updatedCount };
|
|
23024
|
+
}
|
|
23025
|
+
async function executeNativeUpsertRecords(appId, keyField, records, rowKeyValues, client, options) {
|
|
23026
|
+
if (records.length === 0) return { type: "UPSERT", insertedCount: 0, updatedCount: 0 };
|
|
23027
|
+
if (options.confirm) {
|
|
23028
|
+
const ok = await options.confirm(records.length, "UPDATE");
|
|
23029
|
+
if (!ok) throw new OperationCancelledError("UPDATE", records.length);
|
|
23030
|
+
}
|
|
23031
|
+
let insertedCount = 0;
|
|
23032
|
+
let updatedCount = 0;
|
|
23033
|
+
for (let offset = 0; offset < records.length; offset += 100) {
|
|
23034
|
+
const nativeRecords = records.slice(offset, offset + 100).map((record, index) => {
|
|
23035
|
+
const payload = {};
|
|
23036
|
+
for (const [field, value] of Object.entries(record)) if (field !== keyField) payload[field] = value;
|
|
23037
|
+
return {
|
|
23038
|
+
updateKey: { field: keyField, value: rowKeyValues[offset + index][0] },
|
|
23039
|
+
record: payload
|
|
23040
|
+
};
|
|
23041
|
+
});
|
|
23042
|
+
const response = await client.upsertRecords({ app: appId, upsert: true, records: nativeRecords });
|
|
23043
|
+
const counts = validateNativeUpsertResponse(response, nativeRecords.length);
|
|
23044
|
+
insertedCount += counts.insertedCount;
|
|
23045
|
+
updatedCount += counts.updatedCount;
|
|
23046
|
+
}
|
|
23047
|
+
return { type: "UPSERT", insertedCount, updatedCount };
|
|
23048
|
+
}
|
|
22816
23049
|
function lookupUpsertTarget(index, keyParts) {
|
|
22817
23050
|
const exact = index.raw.get(upsertCompositeKey(keyParts));
|
|
22818
23051
|
if (exact !== void 0) return exact;
|
|
@@ -23029,6 +23262,10 @@ async function getFieldsCached(appId, client, cacheContext) {
|
|
|
23029
23262
|
setScopedCacheValue(fieldInfoCache, cacheContext, appId, loading);
|
|
23030
23263
|
return loading;
|
|
23031
23264
|
}
|
|
23265
|
+
async function getFieldsIfCached(appId, cacheContext) {
|
|
23266
|
+
const cached = getScopedCacheValue(fieldInfoCache, cacheContext, appId);
|
|
23267
|
+
return cached ? await cached : null;
|
|
23268
|
+
}
|
|
23032
23269
|
async function getNumberPrecisionCached(appId, client, cacheContext) {
|
|
23033
23270
|
const cached = getScopedCacheValue(numberPrecisionCache, cacheContext, appId);
|
|
23034
23271
|
if (cached) return cached;
|
|
@@ -25596,6 +25833,16 @@ async function executeDelete(stmt, client, options, cacheContext) {
|
|
|
25596
25833
|
}
|
|
25597
25834
|
return { type: "DELETE", deletedCount: ids.length };
|
|
25598
25835
|
}
|
|
25836
|
+
function materializeUpsertValueRecords(stmt, fieldTypes, options) {
|
|
25837
|
+
return stmt.values.map((row) => {
|
|
25838
|
+
const record = {};
|
|
25839
|
+
stmt.fields.forEach((field, index) => {
|
|
25840
|
+
const value = row[index];
|
|
25841
|
+
record[field] = { value: value.type === "CASE_VALUE" ? evalCaseWhenValue(value.expr, {}, fieldTypes.get(field), statementEvaluationContext(options)) : toKintoneValue(value, fieldTypes.get(field)) };
|
|
25842
|
+
});
|
|
25843
|
+
return record;
|
|
25844
|
+
});
|
|
25845
|
+
}
|
|
25599
25846
|
async function executeUpsert(stmt, client, options, cacheContext) {
|
|
25600
25847
|
if (stmt.onInsertApplyBlocks?.length || stmt.onUpdateApplyBlocks?.length) {
|
|
25601
25848
|
return executeApplyUpsert(stmt, client, options, cacheContext);
|
|
@@ -25607,6 +25854,14 @@ async function executeUpsert(stmt, client, options, cacheContext) {
|
|
|
25607
25854
|
const toUpdate = [];
|
|
25608
25855
|
const fieldTypes = await getFieldTypeMap(stmt.appId, client, cacheContext);
|
|
25609
25856
|
const rowKeyValues = buildUpsertRowKeyValues(stmt);
|
|
25857
|
+
const nativeEligibility = evaluateNativeUpsertEligibility(
|
|
25858
|
+
nativeEligibilityInput(stmt, client, options, fieldInfos, rowKeyValues)
|
|
25859
|
+
);
|
|
25860
|
+
if (nativeEligibility.execution.status === "ELIGIBLE") {
|
|
25861
|
+
const records = materializeUpsertValueRecords(stmt, fieldTypes, options);
|
|
25862
|
+
assertValidDmlRecords(records, stmt.fields, fieldInfos, numberPrecision);
|
|
25863
|
+
return executeNativeUpsertRecords(stmt.appId, stmt.keyFields[0], records, rowKeyValues, client, options);
|
|
25864
|
+
}
|
|
25610
25865
|
const targetIndex = await resolveUpsertTargets(stmt.appId, stmt.keyFields, rowKeyValues, client, options, fieldTypes);
|
|
25611
25866
|
stmt.values.forEach((row, rowIdx) => {
|
|
25612
25867
|
const record = {};
|
|
@@ -26095,6 +26350,12 @@ async function executeUpsertSelect(stmt, client, options, cacheContext, cteCache
|
|
|
26095
26350
|
const rowKeyValues = records.map(
|
|
26096
26351
|
(record) => stmt.keyFields.map((key) => String(record[key]?.value ?? ""))
|
|
26097
26352
|
);
|
|
26353
|
+
const nativeEligibility = evaluateNativeUpsertEligibility(
|
|
26354
|
+
nativeEligibilityInput(stmt, client, options, fieldInfos, rowKeyValues)
|
|
26355
|
+
);
|
|
26356
|
+
if (nativeEligibility.execution.status === "ELIGIBLE") {
|
|
26357
|
+
return executeNativeUpsertRecords(stmt.appId, stmt.keyFields[0], records, rowKeyValues, client, options);
|
|
26358
|
+
}
|
|
26098
26359
|
if (importSourceByDmlStatement.has(stmt)) {
|
|
26099
26360
|
const numericKey = stmt.keyFields.map((key) => fieldTypes.get(key) === "NUMBER");
|
|
26100
26361
|
const sourceKeys = /* @__PURE__ */ new Set();
|
|
@@ -26524,6 +26785,10 @@ async function buildExplainWhereAnalysis(query, client, cacheContext, maxRecords
|
|
|
26524
26785
|
return;
|
|
26525
26786
|
}
|
|
26526
26787
|
const typed = node;
|
|
26788
|
+
if (typed["type"] === "UPSERT" || typed["type"] === "UPSERT_SELECT") {
|
|
26789
|
+
const upsert = node;
|
|
26790
|
+
await getFieldsCached(upsert.appId, tracedClient, cacheContext);
|
|
26791
|
+
}
|
|
26527
26792
|
if (typed["type"] === "SELECT") {
|
|
26528
26793
|
const select = node;
|
|
26529
26794
|
await validateSelectGroupingPlanning(select, tracedClient, cacheContext);
|
|
@@ -27146,7 +27411,7 @@ var EXPLAIN_FETCH_PLAN = /* @__PURE__ */ Symbol("ksql.explainFetchPlan");
|
|
|
27146
27411
|
function setExplainFetchPlan(result, plan) {
|
|
27147
27412
|
result[EXPLAIN_FETCH_PLAN] = plan;
|
|
27148
27413
|
}
|
|
27149
|
-
async function buildBatchExplainPlans(sql, client, injectedVariables, cacheContext = "batch-explain", maxRecords = 1e4, cursorMaxActive = 2, enableImport = false, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, resolveMetadata = true, recursiveCteMaxDepth, recursiveCteMaxRows, recursiveCteMaxExpansions, asOf, timezone) {
|
|
27414
|
+
async function buildBatchExplainPlans(sql, client, injectedVariables, cacheContext = "batch-explain", maxRecords = 1e4, cursorMaxActive = 2, enableImport = false, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, resolveMetadata = true, recursiveCteMaxDepth, recursiveCteMaxRows, recursiveCteMaxExpansions, asOf, timezone, nativeUpsertOptions = { surface: "DOCUMENT_ONLY" }) {
|
|
27150
27415
|
const asOfClock = createAsOfClock(asOf ?? /* @__PURE__ */ new Date(), timezone);
|
|
27151
27416
|
const recursiveLimits = resolveRecursiveCteLimits({
|
|
27152
27417
|
recursiveCteMaxDepth,
|
|
@@ -27245,10 +27510,15 @@ async function buildBatchExplainPlans(sql, client, injectedVariables, cacheConte
|
|
|
27245
27510
|
maxRecords,
|
|
27246
27511
|
dmlMaxRows
|
|
27247
27512
|
) : [];
|
|
27513
|
+
const nativeUpsertPlan = await nativeUpsertExplainLines(
|
|
27514
|
+
planStmt,
|
|
27515
|
+
invocationCacheContext,
|
|
27516
|
+
nativeUpsertOptions
|
|
27517
|
+
);
|
|
27248
27518
|
plans.push({
|
|
27249
27519
|
index: i,
|
|
27250
27520
|
type: analysis.statements[i].statementType,
|
|
27251
|
-
plan: statementPlan.length === 0 ? [...metadataPlan, ...dialect1Estimate] : [statementPlan[0], ...metadataPlan, ...statementPlan.slice(1), ...dialect1Estimate]
|
|
27521
|
+
plan: statementPlan.length === 0 ? [...metadataPlan, ...nativeUpsertPlan, ...dialect1Estimate] : [statementPlan[0], ...metadataPlan, ...statementPlan.slice(1), ...nativeUpsertPlan, ...dialect1Estimate]
|
|
27252
27522
|
});
|
|
27253
27523
|
fetchStatements.push({
|
|
27254
27524
|
index: i,
|
|
@@ -27562,21 +27832,29 @@ var explainMaterializedTables = /* @__PURE__ */ new WeakMap();
|
|
|
27562
27832
|
function defaultRecursiveExplainContext() {
|
|
27563
27833
|
return { maxRecords: 1e4, recursiveLimits: resolveRecursiveCteLimits({}) };
|
|
27564
27834
|
}
|
|
27565
|
-
async function executeExplain(stmt, client, cacheContext, maxRecords, cursorMaxActive, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, relativeDatePlan, recursiveCteMaxDepth, recursiveCteMaxRows, recursiveCteMaxExpansions) {
|
|
27835
|
+
async function executeExplain(stmt, client, cacheContext, maxRecords, cursorMaxActive, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, relativeDatePlan, recursiveCteMaxDepth, recursiveCteMaxRows, recursiveCteMaxExpansions, resolveMetadata = true, nativeUpsertOptions = { surface: "DOCUMENT_ONLY" }) {
|
|
27566
27836
|
const recursiveLimits = resolveRecursiveCteLimits({
|
|
27567
27837
|
recursiveCteMaxDepth,
|
|
27568
27838
|
recursiveCteMaxRows,
|
|
27569
27839
|
recursiveCteMaxExpansions
|
|
27570
27840
|
});
|
|
27571
27841
|
const sharedPlan = relativeDatePlan ?? await resolveRelativeDateExecutionPlan(stmt.query, client, cacheContext);
|
|
27572
|
-
const analysis = await buildExplainWhereAnalysis(
|
|
27842
|
+
const analysis = resolveMetadata ? await buildExplainWhereAnalysis(
|
|
27573
27843
|
stmt.query,
|
|
27574
27844
|
client,
|
|
27575
27845
|
cacheContext,
|
|
27576
27846
|
maxRecords,
|
|
27577
27847
|
sharedPlan,
|
|
27578
27848
|
explainMaterializedTables.get(stmt)
|
|
27579
|
-
)
|
|
27849
|
+
) : {
|
|
27850
|
+
capabilities: /* @__PURE__ */ new Map(),
|
|
27851
|
+
orderPlans: /* @__PURE__ */ new Map(),
|
|
27852
|
+
plainGroupByPlans: /* @__PURE__ */ new Map(),
|
|
27853
|
+
fieldApps: /* @__PURE__ */ new Set(),
|
|
27854
|
+
processStatusApps: /* @__PURE__ */ new Set(),
|
|
27855
|
+
numberPrecisionApps: /* @__PURE__ */ new Set(),
|
|
27856
|
+
relativeDatePlan: sharedPlan
|
|
27857
|
+
};
|
|
27580
27858
|
const fetchCollector = { sources: [] };
|
|
27581
27859
|
const relativeLines = relativeDateExplainLines(sharedPlan);
|
|
27582
27860
|
const planLines = sharedPlan.hasServerOnlyWhereFunction && !sharedPlan.allowed ? [...explainMetadataLines(analysis), ...relativeLines] : [
|
|
@@ -27600,7 +27878,8 @@ async function executeExplain(stmt, client, cacheContext, maxRecords, cursorMaxA
|
|
|
27600
27878
|
cursorMaxActive
|
|
27601
27879
|
)
|
|
27602
27880
|
];
|
|
27603
|
-
const
|
|
27881
|
+
const nativeUpsertPlan = await nativeUpsertExplainLines(stmt, cacheContext, nativeUpsertOptions);
|
|
27882
|
+
const lines = addFetchSummary([...planLines, ...nativeUpsertPlan], fetchCollector.sources);
|
|
27604
27883
|
const result = {
|
|
27605
27884
|
type: "SELECT",
|
|
27606
27885
|
columns: ["plan"],
|
|
@@ -29523,7 +29802,7 @@ var RequestGate = class {
|
|
|
29523
29802
|
}
|
|
29524
29803
|
};
|
|
29525
29804
|
function withRequestGate(client, gate) {
|
|
29526
|
-
|
|
29805
|
+
const wrapped = {
|
|
29527
29806
|
getRecords: (params) => gate.runReadOnly(() => client.getRecords(params)),
|
|
29528
29807
|
openCursor: async (params) => {
|
|
29529
29808
|
const handle = await gate.runCursorStep(() => client.openCursor(params));
|
|
@@ -29541,6 +29820,10 @@ function withRequestGate(client, gate) {
|
|
|
29541
29820
|
putRecords: (params) => gate.runMutation(() => client.putRecords(params)),
|
|
29542
29821
|
deleteRecords: (params) => gate.runMutation(() => client.deleteRecords(params))
|
|
29543
29822
|
};
|
|
29823
|
+
if ("upsertRecords" in client && typeof client.upsertRecords === "function") {
|
|
29824
|
+
wrapped.upsertRecords = (params) => gate.runMutation(() => client.upsertRecords(params));
|
|
29825
|
+
}
|
|
29826
|
+
return wrapped;
|
|
29544
29827
|
}
|
|
29545
29828
|
var globalGate = null;
|
|
29546
29829
|
function getGlobalRequestGate(options) {
|
|
@@ -30297,6 +30580,16 @@ function createNodeKintoneConnection(baseUrl, tokenResolver) {
|
|
|
30297
30580
|
_params.app
|
|
30298
30581
|
);
|
|
30299
30582
|
},
|
|
30583
|
+
async upsertRecords(_params) {
|
|
30584
|
+
return requestJson(
|
|
30585
|
+
`${apiBasePath}/records.json`,
|
|
30586
|
+
{
|
|
30587
|
+
method: "PUT",
|
|
30588
|
+
body: JSON.stringify({ app: _params.app, upsert: true, records: _params.records })
|
|
30589
|
+
},
|
|
30590
|
+
_params.app
|
|
30591
|
+
);
|
|
30592
|
+
},
|
|
30300
30593
|
async deleteRecords(_params) {
|
|
30301
30594
|
await requestJson(
|
|
30302
30595
|
`${apiBasePath}/records.json`,
|
|
@@ -30696,6 +30989,9 @@ var CLI_HELP_TEXT = HELP_TEXT.replace(
|
|
|
30696
30989
|
" --max-records <n> Max records to fetch (default: 500)",
|
|
30697
30990
|
` --max-records <n> Max records to fetch (default: 500)
|
|
30698
30991
|
${RECURSIVE_CTE_HELP_LINES}`
|
|
30992
|
+
).replace(
|
|
30993
|
+
" --allow-dml Enable UPDATE/DELETE/INSERT/UPSERT/REORDER execution",
|
|
30994
|
+
" --allow-dml Enable UPDATE/DELETE/INSERT/UPSERT/REORDER execution\n --native-upsert Allow eligible plain UPSERT to use kintone native UPSERT"
|
|
30699
30995
|
);
|
|
30700
30996
|
var CLI_IMPORT_SOURCE_REQUIRED_MESSAGE = "IMPORT \u306B\u306F\u30BD\u30FC\u30B9\u304C\u5FC5\u8981\u3067\u3059\u3002--import-csv <name=path> \u307E\u305F\u306F --import-json <name=path> \u3067\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002";
|
|
30701
30997
|
function toCliImportError(error, importEnabled) {
|
|
@@ -30747,6 +31043,7 @@ function parseArgs(argv) {
|
|
|
30747
31043
|
debugHeaders: false,
|
|
30748
31044
|
exitOnEmpty: false,
|
|
30749
31045
|
allowDml: false,
|
|
31046
|
+
nativeUpsert: false,
|
|
30750
31047
|
yes: false,
|
|
30751
31048
|
allowWithoutWhere: false,
|
|
30752
31049
|
continueOnError: false,
|
|
@@ -30819,6 +31116,10 @@ function parseArgs(argv) {
|
|
|
30819
31116
|
out.allowDml = true;
|
|
30820
31117
|
continue;
|
|
30821
31118
|
}
|
|
31119
|
+
if (a === "--native-upsert") {
|
|
31120
|
+
out.nativeUpsert = true;
|
|
31121
|
+
continue;
|
|
31122
|
+
}
|
|
30822
31123
|
if (a === "--yes") {
|
|
30823
31124
|
out.yes = true;
|
|
30824
31125
|
continue;
|
|
@@ -31656,6 +31957,7 @@ function buildReplExecArgv(base, sql, dryRun, format) {
|
|
|
31656
31957
|
if (base.exitOnEmpty) argv.push("--exit-on-empty");
|
|
31657
31958
|
if (base.allowDml) argv.push("--yes");
|
|
31658
31959
|
if (base.allowDml) argv.push("--allow-dml");
|
|
31960
|
+
if (base.nativeUpsert) argv.push("--native-upsert");
|
|
31659
31961
|
if (base.allowWithoutWhere) argv.push("--allow-without-where");
|
|
31660
31962
|
if (base.continueOnError) argv.push("--continue-on-error");
|
|
31661
31963
|
return argv;
|
|
@@ -31832,7 +32134,8 @@ async function runConsole(base) {
|
|
|
31832
32134
|
` auth=${base.auth ?? "(auto)"}`,
|
|
31833
32135
|
` format=${format ?? "(default)"}`,
|
|
31834
32136
|
` dryrun=${dryRun ? "on" : "off"}`,
|
|
31835
|
-
` allow-dml=${base.allowDml ? "on" : "off"}
|
|
32137
|
+
` allow-dml=${base.allowDml ? "on" : "off"}`,
|
|
32138
|
+
` native-upsert=${base.nativeUpsert ? "on" : "off"}`
|
|
31836
32139
|
].join("\n") + "\n"
|
|
31837
32140
|
);
|
|
31838
32141
|
try {
|
|
@@ -31963,6 +32266,7 @@ async function runConsole(base) {
|
|
|
31963
32266
|
`app=${base.app ?? "(from SQL or config)"}`,
|
|
31964
32267
|
`resolved-app-profiles=${lastResolvedProfiles}`,
|
|
31965
32268
|
`allow-dml=${base.allowDml ? "on" : "off"}`,
|
|
32269
|
+
`native-upsert=${base.nativeUpsert ? "on" : "off"}`,
|
|
31966
32270
|
`dml-max-rows=${base.dmlMaxRows ?? "(default)"}`,
|
|
31967
32271
|
`dml-max-subtable-rows=${base.dmlMaxSubtableRows ?? "(default)"}`
|
|
31968
32272
|
];
|
|
@@ -32335,7 +32639,8 @@ async function run() {
|
|
|
32335
32639
|
appProfileByApp.set(appId, appBindingByMappedApp.get(appId)?.profile ?? profileName.toLowerCase());
|
|
32336
32640
|
}
|
|
32337
32641
|
const cacheContext = buildCacheContext(profileName, appBindingByMappedApp);
|
|
32338
|
-
|
|
32642
|
+
const fullyOfflineDryRun = args.dryRun && (!dryRunNeedsMetadata || dryRunUsesStaticTypedPlan);
|
|
32643
|
+
if (fullyOfflineDryRun) {
|
|
32339
32644
|
client = createDryRunClient();
|
|
32340
32645
|
} else {
|
|
32341
32646
|
for (const explicitProfile of appProfileByApp.values()) {
|
|
@@ -32545,6 +32850,14 @@ async function run() {
|
|
|
32545
32850
|
if (!routed) throw new Error(`AuthError: profile "${pName}" is not resolved for APP${params.app}.`);
|
|
32546
32851
|
return routed.putRecords({ ...params, app: binding.appId });
|
|
32547
32852
|
},
|
|
32853
|
+
upsertRecords: (params) => {
|
|
32854
|
+
const binding = appBindingByMappedApp.get(params.app) ?? { appId: params.app, profile: profileName.toLowerCase() };
|
|
32855
|
+
const routed = profileClientMap.get(binding.profile);
|
|
32856
|
+
if (!routed || typeof routed.upsertRecords !== "function") {
|
|
32857
|
+
throw new Error(`AuthError: native UPSERT client is not resolved for APP${params.app}.`);
|
|
32858
|
+
}
|
|
32859
|
+
return routed.upsertRecords({ ...params, app: binding.appId });
|
|
32860
|
+
},
|
|
32548
32861
|
deleteRecords: (params) => {
|
|
32549
32862
|
const binding = appBindingByMappedApp.get(params.app) ?? { appId: params.app, profile: profileName.toLowerCase() };
|
|
32550
32863
|
const pName = binding.profile;
|
|
@@ -32595,10 +32908,17 @@ async function run() {
|
|
|
32595
32908
|
Object.keys(args.importCsv).length > 0 || Object.keys(args.importJson).length > 0,
|
|
32596
32909
|
dmlMaxRows,
|
|
32597
32910
|
dmlMaxSubtableRows,
|
|
32598
|
-
!
|
|
32911
|
+
!fullyOfflineDryRun,
|
|
32599
32912
|
recursiveCteMaxDepth,
|
|
32600
32913
|
recursiveCteMaxRows,
|
|
32601
|
-
recursiveCteMaxExpansions
|
|
32914
|
+
recursiveCteMaxExpansions,
|
|
32915
|
+
void 0,
|
|
32916
|
+
void 0,
|
|
32917
|
+
{
|
|
32918
|
+
surface: "CLI",
|
|
32919
|
+
enableNativeUpsert: args.nativeUpsert,
|
|
32920
|
+
clientHasNativeUpsert: true
|
|
32921
|
+
}
|
|
32602
32922
|
);
|
|
32603
32923
|
const out = [];
|
|
32604
32924
|
const restoredStatements = sqlDiagnosticContext ? restoreSqlDiagnosticValue(plans.statements, sqlDiagnosticContext.appBindingByMappedApp) : plans.statements;
|
|
@@ -32679,7 +32999,7 @@ query=${label}`);
|
|
|
32679
32999
|
return 2;
|
|
32680
33000
|
}
|
|
32681
33001
|
}
|
|
32682
|
-
let batchResult = await executeBatch(sql, client, {
|
|
33002
|
+
let batchResult = await executeBatch(sql, client, withNativeUpsertExecutionOption({
|
|
32683
33003
|
maxRecords,
|
|
32684
33004
|
fetchParallel,
|
|
32685
33005
|
onLimitReached: effectiveOnLimit,
|
|
@@ -32717,7 +33037,7 @@ query=${label}`);
|
|
|
32717
33037
|
}
|
|
32718
33038
|
return true;
|
|
32719
33039
|
} : void 0
|
|
32720
|
-
});
|
|
33040
|
+
}, args.nativeUpsert, true));
|
|
32721
33041
|
if (sqlDiagnosticContext) {
|
|
32722
33042
|
batchResult = {
|
|
32723
33043
|
...batchResult,
|
|
@@ -32734,7 +33054,7 @@ query=${label}`);
|
|
|
32734
33054
|
}
|
|
32735
33055
|
return writeBatchOutput(batchResult, { format, noHeader, pretty, displayOptions, outputPath, quiet });
|
|
32736
33056
|
}
|
|
32737
|
-
let result = args.dryRun ? await execute(`EXPLAIN ${sql}`, client, {
|
|
33057
|
+
let result = args.dryRun ? await execute(`EXPLAIN ${sql}`, client, withNativeUpsertExecutionOption({
|
|
32738
33058
|
maxRecords,
|
|
32739
33059
|
onLimitReached: onLimit,
|
|
32740
33060
|
cacheContext,
|
|
@@ -32745,8 +33065,9 @@ query=${label}`);
|
|
|
32745
33065
|
dmlMaxSubtableRows,
|
|
32746
33066
|
recursiveCteMaxDepth,
|
|
32747
33067
|
recursiveCteMaxRows,
|
|
32748
|
-
recursiveCteMaxExpansions
|
|
32749
|
-
|
|
33068
|
+
recursiveCteMaxExpansions,
|
|
33069
|
+
resolveMetadata: !fullyOfflineDryRun
|
|
33070
|
+
}, args.nativeUpsert, true)) : await execute(sql, client, withNativeUpsertExecutionOption({
|
|
32750
33071
|
maxRecords,
|
|
32751
33072
|
fetchParallel,
|
|
32752
33073
|
onLimitReached: effectiveOnLimit,
|
|
@@ -32764,7 +33085,7 @@ query=${label}`);
|
|
|
32764
33085
|
dmlMaxSubtableRows
|
|
32765
33086
|
} : {},
|
|
32766
33087
|
...containsApplyMutation ? { allowApplyMutation: true } : {}
|
|
32767
|
-
});
|
|
33088
|
+
}, args.nativeUpsert, true));
|
|
32768
33089
|
if ((args.dryRun || parsedStatements[0]?.type === "EXPLAIN") && sqlDiagnosticContext) {
|
|
32769
33090
|
result = restoreSqlDiagnosticValue(result, sqlDiagnosticContext.appBindingByMappedApp);
|
|
32770
33091
|
}
|