@rex0220/kintone-sql-tools 3.30.0 → 3.31.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-cli/ksql.js +338 -146
- package/dist-engine/errors.d.ts +3 -0
- package/dist-engine/index.cjs +11 -10
- package/dist-engine/index.mjs +11 -10
- package/dist-engine/ksql-engine.umd.js +9 -8
- package/dist-engine/meta/bundle-baseline.json +10 -10
- package/dist-engine/meta/cjs.json +124 -106
- package/dist-engine/meta/esm.json +124 -106
- package/dist-engine/meta/umd.json +124 -106
- package/dist-engine/query.d.ts +1 -2
- package/dist-mcp/ksql-mcp.js +341 -148
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -670,6 +670,9 @@ function quote(value) {
|
|
|
670
670
|
return `'${value.replace(/'/g, "''")}'`;
|
|
671
671
|
}
|
|
672
672
|
function arithLabel(node, topLevel = false) {
|
|
673
|
+
if (node.type === "VARIABLE") throw new Error(
|
|
674
|
+
`InternalError: unresolved arithmetic variable @${node.name} reached aggregate expression labeling.`
|
|
675
|
+
);
|
|
673
676
|
if (node.type === "FIELD_REF") return node.field;
|
|
674
677
|
if (node.type === "NUMBER") return numberLiteralText(node);
|
|
675
678
|
if (node.type === "STRING_FUNC") return stringFuncLabel(node);
|
|
@@ -1054,6 +1057,7 @@ var Parser = class {
|
|
|
1054
1057
|
this.cteNames = /* @__PURE__ */ new Set();
|
|
1055
1058
|
/** パース中に出現した一時テーブル参照(#name)のトークン。単文 API での拒否に使う */
|
|
1056
1059
|
this.tempTableRefs = [];
|
|
1060
|
+
this.allowSelectArithVariable = false;
|
|
1057
1061
|
}
|
|
1058
1062
|
// ----------------------------------------------------------
|
|
1059
1063
|
// 公開 API
|
|
@@ -1893,6 +1897,15 @@ var Parser = class {
|
|
|
1893
1897
|
} while (this.consume("," /* COMMA */));
|
|
1894
1898
|
return cols;
|
|
1895
1899
|
}
|
|
1900
|
+
parseSelectArith(parse) {
|
|
1901
|
+
const previous = this.allowSelectArithVariable;
|
|
1902
|
+
this.allowSelectArithVariable = true;
|
|
1903
|
+
try {
|
|
1904
|
+
return parse();
|
|
1905
|
+
} finally {
|
|
1906
|
+
this.allowSelectArithVariable = previous;
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1896
1909
|
parseSelectColumn() {
|
|
1897
1910
|
if (this.consume("*" /* STAR */)) {
|
|
1898
1911
|
return { type: "WILDCARD" };
|
|
@@ -1938,7 +1951,7 @@ var Parser = class {
|
|
|
1938
1951
|
if (this.tryStringFuncName() !== null) {
|
|
1939
1952
|
const funcExpr = this.parseStringFuncExpr();
|
|
1940
1953
|
if (this.isArithOp(this.peek().kind)) {
|
|
1941
|
-
const node = this.continueArith(funcExpr);
|
|
1954
|
+
const node = this.parseSelectArith(() => this.continueArith(funcExpr));
|
|
1942
1955
|
const alias3 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
|
|
1943
1956
|
return { type: "ARITH_COL", expr: node, alias: alias3 };
|
|
1944
1957
|
}
|
|
@@ -1976,7 +1989,7 @@ var Parser = class {
|
|
|
1976
1989
|
return { type: "LITERAL_COL", value, alias: alias2 };
|
|
1977
1990
|
}
|
|
1978
1991
|
if (this.peek().kind === "(" /* LPAREN */ || this.peek().kind === "NUMBER" /* NUMBER */) {
|
|
1979
|
-
const node = this.parseArithAddSub();
|
|
1992
|
+
const node = this.parseSelectArith(() => this.parseArithAddSub());
|
|
1980
1993
|
const alias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
|
|
1981
1994
|
return { type: "ARITH_COL", expr: node, alias: alias2 };
|
|
1982
1995
|
}
|
|
@@ -1989,7 +2002,7 @@ var Parser = class {
|
|
|
1989
2002
|
}
|
|
1990
2003
|
if (this.isArithOp(this.peek().kind)) {
|
|
1991
2004
|
const left = { type: "FIELD_REF", field };
|
|
1992
|
-
const node = this.continueArith(left);
|
|
2005
|
+
const node = this.parseSelectArith(() => this.continueArith(left));
|
|
1993
2006
|
const alias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
|
|
1994
2007
|
return { type: "ARITH_COL", expr: node, alias: alias2 };
|
|
1995
2008
|
}
|
|
@@ -2269,6 +2282,10 @@ var Parser = class {
|
|
|
2269
2282
|
this.advance();
|
|
2270
2283
|
return makeNumberLiteral(tok.value);
|
|
2271
2284
|
}
|
|
2285
|
+
if (this.allowSelectArithVariable && tok.kind === "VARIABLE" /* VARIABLE */) {
|
|
2286
|
+
this.advance();
|
|
2287
|
+
return { type: "VARIABLE", name: tok.value.slice(1).toLowerCase() };
|
|
2288
|
+
}
|
|
2272
2289
|
if (tok.kind === "IDENT" /* IDENT */ || tok.kind === "BIDENT" /* BIDENT */) {
|
|
2273
2290
|
this.advance();
|
|
2274
2291
|
let field = tok.value;
|
|
@@ -5258,6 +5275,9 @@ function collectArithFields(expr, out) {
|
|
|
5258
5275
|
collectArithNode(expr.right, out);
|
|
5259
5276
|
}
|
|
5260
5277
|
function collectArithNode(node, out) {
|
|
5278
|
+
if (node.type === "VARIABLE") throw new Error(
|
|
5279
|
+
`InternalError: unresolved arithmetic variable @${node.name} reached SELECT field collection.`
|
|
5280
|
+
);
|
|
5261
5281
|
if (node.type === "FIELD_REF") out.push(normalizeSimpleFieldRef(node.field));
|
|
5262
5282
|
else if (node.type === "ARITH") collectArithFields(node, out);
|
|
5263
5283
|
else if (node.type === "STRING_FUNC") collectStringFuncFields(node, out);
|
|
@@ -5482,6 +5502,11 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
|
|
|
5482
5502
|
addFieldName(field, phase);
|
|
5483
5503
|
};
|
|
5484
5504
|
const walkArith = (node, phase = "select") => {
|
|
5505
|
+
if (node.type === "VARIABLE") {
|
|
5506
|
+
throw new Error(
|
|
5507
|
+
`InternalError: unresolved arithmetic variable @${node.name} reached source-aware field collection.`
|
|
5508
|
+
);
|
|
5509
|
+
}
|
|
5485
5510
|
if (node.type === "FIELD_REF") {
|
|
5486
5511
|
addFieldName(node.field, phase);
|
|
5487
5512
|
return;
|
|
@@ -7129,6 +7154,9 @@ function selectScalarExtreme(values, extreme) {
|
|
|
7129
7154
|
|
|
7130
7155
|
// src/engine/evalFunc.ts
|
|
7131
7156
|
function evalArithExpr(expr, row) {
|
|
7157
|
+
if (expr.type === "VARIABLE") throw new Error(
|
|
7158
|
+
`InternalError: unresolved arithmetic variable @${expr.name} reached arithmetic evaluation.`
|
|
7159
|
+
);
|
|
7132
7160
|
if (expr.type === "NUMBER") return expr.value;
|
|
7133
7161
|
if (expr.type === "FIELD_REF") return Number(resolveFieldRef(row, expr.field));
|
|
7134
7162
|
if (expr.type === "STRING_FUNC") return Number(evalStringFunc(expr, row));
|
|
@@ -8166,6 +8194,9 @@ function collectArithFields2(expr, out) {
|
|
|
8166
8194
|
collectArithNode2(expr.right, out);
|
|
8167
8195
|
}
|
|
8168
8196
|
function collectArithNode2(node, out) {
|
|
8197
|
+
if (node.type === "VARIABLE") throw new Error(
|
|
8198
|
+
`InternalError: unresolved arithmetic variable @${node.name} reached DML field collection.`
|
|
8199
|
+
);
|
|
8169
8200
|
if (node.type === "FIELD_REF") out.add(node.field);
|
|
8170
8201
|
else if (node.type === "ARITH") collectArithFields2(node, out);
|
|
8171
8202
|
else if (node.type === "STRING_FUNC") collectStringFuncFields2(node, out);
|
|
@@ -8363,6 +8394,9 @@ function evalArith(expr, raw) {
|
|
|
8363
8394
|
}
|
|
8364
8395
|
}
|
|
8365
8396
|
function resolveArithOperand(operand, raw) {
|
|
8397
|
+
if (operand.type === "VARIABLE") throw new Error(
|
|
8398
|
+
`InternalError: unresolved arithmetic variable @${operand.name} reached DML evaluation.`
|
|
8399
|
+
);
|
|
8366
8400
|
if (operand.type === "NUMBER") return operand.value;
|
|
8367
8401
|
if (operand.type === "ARITH") return evalArith(operand, raw);
|
|
8368
8402
|
if (operand.type === "STRING_FUNC") throw new DmlConvertError(
|
|
@@ -12465,6 +12499,65 @@ function planPlainGroupByResolution(groupBy, columns, schemas) {
|
|
|
12465
12499
|
};
|
|
12466
12500
|
}
|
|
12467
12501
|
|
|
12502
|
+
// src/core/emptyWildcardSchema.ts
|
|
12503
|
+
var EMPTY_WILDCARD_FIELD_TYPE_POLICY = {
|
|
12504
|
+
CALC: "RECORD",
|
|
12505
|
+
CATEGORY: "NON_RECORD",
|
|
12506
|
+
CHECK_BOX: "RECORD",
|
|
12507
|
+
CREATED_TIME: "RECORD",
|
|
12508
|
+
CREATOR: "RECORD",
|
|
12509
|
+
DATE: "RECORD",
|
|
12510
|
+
DATETIME: "RECORD",
|
|
12511
|
+
DROP_DOWN: "RECORD",
|
|
12512
|
+
FILE: "RECORD",
|
|
12513
|
+
GROUP: "NON_RECORD",
|
|
12514
|
+
GROUP_SELECT: "RECORD",
|
|
12515
|
+
LINK: "RECORD",
|
|
12516
|
+
MODIFIER: "RECORD",
|
|
12517
|
+
MULTI_LINE_TEXT: "RECORD",
|
|
12518
|
+
MULTI_SELECT: "RECORD",
|
|
12519
|
+
NUMBER: "RECORD",
|
|
12520
|
+
ORGANIZATION_SELECT: "RECORD",
|
|
12521
|
+
RADIO_BUTTON: "RECORD",
|
|
12522
|
+
RECORD_NUMBER: "RECORD",
|
|
12523
|
+
REFERENCE_TABLE: "NON_RECORD",
|
|
12524
|
+
RICH_TEXT: "RECORD",
|
|
12525
|
+
SINGLE_LINE_TEXT: "RECORD",
|
|
12526
|
+
STATUS: "PROCESS",
|
|
12527
|
+
STATUS_ASSIGNEE: "PROCESS",
|
|
12528
|
+
SUBTABLE: "RECORD",
|
|
12529
|
+
TIME: "RECORD",
|
|
12530
|
+
UPDATED_TIME: "RECORD",
|
|
12531
|
+
USER_SELECT: "RECORD"
|
|
12532
|
+
};
|
|
12533
|
+
function fieldPolicy(fieldType) {
|
|
12534
|
+
const policy = EMPTY_WILDCARD_FIELD_TYPE_POLICY[fieldType];
|
|
12535
|
+
if (policy === void 0) {
|
|
12536
|
+
throw new Error(
|
|
12537
|
+
`InternalError: empty SELECT * schema policy is not defined for field type ${fieldType}.`
|
|
12538
|
+
);
|
|
12539
|
+
}
|
|
12540
|
+
return policy;
|
|
12541
|
+
}
|
|
12542
|
+
async function deriveEmptyWildcardColumns(fields, subtableCode, loadProcessStatuses) {
|
|
12543
|
+
if (subtableCode != null) {
|
|
12544
|
+
return [
|
|
12545
|
+
"_pid",
|
|
12546
|
+
"_rid",
|
|
12547
|
+
"_idx",
|
|
12548
|
+
...fields.filter((field) => field.inSubtable === true && field.subtableCode === subtableCode).map((field) => field.code)
|
|
12549
|
+
];
|
|
12550
|
+
}
|
|
12551
|
+
const topLevel = fields.filter((field) => !field.inSubtable);
|
|
12552
|
+
const needsProcessSettings = topLevel.some((field) => fieldPolicy(field.fieldType) === "PROCESS");
|
|
12553
|
+
const processEnabled = needsProcessSettings ? (await loadProcessStatuses()).enable : false;
|
|
12554
|
+
const columns = topLevel.filter((field) => {
|
|
12555
|
+
const policy = fieldPolicy(field.fieldType);
|
|
12556
|
+
return policy === "RECORD" || policy === "PROCESS" && processEnabled;
|
|
12557
|
+
}).map((field) => field.code);
|
|
12558
|
+
return [...columns, "$revision", "$id"];
|
|
12559
|
+
}
|
|
12560
|
+
|
|
12468
12561
|
// src/engine/process.ts
|
|
12469
12562
|
function flatten(record, alias) {
|
|
12470
12563
|
const row = {};
|
|
@@ -13348,6 +13441,9 @@ function stripParentShortcutColumns(row) {
|
|
|
13348
13441
|
}
|
|
13349
13442
|
function arithColDefaultKey(expr) {
|
|
13350
13443
|
const nodeLabel = (n) => {
|
|
13444
|
+
if (n.type === "VARIABLE") throw new Error(
|
|
13445
|
+
`InternalError: unresolved arithmetic variable @${n.name} reached arithmetic column labeling.`
|
|
13446
|
+
);
|
|
13351
13447
|
if (n.type === "FIELD_REF") return n.field;
|
|
13352
13448
|
if (n.type === "NUMBER") return numberLiteralText(n);
|
|
13353
13449
|
if (n.type === "STRING_FUNC") return stringFuncDefaultKey(n);
|
|
@@ -15287,6 +15383,7 @@ var materializedMetaByValidationResult = /* @__PURE__ */ new WeakMap();
|
|
|
15287
15383
|
var importSourceByDmlStatement = /* @__PURE__ */ new WeakMap();
|
|
15288
15384
|
var defaultCacheContextByClient = /* @__PURE__ */ new WeakMap();
|
|
15289
15385
|
var nextDefaultCacheContextId = 1;
|
|
15386
|
+
var nextCacheInvocationId = 1;
|
|
15290
15387
|
function resolveCacheContext(client, explicit) {
|
|
15291
15388
|
if (explicit) return explicit;
|
|
15292
15389
|
let context = defaultCacheContextByClient.get(client);
|
|
@@ -15296,31 +15393,40 @@ function resolveCacheContext(client, explicit) {
|
|
|
15296
15393
|
}
|
|
15297
15394
|
return context;
|
|
15298
15395
|
}
|
|
15396
|
+
function createInvocationCacheContext(cacheContext) {
|
|
15397
|
+
return `${cacheContext}\0inv:${nextCacheInvocationId++}`;
|
|
15398
|
+
}
|
|
15299
15399
|
async function execute(sql, client, options = {}) {
|
|
15300
15400
|
const startedAt = Date.now();
|
|
15301
|
-
const cacheContext =
|
|
15302
|
-
|
|
15303
|
-
const metrics = createEmptyMetrics();
|
|
15304
|
-
const countedClient = wrapClientWithMetrics(client, metrics);
|
|
15305
|
-
const collector = { aborted: false };
|
|
15306
|
-
const guardedClient = wrapClientWithSearchAbort(
|
|
15307
|
-
countedClient,
|
|
15308
|
-
collector,
|
|
15309
|
-
!isSelectLikeStatement(stmt) || statementContainsOuterJoin(stmt)
|
|
15310
|
-
);
|
|
15311
|
-
const result = await executeParsedStatement(
|
|
15312
|
-
stmt,
|
|
15313
|
-
guardedClient,
|
|
15314
|
-
options,
|
|
15315
|
-
cacheContext
|
|
15401
|
+
const cacheContext = createInvocationCacheContext(
|
|
15402
|
+
resolveCacheContext(client, options.cacheContext)
|
|
15316
15403
|
);
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
const
|
|
15321
|
-
|
|
15404
|
+
try {
|
|
15405
|
+
const stmt = parseSql(sql, options.enableImport === true);
|
|
15406
|
+
const metrics = createEmptyMetrics();
|
|
15407
|
+
const countedClient = wrapClientWithMetrics(client, metrics);
|
|
15408
|
+
const collector = { aborted: false };
|
|
15409
|
+
const guardedClient = wrapClientWithSearchAbort(
|
|
15410
|
+
countedClient,
|
|
15411
|
+
collector,
|
|
15412
|
+
!isSelectLikeStatement(stmt) || statementContainsOuterJoin(stmt)
|
|
15413
|
+
);
|
|
15414
|
+
const result = await executeParsedStatement(
|
|
15415
|
+
stmt,
|
|
15416
|
+
guardedClient,
|
|
15417
|
+
options,
|
|
15418
|
+
cacheContext
|
|
15419
|
+
);
|
|
15420
|
+
metrics.elapsedMs = Date.now() - startedAt;
|
|
15421
|
+
const finalResult = { ...attachSearchAbortWarning(result, collector), metrics };
|
|
15422
|
+
if (result.type === "SELECT") {
|
|
15423
|
+
const columnMeta = materializedMetaBySelectResult.get(result);
|
|
15424
|
+
if (columnMeta) materializedMetaBySelectResult.set(finalResult, columnMeta);
|
|
15425
|
+
}
|
|
15426
|
+
return finalResult;
|
|
15427
|
+
} finally {
|
|
15428
|
+
releaseMetadataCacheScope(cacheContext);
|
|
15322
15429
|
}
|
|
15323
|
-
return finalResult;
|
|
15324
15430
|
}
|
|
15325
15431
|
function createEmptyMetrics() {
|
|
15326
15432
|
return {
|
|
@@ -15891,91 +15997,97 @@ async function executeBatch(sql, client, options = {}) {
|
|
|
15891
15997
|
const countedClient = wrapClientWithMetrics(client, metrics);
|
|
15892
15998
|
const startedAt = Date.now();
|
|
15893
15999
|
const deadline = options.timeoutMs != null ? startedAt + options.timeoutMs : null;
|
|
15894
|
-
const cacheContext =
|
|
15895
|
-
|
|
15896
|
-
|
|
15897
|
-
|
|
15898
|
-
|
|
15899
|
-
|
|
15900
|
-
|
|
15901
|
-
const
|
|
15902
|
-
|
|
15903
|
-
|
|
15904
|
-
|
|
15905
|
-
|
|
15906
|
-
|
|
15907
|
-
|
|
15908
|
-
|
|
15909
|
-
|
|
15910
|
-
const depName = analysis.statements[brokenDep].tempTablesCreated[0] ?? `statement ${brokenDep}`;
|
|
15911
|
-
results.push({ ...base, status: "skipped", skippedReason: `dependency: ${depName}` });
|
|
15912
|
-
failed.add(i);
|
|
15913
|
-
continue;
|
|
15914
|
-
}
|
|
15915
|
-
if (deadline !== null && Date.now() >= deadline) {
|
|
15916
|
-
results.push({ ...base, status: "skipped", skippedReason: "timeout" });
|
|
15917
|
-
failed.add(i);
|
|
15918
|
-
aborted = "timeout";
|
|
15919
|
-
continue;
|
|
15920
|
-
}
|
|
15921
|
-
try {
|
|
15922
|
-
const remaining = deadline !== null ? deadline - Date.now() : null;
|
|
15923
|
-
const userConfirm = batchOptions.confirm;
|
|
15924
|
-
const stmtOptions = userConfirm ? {
|
|
15925
|
-
...batchOptions,
|
|
15926
|
-
confirm: (count, operation, detailContext) => userConfirm(count, operation, {
|
|
15927
|
-
statementIndex: i,
|
|
15928
|
-
statementCount: statements.length,
|
|
15929
|
-
statementType: info.statementType,
|
|
15930
|
-
targetAppId: info.targetAppId,
|
|
15931
|
-
...detailContext?.importDetail ? { importDetail: detailContext.importDetail } : {},
|
|
15932
|
-
...detailContext?.applyDetail ? { applyDetail: detailContext.applyDetail } : {},
|
|
15933
|
-
...detailContext?.applyDiagnostic ? { applyDiagnostic: detailContext.applyDiagnostic } : {}
|
|
15934
|
-
})
|
|
15935
|
-
} : batchOptions;
|
|
15936
|
-
const searchAbortCollector = { aborted: false };
|
|
15937
|
-
const statementClient = wrapClientWithSearchAbort(
|
|
15938
|
-
countedClient,
|
|
15939
|
-
searchAbortCollector,
|
|
15940
|
-
info.statementType !== "SELECT" && info.statementType !== "UNION" && info.statementType !== "WITH" || statementContainsOuterJoin(statements[i])
|
|
15941
|
-
);
|
|
15942
|
-
const cursorScope = wrapClientWithCursorScope(statementClient);
|
|
15943
|
-
const outcome = await runWithDeadline(
|
|
15944
|
-
executeBatchStatement(statements[i], info, cursorScope.client, stmtOptions, cacheContext, tempTables, variables),
|
|
15945
|
-
remaining,
|
|
15946
|
-
cursorScope.closeActive
|
|
15947
|
-
);
|
|
15948
|
-
if (outcome.result) {
|
|
15949
|
-
outcome.result = attachSearchAbortWarning(outcome.result, searchAbortCollector);
|
|
16000
|
+
const cacheContext = createInvocationCacheContext(
|
|
16001
|
+
resolveCacheContext(client, options.cacheContext)
|
|
16002
|
+
);
|
|
16003
|
+
try {
|
|
16004
|
+
const tempTables = /* @__PURE__ */ new Map();
|
|
16005
|
+
const variables = /* @__PURE__ */ new Map();
|
|
16006
|
+
const results = [];
|
|
16007
|
+
const failed = /* @__PURE__ */ new Set();
|
|
16008
|
+
let aborted = null;
|
|
16009
|
+
for (let i = 0; i < statements.length; i++) {
|
|
16010
|
+
const info = analysis.statements[i];
|
|
16011
|
+
const base = { index: i, type: info.statementType };
|
|
16012
|
+
if (aborted) {
|
|
16013
|
+
results.push({ ...base, status: "skipped", skippedReason: aborted });
|
|
16014
|
+
failed.add(i);
|
|
16015
|
+
continue;
|
|
15950
16016
|
}
|
|
15951
|
-
|
|
15952
|
-
|
|
15953
|
-
|
|
15954
|
-
...base,
|
|
15955
|
-
|
|
15956
|
-
|
|
15957
|
-
|
|
15958
|
-
|
|
15959
|
-
|
|
15960
|
-
|
|
16017
|
+
const brokenDep = info.dependsOn.find((d) => failed.has(d));
|
|
16018
|
+
if (brokenDep !== void 0) {
|
|
16019
|
+
const depName = analysis.statements[brokenDep].tempTablesCreated[0] ?? `statement ${brokenDep}`;
|
|
16020
|
+
results.push({ ...base, status: "skipped", skippedReason: `dependency: ${depName}` });
|
|
16021
|
+
failed.add(i);
|
|
16022
|
+
continue;
|
|
16023
|
+
}
|
|
16024
|
+
if (deadline !== null && Date.now() >= deadline) {
|
|
16025
|
+
results.push({ ...base, status: "skipped", skippedReason: "timeout" });
|
|
16026
|
+
failed.add(i);
|
|
15961
16027
|
aborted = "timeout";
|
|
15962
|
-
|
|
15963
|
-
|
|
15964
|
-
|
|
15965
|
-
|
|
15966
|
-
|
|
15967
|
-
|
|
16028
|
+
continue;
|
|
16029
|
+
}
|
|
16030
|
+
try {
|
|
16031
|
+
const remaining = deadline !== null ? deadline - Date.now() : null;
|
|
16032
|
+
const userConfirm = batchOptions.confirm;
|
|
16033
|
+
const stmtOptions = userConfirm ? {
|
|
16034
|
+
...batchOptions,
|
|
16035
|
+
confirm: (count, operation, detailContext) => userConfirm(count, operation, {
|
|
16036
|
+
statementIndex: i,
|
|
16037
|
+
statementCount: statements.length,
|
|
16038
|
+
statementType: info.statementType,
|
|
16039
|
+
targetAppId: info.targetAppId,
|
|
16040
|
+
...detailContext?.importDetail ? { importDetail: detailContext.importDetail } : {},
|
|
16041
|
+
...detailContext?.applyDetail ? { applyDetail: detailContext.applyDetail } : {},
|
|
16042
|
+
...detailContext?.applyDiagnostic ? { applyDiagnostic: detailContext.applyDiagnostic } : {}
|
|
16043
|
+
})
|
|
16044
|
+
} : batchOptions;
|
|
16045
|
+
const searchAbortCollector = { aborted: false };
|
|
16046
|
+
const statementClient = wrapClientWithSearchAbort(
|
|
16047
|
+
countedClient,
|
|
16048
|
+
searchAbortCollector,
|
|
16049
|
+
info.statementType !== "SELECT" && info.statementType !== "UNION" && info.statementType !== "WITH" || statementContainsOuterJoin(statements[i])
|
|
16050
|
+
);
|
|
16051
|
+
const cursorScope = wrapClientWithCursorScope(statementClient);
|
|
16052
|
+
const outcome = await runWithDeadline(
|
|
16053
|
+
executeBatchStatement(statements[i], info, cursorScope.client, stmtOptions, cacheContext, tempTables, variables),
|
|
16054
|
+
remaining,
|
|
16055
|
+
cursorScope.closeActive
|
|
16056
|
+
);
|
|
16057
|
+
if (outcome.result) {
|
|
16058
|
+
outcome.result = attachSearchAbortWarning(outcome.result, searchAbortCollector);
|
|
16059
|
+
}
|
|
16060
|
+
results.push({ ...base, status: "success", ...outcome });
|
|
16061
|
+
} catch (e) {
|
|
16062
|
+
results.push({
|
|
16063
|
+
...base,
|
|
16064
|
+
status: "error",
|
|
16065
|
+
error: toBatchStatementError(e),
|
|
16066
|
+
...e instanceof RejectLimitExceededError ? { result: e.diagnostic } : {}
|
|
16067
|
+
});
|
|
16068
|
+
failed.add(i);
|
|
16069
|
+
if (e instanceof BatchTimeoutError) {
|
|
16070
|
+
aborted = "timeout";
|
|
16071
|
+
} else if (e instanceof AssertError) {
|
|
16072
|
+
aborted = "assertion";
|
|
16073
|
+
} else if (info.statementType === "SET_VARIABLE" || info.statementType === "DECLARE_VARIABLE") {
|
|
16074
|
+
aborted = "fail-fast";
|
|
16075
|
+
} else if (!options.continueOnError) {
|
|
16076
|
+
aborted = "fail-fast";
|
|
16077
|
+
}
|
|
15968
16078
|
}
|
|
15969
16079
|
}
|
|
16080
|
+
metrics.elapsedMs = Date.now() - startedAt;
|
|
16081
|
+
return {
|
|
16082
|
+
ok: results.every((r) => r.status === "success"),
|
|
16083
|
+
statementCount: statements.length,
|
|
16084
|
+
statements: results,
|
|
16085
|
+
analysis,
|
|
16086
|
+
metrics
|
|
16087
|
+
};
|
|
16088
|
+
} finally {
|
|
16089
|
+
releaseMetadataCacheScope(cacheContext);
|
|
15970
16090
|
}
|
|
15971
|
-
metrics.elapsedMs = Date.now() - startedAt;
|
|
15972
|
-
return {
|
|
15973
|
-
ok: results.every((r) => r.status === "success"),
|
|
15974
|
-
statementCount: statements.length,
|
|
15975
|
-
statements: results,
|
|
15976
|
-
analysis,
|
|
15977
|
-
metrics
|
|
15978
|
-
};
|
|
15979
16091
|
}
|
|
15980
16092
|
function statementHasApplyMutation(statement) {
|
|
15981
16093
|
if (statement.type === "UPDATE" || statement.type === "INSERT") {
|
|
@@ -16262,8 +16374,11 @@ function evaluateScalarExpr(expr) {
|
|
|
16262
16374
|
}
|
|
16263
16375
|
}
|
|
16264
16376
|
function resolveBatchVariableReferences(node, variables) {
|
|
16377
|
+
return resolveBatchVariableReferencesInternal(node, variables, false);
|
|
16378
|
+
}
|
|
16379
|
+
function resolveBatchVariableReferencesInternal(node, variables, numericArithmeticOperand) {
|
|
16265
16380
|
if (Array.isArray(node)) {
|
|
16266
|
-
return node.map((v) =>
|
|
16381
|
+
return node.map((v) => resolveBatchVariableReferencesInternal(v, variables, false));
|
|
16267
16382
|
}
|
|
16268
16383
|
if (node !== null && typeof node === "object") {
|
|
16269
16384
|
const obj = node;
|
|
@@ -16275,7 +16390,12 @@ function resolveBatchVariableReferences(node, variables) {
|
|
|
16275
16390
|
if (value.type === "array") {
|
|
16276
16391
|
throw new Error(`ParseError: array variable @${obj["name"]} can only be used as IN @${obj["name"]}.`);
|
|
16277
16392
|
}
|
|
16278
|
-
|
|
16393
|
+
if (numericArithmeticOperand && value.type !== "number" && value.placeholder !== true) {
|
|
16394
|
+
throw new Error(
|
|
16395
|
+
`ArgumentError: variable @${obj["name"]} is not numeric and cannot be used in arithmetic.`
|
|
16396
|
+
);
|
|
16397
|
+
}
|
|
16398
|
+
return numericArithmeticOperand && value.type === "string" && value.placeholder === true ? { type: "NUMBER", value: 0, raw: value.value } : value.type === "number" ? { type: "NUMBER", value: value.value, raw: value.raw ?? String(value.value) } : { type: "STRING", value: value.value };
|
|
16279
16399
|
}
|
|
16280
16400
|
if (obj["type"] === "VARIABLE_COL" && typeof obj["name"] === "string" && typeof obj["alias"] === "string") {
|
|
16281
16401
|
const value = variables.get(obj["name"]);
|
|
@@ -16285,7 +16405,14 @@ function resolveBatchVariableReferences(node, variables) {
|
|
|
16285
16405
|
}
|
|
16286
16406
|
if (obj["type"] === "VARIABLE_IN_LIST") return obj;
|
|
16287
16407
|
const resolved = Object.fromEntries(
|
|
16288
|
-
Object.entries(obj).map(([key, value]) => [
|
|
16408
|
+
Object.entries(obj).map(([key, value]) => [
|
|
16409
|
+
key,
|
|
16410
|
+
resolveBatchVariableReferencesInternal(
|
|
16411
|
+
value,
|
|
16412
|
+
variables,
|
|
16413
|
+
(obj["type"] === "ARITH" || obj["type"] === "SCALAR_ARITH" || obj["type"] === "AGG_ARITH") && (key === "left" || key === "right")
|
|
16414
|
+
)
|
|
16415
|
+
])
|
|
16289
16416
|
);
|
|
16290
16417
|
if (resolved["type"] === "BINARY") {
|
|
16291
16418
|
const right = resolved["right"];
|
|
@@ -16440,6 +16567,11 @@ function withScalarProbeLimit(query) {
|
|
|
16440
16567
|
return { query: { ...query, limit: 2 }, probed: true };
|
|
16441
16568
|
}
|
|
16442
16569
|
function evalAssertArith(node) {
|
|
16570
|
+
if (node.type === "VARIABLE") {
|
|
16571
|
+
throw new Error(
|
|
16572
|
+
`InternalError: unresolved arithmetic variable @${node.name} reached ASSERT evaluation.`
|
|
16573
|
+
);
|
|
16574
|
+
}
|
|
16443
16575
|
if (node.type === "NUMBER") return node.value;
|
|
16444
16576
|
if (node.type === "ARITH") {
|
|
16445
16577
|
const left = evalAssertArith(node.left);
|
|
@@ -16956,6 +17088,11 @@ function isNoFromSelect(stmt) {
|
|
|
16956
17088
|
return stmt.from.appId === 0 && stmt.from.cteName === NO_FROM_CTE_NAME;
|
|
16957
17089
|
}
|
|
16958
17090
|
function arithHasFieldRef(node) {
|
|
17091
|
+
if (node.type === "VARIABLE") {
|
|
17092
|
+
throw new Error(
|
|
17093
|
+
`InternalError: unresolved arithmetic variable @${node.name} reached SELECT planning.`
|
|
17094
|
+
);
|
|
17095
|
+
}
|
|
16959
17096
|
if (node.type === "FIELD_REF") return true;
|
|
16960
17097
|
if (node.type === "ARITH") return arithHasFieldRef(node.left) || arithHasFieldRef(node.right);
|
|
16961
17098
|
if (node.type === "STRING_FUNC") return stringFuncHasFieldRef(node);
|
|
@@ -17098,7 +17235,7 @@ async function executeSimpleSelect(stmt, client, options, cacheContext, orderPla
|
|
|
17098
17235
|
);
|
|
17099
17236
|
rows = applyLimit(rows, stmt.limit, stmt.offset);
|
|
17100
17237
|
}
|
|
17101
|
-
const { rows: projected, columns } = project(
|
|
17238
|
+
const { rows: projected, columns: projectedColumns } = project(
|
|
17102
17239
|
rows,
|
|
17103
17240
|
stmt.columns,
|
|
17104
17241
|
void 0,
|
|
@@ -17106,6 +17243,13 @@ async function executeSimpleSelect(stmt, client, options, cacheContext, orderPla
|
|
|
17106
17243
|
void 0,
|
|
17107
17244
|
projectionSemanticsResolver
|
|
17108
17245
|
);
|
|
17246
|
+
const columns = await restoreEmptyWildcardColumns(
|
|
17247
|
+
stmt,
|
|
17248
|
+
projected,
|
|
17249
|
+
projectedColumns,
|
|
17250
|
+
client,
|
|
17251
|
+
cacheContext
|
|
17252
|
+
);
|
|
17109
17253
|
return { type: "SELECT", rows: projected, columns, rowCount: projected.length, warnings: [...warnings] };
|
|
17110
17254
|
}
|
|
17111
17255
|
async function validateSelectFieldCodes(stmt, mode, client, cacheContext) {
|
|
@@ -18082,7 +18226,7 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
18082
18226
|
tables.set(join2.table.alias, joinRecords);
|
|
18083
18227
|
}));
|
|
18084
18228
|
const { optionOrders, sortKinds, semantics } = await orderByMetaPromise;
|
|
18085
|
-
const { rows, columns } = runFullScan({
|
|
18229
|
+
const { rows, columns: projectedColumns } = runFullScan({
|
|
18086
18230
|
tables,
|
|
18087
18231
|
stmt,
|
|
18088
18232
|
scalarCache,
|
|
@@ -18099,6 +18243,13 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
18099
18243
|
resolvedGroupingSpec: resolvedGroupingSpecs.get(stmt),
|
|
18100
18244
|
plainGroupByPlan
|
|
18101
18245
|
});
|
|
18246
|
+
const columns = await restoreEmptyWildcardColumns(
|
|
18247
|
+
stmt,
|
|
18248
|
+
rows,
|
|
18249
|
+
projectedColumns,
|
|
18250
|
+
client,
|
|
18251
|
+
cacheContext
|
|
18252
|
+
);
|
|
18102
18253
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
18103
18254
|
}
|
|
18104
18255
|
async function executeUnion(stmt, client, options, cacheContext, captureColumnMeta = false, forLibraryCapture = false) {
|
|
@@ -18341,7 +18492,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
18341
18492
|
await Promise.all(joinFetches);
|
|
18342
18493
|
const { optionOrders, sortKinds, semantics } = await orderByMetaPromise;
|
|
18343
18494
|
const sourceColumns2 = stmt.joins.length === 0 && stmt.from.cteName != null ? requireMaterializedTable(stmt.from.cteName).columns : void 0;
|
|
18344
|
-
const { rows, columns } = runFullScan({
|
|
18495
|
+
const { rows, columns: projectedColumns } = runFullScan({
|
|
18345
18496
|
tables,
|
|
18346
18497
|
stmt,
|
|
18347
18498
|
scalarCache,
|
|
@@ -18360,8 +18511,26 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
18360
18511
|
resolvedGroupingSpec,
|
|
18361
18512
|
plainGroupByPlan
|
|
18362
18513
|
});
|
|
18514
|
+
const columns = await restoreEmptyWildcardColumns(
|
|
18515
|
+
stmt,
|
|
18516
|
+
rows,
|
|
18517
|
+
projectedColumns,
|
|
18518
|
+
client,
|
|
18519
|
+
cacheContext
|
|
18520
|
+
);
|
|
18363
18521
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
18364
18522
|
}
|
|
18523
|
+
async function restoreEmptyWildcardColumns(stmt, rows, columns, client, cacheContext) {
|
|
18524
|
+
if (rows.length !== 0 || columns.length !== 0 || stmt.columns.length !== 1 || stmt.columns[0].type !== "WILDCARD" || stmt.joins.length !== 0 || stmt.from.cteName !== null) {
|
|
18525
|
+
return [...columns];
|
|
18526
|
+
}
|
|
18527
|
+
const fields = await getFieldsCached(stmt.from.appId, client, cacheContext);
|
|
18528
|
+
return deriveEmptyWildcardColumns(
|
|
18529
|
+
fields,
|
|
18530
|
+
stmt.from.subtableCode,
|
|
18531
|
+
() => getProcessStatusesCached(stmt.from.appId, client, cacheContext)
|
|
18532
|
+
);
|
|
18533
|
+
}
|
|
18365
18534
|
function processRowToKintoneRecord(row) {
|
|
18366
18535
|
return Object.fromEntries(
|
|
18367
18536
|
Object.entries(row).map(([k, v]) => [k, { value: v ?? "" }])
|
|
@@ -18561,6 +18730,14 @@ var sortKindCache = /* @__PURE__ */ new Map();
|
|
|
18561
18730
|
var fieldInfoCache = /* @__PURE__ */ new Map();
|
|
18562
18731
|
var processStatusCache = /* @__PURE__ */ new Map();
|
|
18563
18732
|
var numberPrecisionCache = /* @__PURE__ */ new Map();
|
|
18733
|
+
function releaseMetadataCacheScope(cacheContext) {
|
|
18734
|
+
fieldTypeCache.delete(cacheContext);
|
|
18735
|
+
optionOrderCache.delete(cacheContext);
|
|
18736
|
+
sortKindCache.delete(cacheContext);
|
|
18737
|
+
fieldInfoCache.delete(cacheContext);
|
|
18738
|
+
processStatusCache.delete(cacheContext);
|
|
18739
|
+
numberPrecisionCache.delete(cacheContext);
|
|
18740
|
+
}
|
|
18564
18741
|
function getScopedCacheValue(root, cacheContext, appId) {
|
|
18565
18742
|
return root.get(cacheContext)?.get(appId);
|
|
18566
18743
|
}
|
|
@@ -22232,45 +22409,50 @@ function serverFunctionClientEvaluationLabel(leaves) {
|
|
|
22232
22409
|
) ? "relative date client evaluations" : "kintone function client evaluations";
|
|
22233
22410
|
}
|
|
22234
22411
|
async function buildBatchExplainPlans(sql, client, injectedVariables, cacheContext = "batch-explain", maxRecords = 1e4, cursorMaxActive = 2, enableImport = false, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS) {
|
|
22235
|
-
const
|
|
22236
|
-
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
|
|
22240
|
-
|
|
22241
|
-
const
|
|
22242
|
-
|
|
22243
|
-
|
|
22244
|
-
|
|
22245
|
-
|
|
22246
|
-
planStmt,
|
|
22247
|
-
|
|
22248
|
-
cacheContext,
|
|
22249
|
-
maxRecords,
|
|
22250
|
-
relativeDatePlan
|
|
22251
|
-
);
|
|
22252
|
-
const statementPlan = relativeDatePlan.hasServerOnlyWhereFunction && !relativeDatePlan.allowed ? relativeDateExplainLines(relativeDatePlan) : [
|
|
22253
|
-
...relativeDateExplainLines(relativeDatePlan),
|
|
22254
|
-
...addCursorConcurrency(buildBatchStatementPlan(
|
|
22412
|
+
const invocationCacheContext = createInvocationCacheContext(cacheContext);
|
|
22413
|
+
try {
|
|
22414
|
+
const statements = parseSqlBatch(sql, enableImport);
|
|
22415
|
+
const analysis = analyzeBatch(statements);
|
|
22416
|
+
validateDeclaredBatchVariables(statements, injectedVariables);
|
|
22417
|
+
const variables = /* @__PURE__ */ new Map();
|
|
22418
|
+
const plans = [];
|
|
22419
|
+
for (let i = 0; i < statements.length; i++) {
|
|
22420
|
+
const stmt = statements[i];
|
|
22421
|
+
const planStmt = stmt.type === "SET_VARIABLE" ? stmt.expr.type === "SCALAR_SUBQUERY" ? { ...stmt, expr: resolveBatchVariableReferences(stmt.expr, variables) } : stmt : resolveBatchVariableReferences(stmt, variables);
|
|
22422
|
+
validateKlikeStatement(planStmt);
|
|
22423
|
+
const relativeDatePlan = await resolveRelativeDateExecutionPlan(planStmt, client, invocationCacheContext);
|
|
22424
|
+
const whereAnalysis = await buildExplainWhereAnalysis(
|
|
22255
22425
|
planStmt,
|
|
22256
|
-
|
|
22257
|
-
|
|
22258
|
-
|
|
22259
|
-
|
|
22260
|
-
|
|
22261
|
-
)
|
|
22262
|
-
|
|
22263
|
-
|
|
22264
|
-
|
|
22265
|
-
|
|
22266
|
-
|
|
22267
|
-
|
|
22268
|
-
|
|
22269
|
-
|
|
22270
|
-
|
|
22426
|
+
client,
|
|
22427
|
+
invocationCacheContext,
|
|
22428
|
+
maxRecords,
|
|
22429
|
+
relativeDatePlan
|
|
22430
|
+
);
|
|
22431
|
+
const statementPlan = relativeDatePlan.hasServerOnlyWhereFunction && !relativeDatePlan.allowed ? relativeDateExplainLines(relativeDatePlan) : [
|
|
22432
|
+
...relativeDateExplainLines(relativeDatePlan),
|
|
22433
|
+
...addCursorConcurrency(buildBatchStatementPlan(
|
|
22434
|
+
planStmt,
|
|
22435
|
+
analysis.statements[i],
|
|
22436
|
+
whereAnalysis.capabilities,
|
|
22437
|
+
whereAnalysis.orderPlans,
|
|
22438
|
+
dmlMaxRows,
|
|
22439
|
+
dmlMaxSubtableRows
|
|
22440
|
+
), cursorMaxActive)
|
|
22441
|
+
];
|
|
22442
|
+
const metadataPlan = explainMetadataLines(whereAnalysis);
|
|
22443
|
+
plans.push({
|
|
22444
|
+
index: i,
|
|
22445
|
+
type: analysis.statements[i].statementType,
|
|
22446
|
+
plan: statementPlan.length === 0 ? metadataPlan : [statementPlan[0], ...metadataPlan, ...statementPlan.slice(1)]
|
|
22447
|
+
});
|
|
22448
|
+
if (stmt.type === "SET_VARIABLE" || stmt.type === "DECLARE_VARIABLE") {
|
|
22449
|
+
variables.set(stmt.name, stmt.type === "SET_VARIABLE" && stmt.expr.type === "ARRAY" ? { type: "array", elements: stmt.expr.elements.map((element) => ({ type: "string", value: element.value })) } : { type: "string", value: `@${stmt.name}`, placeholder: true });
|
|
22450
|
+
}
|
|
22271
22451
|
}
|
|
22452
|
+
return { statementCount: statements.length, statements: plans };
|
|
22453
|
+
} finally {
|
|
22454
|
+
releaseMetadataCacheScope(invocationCacheContext);
|
|
22272
22455
|
}
|
|
22273
|
-
return { statementCount: statements.length, statements: plans };
|
|
22274
22456
|
}
|
|
22275
22457
|
function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS) {
|
|
22276
22458
|
if (stmt.type === "CREATE_TEMP_TABLE") {
|
|
@@ -23050,6 +23232,11 @@ function collectArithRefFields(stmt) {
|
|
|
23050
23232
|
return [...refs];
|
|
23051
23233
|
}
|
|
23052
23234
|
function collectArithNodeRefs(node, out) {
|
|
23235
|
+
if (node.type === "VARIABLE") {
|
|
23236
|
+
throw new Error(
|
|
23237
|
+
`InternalError: unresolved arithmetic variable @${node.name} reached CHECK field collection.`
|
|
23238
|
+
);
|
|
23239
|
+
}
|
|
23053
23240
|
if (node.type === "FIELD_REF") {
|
|
23054
23241
|
out.add(node.field);
|
|
23055
23242
|
return;
|
|
@@ -23145,6 +23332,11 @@ function formatArithExprStr(expr) {
|
|
|
23145
23332
|
return `${formatArithNodeStr(expr.left)} ${expr.op} ${formatArithNodeStr(expr.right)}`;
|
|
23146
23333
|
}
|
|
23147
23334
|
function formatArithNodeStr(node) {
|
|
23335
|
+
if (node.type === "VARIABLE") {
|
|
23336
|
+
throw new Error(
|
|
23337
|
+
`InternalError: unresolved arithmetic variable @${node.name} reached arithmetic formatting.`
|
|
23338
|
+
);
|
|
23339
|
+
}
|
|
23148
23340
|
if (node.type === "FIELD_REF") return node.field;
|
|
23149
23341
|
if (node.type === "NUMBER") return numberLiteralText(node);
|
|
23150
23342
|
if (node.type === "ARITH") return `(${formatArithExprStr(node)})`;
|