@rex0220/kintone-sql-tools 3.30.0 → 3.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist-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 = resolveCacheContext(client, options.cacheContext);
15302
- const stmt = parseSql(sql, options.enableImport === true);
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
- metrics.elapsedMs = Date.now() - startedAt;
15318
- const finalResult = { ...attachSearchAbortWarning(result, collector), metrics };
15319
- if (result.type === "SELECT") {
15320
- const columnMeta = materializedMetaBySelectResult.get(result);
15321
- if (columnMeta) materializedMetaBySelectResult.set(finalResult, columnMeta);
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 = resolveCacheContext(client, options.cacheContext);
15895
- const tempTables = /* @__PURE__ */ new Map();
15896
- const variables = /* @__PURE__ */ new Map();
15897
- const results = [];
15898
- const failed = /* @__PURE__ */ new Set();
15899
- let aborted = null;
15900
- for (let i = 0; i < statements.length; i++) {
15901
- const info = analysis.statements[i];
15902
- const base = { index: i, type: info.statementType };
15903
- if (aborted) {
15904
- results.push({ ...base, status: "skipped", skippedReason: aborted });
15905
- failed.add(i);
15906
- continue;
15907
- }
15908
- const brokenDep = info.dependsOn.find((d) => failed.has(d));
15909
- if (brokenDep !== void 0) {
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
- results.push({ ...base, status: "success", ...outcome });
15952
- } catch (e) {
15953
- results.push({
15954
- ...base,
15955
- status: "error",
15956
- error: toBatchStatementError(e),
15957
- ...e instanceof RejectLimitExceededError ? { result: e.diagnostic } : {}
15958
- });
15959
- failed.add(i);
15960
- if (e instanceof BatchTimeoutError) {
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
- } else if (e instanceof AssertError) {
15963
- aborted = "assertion";
15964
- } else if (info.statementType === "SET_VARIABLE" || info.statementType === "DECLARE_VARIABLE") {
15965
- aborted = "fail-fast";
15966
- } else if (!options.continueOnError) {
15967
- aborted = "fail-fast";
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) => resolveBatchVariableReferences(v, variables));
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,6 +16390,11 @@ 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
  }
16393
+ if (numericArithmeticOperand && value.type !== "number") {
16394
+ throw new Error(
16395
+ `ArgumentError: variable @${obj["name"]} is not numeric and cannot be used in arithmetic.`
16396
+ );
16397
+ }
16278
16398
  return 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") {
@@ -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]) => [key, resolveBatchVariableReferences(value, variables)])
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 statements = parseSqlBatch(sql, enableImport);
22236
- const analysis = analyzeBatch(statements);
22237
- validateDeclaredBatchVariables(statements, injectedVariables);
22238
- const variables = /* @__PURE__ */ new Map();
22239
- const plans = [];
22240
- for (let i = 0; i < statements.length; i++) {
22241
- const stmt = statements[i];
22242
- const planStmt = stmt.type === "SET_VARIABLE" ? stmt.expr.type === "SCALAR_SUBQUERY" ? { ...stmt, expr: resolveBatchVariableReferences(stmt.expr, variables) } : stmt : resolveBatchVariableReferences(stmt, variables);
22243
- validateKlikeStatement(planStmt);
22244
- const relativeDatePlan = await resolveRelativeDateExecutionPlan(planStmt, client, cacheContext);
22245
- const whereAnalysis = await buildExplainWhereAnalysis(
22246
- planStmt,
22247
- client,
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
- analysis.statements[i],
22257
- whereAnalysis.capabilities,
22258
- whereAnalysis.orderPlans,
22259
- dmlMaxRows,
22260
- dmlMaxSubtableRows
22261
- ), cursorMaxActive)
22262
- ];
22263
- const metadataPlan = explainMetadataLines(whereAnalysis);
22264
- plans.push({
22265
- index: i,
22266
- type: analysis.statements[i].statementType,
22267
- plan: statementPlan.length === 0 ? metadataPlan : [statementPlan[0], ...metadataPlan, ...statementPlan.slice(1)]
22268
- });
22269
- if (stmt.type === "SET_VARIABLE" || stmt.type === "DECLARE_VARIABLE") {
22270
- 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}` });
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}` });
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)})`;