@rex0220/kintone-sql-tools 3.15.0 → 3.16.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.
@@ -32371,6 +32371,121 @@ function numberLiteralText(node) {
32371
32371
  return toPlainDecimal(source) ?? source;
32372
32372
  }
32373
32373
 
32374
+ // src/core/aggregateExpression.ts
32375
+ init_define_KSQL_DOCS();
32376
+ function quote(value) {
32377
+ return `'${value.replace(/'/g, "''")}'`;
32378
+ }
32379
+ function arithLabel(node, topLevel = false) {
32380
+ if (node.type === "FIELD_REF") return node.field;
32381
+ if (node.type === "NUMBER") return numberLiteralText(node);
32382
+ if (node.type === "STRING_FUNC") return stringFuncLabel(node);
32383
+ const label = `${arithLabel(node.left)}${node.op}${arithLabel(node.right)}`;
32384
+ return topLevel ? label : `(${label})`;
32385
+ }
32386
+ function fieldValueLabel(value) {
32387
+ if (value.type === "FIELD") return value.tableAlias ? `${value.tableAlias}.${value.field}` : value.field;
32388
+ if (value.type === "FUNC_FIELD") return stringFuncLabel(value.expr);
32389
+ if (value.type === "ARITH_FIELD") return arithLabel(value.expr);
32390
+ return caseLabel(value.expr);
32391
+ }
32392
+ function sqlValueLabel(value) {
32393
+ switch (value.type) {
32394
+ case "STRING":
32395
+ return quote(value.value);
32396
+ case "NUMBER":
32397
+ return numberLiteralText(value);
32398
+ case "VARIABLE":
32399
+ return `@${value.name}`;
32400
+ case "VARIABLE_IN_LIST":
32401
+ return `@${value.name}`;
32402
+ case "KINTONE_FUNC":
32403
+ return `${value.name}()`;
32404
+ case "ARRAY":
32405
+ return `[${value.elements.map((entry) => quote(entry.value)).join(",")}]`;
32406
+ case "IN_LIST":
32407
+ return `(${value.values.map(sqlValueLabel).join(",")})`;
32408
+ case "ARITH_VALUE":
32409
+ return arithLabel(value.expr);
32410
+ case "CASE_VALUE":
32411
+ return caseLabel(value.expr);
32412
+ case "SUBQUERY_IN_LIST":
32413
+ return "(SUBQUERY)";
32414
+ case "SCALAR_SUBQUERY":
32415
+ return "(SUBQUERY)";
32416
+ }
32417
+ }
32418
+ function whereLabel(expr) {
32419
+ switch (expr.type) {
32420
+ case "BINARY":
32421
+ return `${fieldValueLabel(expr.left)} ${expr.op.replace("_", " ")} ${sqlValueLabel(expr.right)}`;
32422
+ case "NULL_CHECK":
32423
+ return `${fieldValueLabel(expr.field)} IS ${expr.not ? "NOT " : ""}NULL`;
32424
+ case "LOGICAL":
32425
+ return `(${whereLabel(expr.left)} ${expr.op} ${whereLabel(expr.right)})`;
32426
+ case "NOT":
32427
+ return `NOT (${whereLabel(expr.expr)})`;
32428
+ case "GROUP":
32429
+ return `(${whereLabel(expr.expr)})`;
32430
+ case "BOOLEAN":
32431
+ return expr.value ? "TRUE" : "FALSE";
32432
+ case "EXISTS":
32433
+ return `${expr.not ? "NOT " : ""}EXISTS (SUBQUERY)`;
32434
+ }
32435
+ }
32436
+ function caseResultLabel(result) {
32437
+ if (result.type === "ARRAY") return `[${result.elements.map((entry) => quote(entry.value)).join(",")}]`;
32438
+ if (result.type === "FIELD_REF" || result.type === "ARITH") return arithLabel(result);
32439
+ return scalarValueLabel(result);
32440
+ }
32441
+ function caseLabel(expr) {
32442
+ const branches = expr.branches.map((branch) => `WHEN ${whereLabel(branch.condition)} THEN ${caseResultLabel(branch.result)}`).join(" ");
32443
+ const otherwise = expr.elseResult === null ? "" : ` ELSE ${caseResultLabel(expr.elseResult)}`;
32444
+ return `CASE ${branches}${otherwise} END`;
32445
+ }
32446
+ function stringFuncArgLabel(arg) {
32447
+ if (arg.type === "AGG_REF") return aggregateSyntheticName(arg.func, arg.distinct, arg.arg);
32448
+ if (arg.type === "AGG_ARITH") return aggregateOperandLabel(arg);
32449
+ return scalarValueLabel(arg);
32450
+ }
32451
+ function stringFuncLabel(expr) {
32452
+ return `${expr.func}(${expr.args.map(stringFuncArgLabel).join(",")})`;
32453
+ }
32454
+ function scalarValueLabel(expr) {
32455
+ switch (expr.type) {
32456
+ case "STRING":
32457
+ return quote(expr.value);
32458
+ case "NUMBER":
32459
+ return numberLiteralText(expr);
32460
+ case "VARIABLE":
32461
+ return `@${expr.name}`;
32462
+ case "FIELD":
32463
+ return expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field;
32464
+ case "STRING_FUNC":
32465
+ return stringFuncLabel(expr);
32466
+ case "CASE_WHEN":
32467
+ return caseLabel(expr);
32468
+ case "SCALAR_ARITH":
32469
+ return `(${scalarValueLabel(expr.left)}${expr.op}${scalarValueLabel(expr.right)})`;
32470
+ case "CONCAT_OP":
32471
+ return `(${scalarValueLabel(expr.left)}||${scalarValueLabel(expr.right)})`;
32472
+ }
32473
+ }
32474
+ function aggregateArgLabel(arg) {
32475
+ if (arg.type === "WILDCARD") return "*";
32476
+ if (arg.type === "FIELD_REF" || arg.type === "ARITH") return arithLabel(arg, true);
32477
+ return scalarValueLabel(arg);
32478
+ }
32479
+ function aggregateSyntheticName(func, distinct, arg) {
32480
+ const label = aggregateArgLabel(arg);
32481
+ return distinct ? `${func}(DISTINCT ${label})` : `${func}(${label})`;
32482
+ }
32483
+ function aggregateOperandLabel(node) {
32484
+ if (node.type === "NUMBER") return numberLiteralText(node);
32485
+ if (node.type === "AGG_REF") return aggregateSyntheticName(node.func, node.distinct, node.arg);
32486
+ return `${aggregateOperandLabel(node.left)}${node.op}${aggregateOperandLabel(node.right)}`;
32487
+ }
32488
+
32374
32489
  // src/parser/parser.ts
32375
32490
  var MAX_BATCH_STATEMENTS = 20;
32376
32491
  var PARSER_SCALAR_FUNCTION_TOKEN_MAP = Object.freeze({
@@ -32574,6 +32689,7 @@ var Parser = class {
32574
32689
  this.scalarAllowsAggregateArgs = true;
32575
32690
  this.scalarAllowsCase = true;
32576
32691
  this.pos = 0;
32692
+ this.insideAggregateArg = 0;
32577
32693
  /** WITH 句で定義された CTE 名のセット(parseTableRef で参照) */
32578
32694
  this.cteNames = /* @__PURE__ */ new Set();
32579
32695
  /** パース中に出現した一時テーブル参照(#name)のトークン。単文 API での拒否に使う */
@@ -33402,7 +33518,7 @@ var Parser = class {
33402
33518
  if (this.consume("*" /* STAR */)) {
33403
33519
  return { type: "WILDCARD" };
33404
33520
  }
33405
- if (this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
33521
+ if (this.tryAggregateFunc() === null && this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
33406
33522
  const expr = this.parseScalarValueExpr({ allowAggregateArgs: true });
33407
33523
  const alias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
33408
33524
  return { type: "SCALAR_VALUE_COL", expr, alias: alias2 };
@@ -33674,7 +33790,12 @@ var Parser = class {
33674
33790
  if (!allowCase) throw new ParseError("\u3053\u306E\u30B9\u30AB\u30E9\u30FC\u5024\u5F0F\u3067\u306F CASE \u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", tok);
33675
33791
  return this.parseCaseWhenExpr();
33676
33792
  }
33677
- if (this.tryAggregateFunc() !== null) throw new ParseError("\u30B9\u30AB\u30E9\u30FC\u5024\u5F0F\u306B\u96C6\u7D04\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", tok);
33793
+ if (this.tryAggregateFunc() !== null) {
33794
+ throw new ParseError(
33795
+ this.insideAggregateArg > 0 ? "\u96C6\u8A08\u95A2\u6570\u306E\u5F15\u6570\u5185\u306B\u96C6\u8A08\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093" : "\u30B9\u30AB\u30E9\u30FC\u5024\u5F0F\u306B\u96C6\u7D04\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093",
33796
+ tok
33797
+ );
33798
+ }
33678
33799
  if (this.tryStringFuncName() !== null) return this.parseStringFuncExpr();
33679
33800
  if (tok.kind === "IDENT" /* IDENT */ || tok.kind === "BIDENT" /* BIDENT */) {
33680
33801
  this.advance();
@@ -33823,6 +33944,9 @@ var Parser = class {
33823
33944
  /** THEN / ELSE の結果値。`||` を含む場合だけ新スカラー文法へ渡す。 */
33824
33945
  parseCaseResult() {
33825
33946
  const tok = this.peek();
33947
+ if (this.insideAggregateArg > 0 && this.tryAggregateFunc() !== null) {
33948
+ throw new ParseError("\u96C6\u8A08\u95A2\u6570\u306E\u5F15\u6570\u5185\u306B\u96C6\u8A08\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", tok);
33949
+ }
33826
33950
  if (tok.kind === "[" /* LBRACKET */) {
33827
33951
  return this.parseArrayLiteral();
33828
33952
  }
@@ -33966,7 +34090,7 @@ var Parser = class {
33966
34090
  }
33967
34091
  arg = { type: "WILDCARD" };
33968
34092
  } else {
33969
- arg = this.parseArithAddSub();
34093
+ arg = this.parseAggregateArgExpr();
33970
34094
  }
33971
34095
  let separator;
33972
34096
  if (this.isSoftKeyword("SEPARATOR")) {
@@ -33985,6 +34109,60 @@ var Parser = class {
33985
34109
  ...separator !== void 0 ? { separator } : {}
33986
34110
  };
33987
34111
  }
34112
+ isAggregateArgEnd() {
34113
+ return this.peek().kind === ")" /* RPAREN */ || this.isSoftKeyword("SEPARATOR");
34114
+ }
34115
+ /** 旧算術 AST を優先し、新規形だけ ScalarValueExpr として読む。 */
34116
+ parseAggregateArgExpr() {
34117
+ const start = this.pos;
34118
+ try {
34119
+ const legacy = this.parseArithAddSub();
34120
+ if (this.isAggregateArgEnd()) return legacy;
34121
+ } catch {
34122
+ }
34123
+ this.pos = start;
34124
+ this.insideAggregateArg++;
34125
+ try {
34126
+ let expr;
34127
+ try {
34128
+ expr = this.parseScalarValueExpr({ allowCase: true, allowAggregateArgs: false });
34129
+ } catch (error51) {
34130
+ if (error51 instanceof ParseError) {
34131
+ if (error51.message.includes("\u6BD4\u8F03\u30FB\u8FF0\u8A9E")) {
34132
+ throw new ParseError(
34133
+ "\u96C6\u8A08\u95A2\u6570\u306E\u5F15\u6570\u306B\u6BD4\u8F03\u30FB\u8FF0\u8A9E\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002CASE \u3067\u5024\u3092\u660E\u793A\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u4F8B: SUM(CASE WHEN amount > 0 THEN 1 ELSE 0 END)",
34134
+ error51.token
34135
+ );
34136
+ }
34137
+ if (error51.message.includes("\u96C6\u7D04\u95A2\u6570")) {
34138
+ throw new ParseError("\u96C6\u8A08\u95A2\u6570\u306E\u5F15\u6570\u5185\u306B\u96C6\u8A08\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", error51.token);
34139
+ }
34140
+ }
34141
+ throw error51;
34142
+ }
34143
+ if (!this.isAggregateArgEnd()) {
34144
+ throw new ParseError(
34145
+ "\u3053\u306E\u96C6\u8A08\u95A2\u6570\u306E\u5F15\u6570\u5F62\u5F0F\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002CASE \u3067\u5024\u3092\u660E\u793A\u3059\u308B\u304B\u3001CTE \u3067\u5F0F\u3092\u5217\u306B\u3057\u3066\u304B\u3089\u96C6\u8A08\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
34146
+ this.peek()
34147
+ );
34148
+ }
34149
+ this.assertNoNestedAggregate(expr);
34150
+ return expr;
34151
+ } finally {
34152
+ this.insideAggregateArg--;
34153
+ }
34154
+ }
34155
+ assertNoNestedAggregate(expr) {
34156
+ const visit = (value) => {
34157
+ if (value === null || typeof value !== "object") return;
34158
+ const node = value;
34159
+ if (node.type === "AGG_REF" || node.type === "AGG_ARITH") {
34160
+ throw new ParseError("\u96C6\u8A08\u95A2\u6570\u306E\u5F15\u6570\u5185\u306B\u96C6\u8A08\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", this.peek());
34161
+ }
34162
+ for (const child of Object.values(node)) visit(child);
34163
+ };
34164
+ visit(expr);
34165
+ }
33988
34166
  // ----------------------------------------------------------
33989
34167
  // FROM / JOIN
33990
34168
  // ----------------------------------------------------------
@@ -34253,31 +34431,11 @@ var Parser = class {
34253
34431
  }
34254
34432
  const aggFunc = this.tryAggregateFunc();
34255
34433
  if (aggFunc !== null) {
34256
- this.advance();
34257
- this.expect("(" /* LPAREN */);
34258
- const distinct = this.consume("DISTINCT" /* DISTINCT */);
34259
- const distinctToken = distinct ? this.prev() : null;
34260
- if (aggFunc === "MODE" && distinctToken) {
34261
- throw new ParseError("MODE \u3067\u306F DISTINCT \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", distinctToken);
34262
- }
34263
- let argStr;
34264
- if (this.consume("*" /* STAR */)) {
34265
- if (!aggregateAcceptsWildcard(aggFunc)) {
34266
- throw new ParseError(`${aggFunc}(*) \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u30D5\u30A3\u30FC\u30EB\u30C9\u307E\u305F\u306F\u5F0F\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`, this.prev());
34267
- }
34268
- argStr = "*";
34269
- } else {
34270
- argStr = this.parseIdentifier();
34271
- }
34272
- if (this.isSoftKeyword("SEPARATOR")) {
34273
- const separatorToken = this.advance();
34274
- if (aggFunc !== "GROUP_CONCAT") {
34275
- throw new ParseError("SEPARATOR \u306F GROUP_CONCAT \u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059", separatorToken);
34276
- }
34277
- this.expect("STRING" /* STRING */, "SEPARATOR \u306E\u5F8C\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059");
34434
+ if (this.insideAggregateArg > 0) {
34435
+ throw new ParseError("\u96C6\u8A08\u95A2\u6570\u306E\u5F15\u6570\u5185\u306B\u96C6\u8A08\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", this.peek());
34278
34436
  }
34279
- this.expect(")" /* RPAREN */);
34280
- const syntheticName = distinct ? `${aggFunc}(DISTINCT ${argStr})` : `${aggFunc}(${argStr})`;
34437
+ const ref = this.parseAggregateRef(aggFunc);
34438
+ const syntheticName = aggregateSyntheticName(ref.func, ref.distinct, ref.arg);
34281
34439
  return { type: "FIELD", tableAlias: null, field: syntheticName };
34282
34440
  }
34283
34441
  if (this.peek().kind === "CASE" /* CASE */) {
@@ -36422,7 +36580,7 @@ function collectCaseResultScalarFields(result, out) {
36422
36580
  }
36423
36581
  function collectAggOperandFields(node, out) {
36424
36582
  if (node.type === "AGG_REF") {
36425
- if (node.arg.type !== "WILDCARD") collectArithNode(node.arg, out);
36583
+ if (node.arg.type !== "WILDCARD") collectAggregateArgFields(node.arg, out);
36426
36584
  return;
36427
36585
  }
36428
36586
  if (node.type === "AGG_ARITH") {
@@ -36430,6 +36588,10 @@ function collectAggOperandFields(node, out) {
36430
36588
  collectAggOperandFields(node.right, out);
36431
36589
  }
36432
36590
  }
36591
+ function collectAggregateArgFields(node, out) {
36592
+ if (node.type === "FIELD_REF" || node.type === "ARITH") collectArithNode(node, out);
36593
+ else collectScalarValueFields(node, out);
36594
+ }
36433
36595
  function hasAggregateInStringFuncExpr(expr) {
36434
36596
  return expr.args.some((arg) => {
36435
36597
  if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
@@ -36575,7 +36737,7 @@ function collectRequiredFieldsByTable(stmt) {
36575
36737
  };
36576
36738
  const walkAgg = (node, phase = "select") => {
36577
36739
  if (node.type === "AGG_REF") {
36578
- if (node.arg.type !== "WILDCARD") walkArith(node.arg, phase);
36740
+ if (node.arg.type !== "WILDCARD") walkAggregateArg(node.arg, phase);
36579
36741
  return;
36580
36742
  }
36581
36743
  if (node.type === "AGG_ARITH") {
@@ -36609,6 +36771,13 @@ function collectRequiredFieldsByTable(stmt) {
36609
36771
  }
36610
36772
  if (expr.type === "CASE_WHEN") walkCase(expr, phase);
36611
36773
  };
36774
+ const walkAggregateArg = (expr, phase = "select") => {
36775
+ if (expr.type === "FIELD_REF" || expr.type === "ARITH") {
36776
+ walkArith(expr, phase);
36777
+ return;
36778
+ }
36779
+ walkScalar(expr, phase);
36780
+ };
36612
36781
  const walkCaseResult = (result, phase = "select") => {
36613
36782
  if (result.type === "ARRAY") return;
36614
36783
  if (result.type === "FIELD_REF" || result.type === "ARITH") {
@@ -36710,7 +36879,7 @@ function collectRequiredFieldsByTable(stmt) {
36710
36879
  case "VARIABLE_COL":
36711
36880
  throw new Error(`internal error: unresolved SELECT variable @${col.name}`);
36712
36881
  case "AGGREGATE":
36713
- if (col.arg.type !== "WILDCARD") walkArith(col.arg, "select");
36882
+ if (col.arg.type !== "WILDCARD") walkAggregateArg(col.arg, "select");
36714
36883
  break;
36715
36884
  case "ARITH_AGG_COL":
36716
36885
  walkAgg(col.expr, "select");
@@ -36791,44 +36960,6 @@ function collectSelectOutputNames(columns) {
36791
36960
  }
36792
36961
  return names;
36793
36962
  }
36794
- function aggregateSyntheticName(func, distinct, arg) {
36795
- const argStr = arg.type === "WILDCARD" ? "*" : arithNodeLabel(arg);
36796
- return distinct ? `${func}(DISTINCT ${argStr})` : `${func}(${argStr})`;
36797
- }
36798
- function arithNodeLabel(node) {
36799
- if (node.type === "FIELD_REF") return node.field;
36800
- if (node.type === "NUMBER") return numberLiteralText(node);
36801
- if (node.type === "STRING_FUNC") return stringFuncLabel(node);
36802
- return `(${arithNodeLabel(node.left)}${node.op}${arithNodeLabel(node.right)})`;
36803
- }
36804
- function stringFuncLabel(expr) {
36805
- const args = expr.args.map((a) => {
36806
- if (a.type === "AGG_REF") return aggregateSyntheticName(a.func, a.distinct, a.arg);
36807
- if (a.type === "AGG_ARITH") return "agg_arith";
36808
- return scalarValueLabel(a);
36809
- });
36810
- return `${expr.func}(${args.join(",")})`;
36811
- }
36812
- function scalarValueLabel(expr) {
36813
- switch (expr.type) {
36814
- case "STRING":
36815
- return `'${expr.value}'`;
36816
- case "NUMBER":
36817
- return numberLiteralText(expr);
36818
- case "VARIABLE":
36819
- return `@${expr.name}`;
36820
- case "FIELD":
36821
- return expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field;
36822
- case "STRING_FUNC":
36823
- return stringFuncLabel(expr);
36824
- case "CASE_WHEN":
36825
- return "case";
36826
- case "SCALAR_ARITH":
36827
- return `(${scalarValueLabel(expr.left)}${expr.op}${scalarValueLabel(expr.right)})`;
36828
- case "CONCAT_OP":
36829
- return `(${scalarValueLabel(expr.left)}||${scalarValueLabel(expr.right)})`;
36830
- }
36831
- }
36832
36963
  function isAggregateSyntheticName(name) {
36833
36964
  return /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/i.test(name);
36834
36965
  }
@@ -37874,6 +38005,38 @@ function evalScalarValueExpr(expr, row, resolveFieldType, resolveFieldSemantics2
37874
38005
  }
37875
38006
  }
37876
38007
  }
38008
+ function evalScalarValueExprNullable(expr, row, resolveFieldType, resolveFieldSemantics2) {
38009
+ switch (expr.type) {
38010
+ case "CASE_WHEN":
38011
+ return evalCaseWhenNullable(expr, row, resolveFieldType, resolveFieldSemantics2);
38012
+ case "SCALAR_ARITH": {
38013
+ const left = evalScalarValueExprNullable(expr.left, row, resolveFieldType, resolveFieldSemantics2);
38014
+ const right = evalScalarValueExprNullable(expr.right, row, resolveFieldType, resolveFieldSemantics2);
38015
+ if (left === null || right === null) return null;
38016
+ const l = Number(left);
38017
+ const r = Number(right);
38018
+ switch (expr.op) {
38019
+ case "+":
38020
+ return l + r;
38021
+ case "-":
38022
+ return l - r;
38023
+ case "*":
38024
+ return l * r;
38025
+ case "/":
38026
+ return r !== 0 ? l / r : NaN;
38027
+ case "%":
38028
+ return r !== 0 ? l % r : NaN;
38029
+ }
38030
+ }
38031
+ case "CONCAT_OP": {
38032
+ const left = evalScalarValueExprNullable(expr.left, row, resolveFieldType, resolveFieldSemantics2);
38033
+ const right = evalScalarValueExprNullable(expr.right, row, resolveFieldType, resolveFieldSemantics2);
38034
+ return `${left ?? ""}${right ?? ""}`;
38035
+ }
38036
+ default:
38037
+ return evalScalarValueExpr(expr, row, resolveFieldType, resolveFieldSemantics2);
38038
+ }
38039
+ }
37877
38040
  function applyRoundOp(op, num, digits) {
37878
38041
  const factor = Math.pow(10, digits);
37879
38042
  const raw = Math[op](num * factor) / factor;
@@ -38583,6 +38746,20 @@ function evalCaseWhen(expr, row, resolveFieldType, resolveFieldSemantics2) {
38583
38746
  }
38584
38747
  return "";
38585
38748
  }
38749
+ function evalCaseWhenNullable(expr, row, resolveFieldType, resolveFieldSemantics2) {
38750
+ for (const branch of expr.branches) {
38751
+ if (evalWhere(branch.condition, row, resolveFieldType, void 0, resolveFieldSemantics2)) {
38752
+ return evalCaseResultNullable(branch.result, row, resolveFieldType, resolveFieldSemantics2);
38753
+ }
38754
+ }
38755
+ return expr.elseResult === null ? null : evalCaseResultNullable(expr.elseResult, row, resolveFieldType, resolveFieldSemantics2);
38756
+ }
38757
+ function evalCaseResultNullable(result, row, resolveFieldType, resolveFieldSemantics2) {
38758
+ if (result.type === "ARRAY") return result.elements.map((entry) => entry.value).join(",");
38759
+ if (result.type === "FIELD_REF") return row[result.field] ?? "";
38760
+ if (result.type === "ARITH") return evalArithExpr(result, row);
38761
+ return evalScalarValueExprNullable(result, row, resolveFieldType, resolveFieldSemantics2);
38762
+ }
38586
38763
  function evalCaseResult(result, row, resolveFieldType, resolveFieldSemantics2) {
38587
38764
  if (result.type === "ARRAY") return result.elements.map((e) => e.value).join(",");
38588
38765
  if (result.type === "FIELD_REF") {
@@ -38816,7 +38993,7 @@ function collectScalarValueFields2(expr, out) {
38816
38993
  }
38817
38994
  function collectAggOperandFields2(node, out) {
38818
38995
  if (node.type === "AGG_REF") {
38819
- if (node.arg.type !== "WILDCARD") collectArithNode2(node.arg, out);
38996
+ if (node.arg.type !== "WILDCARD") collectAggregateArgFields2(node.arg, out);
38820
38997
  return;
38821
38998
  }
38822
38999
  if (node.type === "AGG_ARITH") {
@@ -38824,6 +39001,10 @@ function collectAggOperandFields2(node, out) {
38824
39001
  collectAggOperandFields2(node.right, out);
38825
39002
  }
38826
39003
  }
39004
+ function collectAggregateArgFields2(node, out) {
39005
+ if (node.type === "FIELD_REF" || node.type === "ARITH") collectArithNode2(node, out);
39006
+ else collectScalarValueFields2(node, out);
39007
+ }
38827
39008
  function collectCaseResultFields(result, out) {
38828
39009
  if (result.type === "ARRAY") return;
38829
39010
  if (result.type === "FIELD_REF" || result.type === "ARITH") {
@@ -41851,7 +42032,7 @@ function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
41851
42032
  }
41852
42033
  for (const col of columns) {
41853
42034
  if (col.type === "AGGREGATE") {
41854
- const syntheticKey = aggregateSyntheticName2(col.func, col.distinct, col.arg);
42035
+ const syntheticKey = aggregateSyntheticName(col.func, col.distinct, col.arg);
41855
42036
  const value = String(evalAggregate(col.func, col.distinct, col.arg, col.separator, groupRows, resolveAggSortKind));
41856
42037
  outRow[col.alias ?? syntheticKey] = value;
41857
42038
  if (col.alias) outRow[syntheticKey] = value;
@@ -41888,10 +42069,16 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
41888
42069
  const raw = row[arg.field];
41889
42070
  if (raw === void 0 || raw === "" && func !== "MIN" && func !== "MAX") continue;
41890
42071
  strVal = raw;
41891
- } else {
42072
+ } else if (arg.type === "ARITH" || arg.type === "NUMBER" || arg.type === "STRING_FUNC") {
41892
42073
  const n = evalArithExpr(arg, row);
41893
42074
  if (isNaN(n)) continue;
41894
42075
  strVal = String(n);
42076
+ } else {
42077
+ const value = evalScalarValueExprNullable(arg, row);
42078
+ if (value === null) continue;
42079
+ if (value === "" && func !== "MIN" && func !== "MAX") continue;
42080
+ if (typeof value === "number" && Number.isNaN(value)) continue;
42081
+ strVal = String(value);
41895
42082
  }
41896
42083
  strValues.push(strVal);
41897
42084
  }
@@ -41906,8 +42093,8 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
41906
42093
  const eff = distinct ? statistical ? [...new Set(numericValues)] : [...new Set(strValues)] : statistical ? numericValues : strValues;
41907
42094
  if (func === "COUNT") return eff.length;
41908
42095
  if (func === "GROUP_CONCAT") return eff.join(separator ?? ",");
41909
- const comparison = (func === "MIN" || func === "MAX" || func === "MODE") && arg.type === "FIELD_REF" ? resolveAggSortKind?.(toAggregateFieldRef(arg.field)) : void 0;
41910
- const semantics = typeof comparison === "string" ? syntheticSemantics(comparison) : comparison ?? (arg.type === "FIELD_REF" ? syntheticSemantics("string") : syntheticSemantics("number"));
42096
+ const comparison = func === "MIN" || func === "MAX" || func === "MODE" ? resolveAggregateArgSemantics(arg, resolveAggSortKind) : void 0;
42097
+ const semantics = typeof comparison === "string" ? syntheticSemantics(comparison) : comparison ?? (arg.type === "FIELD_REF" || arg.type === "FIELD" || arg.type === "STRING" || arg.type === "CONCAT_OP" || arg.type === "CASE_WHEN" ? syntheticSemantics("string") : syntheticSemantics("number"));
41911
42098
  if (func === "MODE") {
41912
42099
  if (strValues.length === 0) return "";
41913
42100
  const frequencies = /* @__PURE__ */ new Map();
@@ -41995,17 +42182,24 @@ function evalAggArithExpr(node, rows, resolveAggSortKind) {
41995
42182
  }
41996
42183
  }
41997
42184
  function aggArithDefaultKey(node) {
41998
- if (node.type === "NUMBER") return numberLiteralText(node);
41999
- if (node.type === "AGG_REF") return aggregateSyntheticName2(node.func, node.distinct, node.arg);
42000
- return `${aggArithDefaultKey(node.left)}${node.op}${aggArithDefaultKey(node.right)}`;
42001
- }
42002
- function aggregateArgLabel(arg) {
42003
- if (arg.type === "WILDCARD") return "*";
42004
- return arithColDefaultKey(arg);
42185
+ return aggregateOperandLabel(node);
42005
42186
  }
42006
- function aggregateSyntheticName2(func, distinct, arg) {
42007
- const argStr = aggregateArgLabel(arg);
42008
- return distinct ? `${func}(DISTINCT ${argStr})` : `${func}(${argStr})`;
42187
+ function resolveAggregateArgSemantics(arg, resolver) {
42188
+ if (arg.type === "FIELD_REF") return resolver?.(toAggregateFieldRef(arg.field)) ?? "string";
42189
+ if (arg.type === "FIELD") return resolver?.(arg) ?? "string";
42190
+ if (arg.type === "NUMBER" || arg.type === "ARITH" || arg.type === "SCALAR_ARITH") return "number";
42191
+ if (arg.type === "STRING" || arg.type === "CONCAT_OP" || arg.type === "VARIABLE") return "string";
42192
+ if (arg.type === "STRING_FUNC") {
42193
+ const numeric = /* @__PURE__ */ new Set(["LENGTH", "LENGTH_CHAR", "INSTR", "ROUND", "FLOOR", "CEIL", "TRUNCATE", "YEAR", "MONTH", "DAY", "DATEDIFF", "ABS", "MOD", "POWER", "SQRT", "DAYOFWEEK", "QUARTER", "WEEK"]);
42194
+ if (arg.func === "CAST") return arg.args[1]?.type === "STRING" && arg.args[1].value === "NUMBER" ? "number" : "string";
42195
+ return numeric.has(arg.func) ? "number" : "string";
42196
+ }
42197
+ const results = [...arg.branches.map((branch) => branch.result), ...arg.elseResult === null ? [] : [arg.elseResult]].filter((result) => result.type !== "ARRAY").map((result) => resolveAggregateArgSemantics(result, resolver));
42198
+ if (results.length === 0 || results.some((result) => result === void 0)) return "string";
42199
+ const kinds = results.map((result) => typeof result === "string" ? result : result.compareMode === "number" || result.compareMode === "recordNumber" ? "number" : "string");
42200
+ if (!kinds.every((kind) => kind === kinds[0])) return "string";
42201
+ const first = results[0];
42202
+ return results.every((result) => JSON.stringify(result) === JSON.stringify(first)) ? first : kinds[0];
42009
42203
  }
42010
42204
  function applyHaving(rows, having, resolveFieldType, resolveFieldSemantics2) {
42011
42205
  if (having === null) return rows;
@@ -42151,7 +42345,7 @@ function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, reso
42151
42345
  evaluators.set(alias, () => column.value);
42152
42346
  break;
42153
42347
  case "AGGREGATE": {
42154
- const source = aggregateSyntheticName2(column.func, column.distinct, column.arg);
42348
+ const source = aggregateSyntheticName(column.func, column.distinct, column.arg);
42155
42349
  evaluators.set(alias, (row) => row[alias] ?? row[source] ?? "0");
42156
42350
  break;
42157
42351
  }
@@ -42276,7 +42470,7 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns, re
42276
42470
  break;
42277
42471
  }
42278
42472
  case "AGGREGATE": {
42279
- const srcKey = aggregateSyntheticName2(col.func, col.distinct, col.arg);
42473
+ const srcKey = aggregateSyntheticName(col.func, col.distinct, col.arg);
42280
42474
  const dstKey = outputKeys?.[colIdx] ?? col.alias ?? srcKey;
42281
42475
  out[dstKey] = row[col.alias ?? srcKey] ?? row[srcKey] ?? "0";
42282
42476
  if (outputKeys === null && rowIdx === 0) orderedKeys.push(dstKey);
@@ -42362,7 +42556,7 @@ function computeOutputKey(col, colIdx, defaultFieldKeys) {
42362
42556
  case "LITERAL_COL":
42363
42557
  return col.alias ?? `'${col.value}'`;
42364
42558
  case "AGGREGATE":
42365
- return col.alias ?? aggregateSyntheticName2(col.func, col.distinct, col.arg);
42559
+ return col.alias ?? aggregateSyntheticName(col.func, col.distinct, col.arg);
42366
42560
  case "ARITH_AGG_COL":
42367
42561
  return col.alias ?? aggArithDefaultKey(col.expr);
42368
42562
  case "ARITH_COL":
@@ -44986,7 +45180,14 @@ async function buildWhereFieldSemanticsResolver(stmt, client, cacheContext, mate
44986
45180
  };
44987
45181
  }
44988
45182
  function selectCaseConditionsNeedFieldMetadata(stmt) {
44989
- return stmt.columns.some((column) => column.type === "CASE_COL" && column.expr.branches.some((branch) => whereNeedsFieldMetadata(branch.condition)));
45183
+ const visit = (value) => {
45184
+ if (value === null || typeof value !== "object") return false;
45185
+ if (Array.isArray(value)) return value.some(visit);
45186
+ const node = value;
45187
+ if (node.type === "CASE_WHEN" && node.branches?.some((branch) => whereNeedsFieldMetadata(branch.condition))) return true;
45188
+ return Object.values(node).some(visit);
45189
+ };
45190
+ return stmt.columns.some(visit);
44990
45191
  }
44991
45192
  function buildHavingFieldSemanticsResolver(stmt, rowResolver) {
44992
45193
  const aliases = /* @__PURE__ */ new Map();
@@ -44998,7 +45199,17 @@ function buildHavingFieldSemanticsResolver(stmt, rowResolver) {
44998
45199
  semantics = syntheticSemantics("number");
44999
45200
  } else if (column.type === "AGGREGATE") {
45000
45201
  if (column.func === "MIN" || column.func === "MAX" || column.func === "MODE") {
45001
- semantics = column.arg.type === "FIELD_REF" ? rowResolver(aggregateFieldRef(column.arg.field)) : syntheticSemantics("number");
45202
+ if (column.arg.type !== "WILDCARD") {
45203
+ semantics = inferAggregateArgMeta(column.arg, (ref) => {
45204
+ const resolved = rowResolver(ref);
45205
+ if (!resolved) return void 0;
45206
+ return {
45207
+ sortKind: resolved.compareMode === "number" || resolved.compareMode === "recordNumber" ? "number" : "string",
45208
+ fieldType: resolved.fieldType,
45209
+ semantics: resolved
45210
+ };
45211
+ }).semantics;
45212
+ }
45002
45213
  } else {
45003
45214
  semantics = column.func === "GROUP_CONCAT" ? syntheticSemantics("string") : syntheticSemantics("number");
45004
45215
  }
@@ -45447,8 +45658,38 @@ function aggregateFieldRef(field) {
45447
45658
  return dot > 0 ? { type: "FIELD", tableAlias: field.slice(0, dot), field: field.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field };
45448
45659
  }
45449
45660
  function collectAggregateRef(func, arg, out) {
45450
- if ((func === "MIN" || func === "MAX" || func === "MODE") && arg.type === "FIELD_REF" && arg.field) {
45661
+ if (func !== "MIN" && func !== "MAX" && func !== "MODE" || arg.type === "WILDCARD") return;
45662
+ collectAggregateArgFieldRefs(arg, out);
45663
+ }
45664
+ function collectAggregateArgFieldRefs(arg, out) {
45665
+ if (arg.type === "FIELD_REF") {
45451
45666
  out.push(aggregateFieldRef(arg.field));
45667
+ return;
45668
+ }
45669
+ if (arg.type === "FIELD") {
45670
+ out.push(arg);
45671
+ return;
45672
+ }
45673
+ if (arg.type === "ARITH") {
45674
+ collectAggregateArgFieldRefs(arg.left, out);
45675
+ collectAggregateArgFieldRefs(arg.right, out);
45676
+ return;
45677
+ }
45678
+ if (arg.type === "SCALAR_ARITH" || arg.type === "CONCAT_OP") {
45679
+ collectAggregateArgFieldRefs(arg.left, out);
45680
+ collectAggregateArgFieldRefs(arg.right, out);
45681
+ return;
45682
+ }
45683
+ if (arg.type === "STRING_FUNC") {
45684
+ for (const child of arg.args) {
45685
+ if (child.type !== "AGG_REF" && child.type !== "AGG_ARITH") collectAggregateArgFieldRefs(child, out);
45686
+ }
45687
+ return;
45688
+ }
45689
+ if (arg.type === "CASE_WHEN") {
45690
+ for (const result of [...arg.branches.map((branch) => branch.result), ...arg.elseResult ? [arg.elseResult] : []]) {
45691
+ if (result.type !== "ARRAY") collectAggregateArgFieldRefs(result, out);
45692
+ }
45452
45693
  }
45453
45694
  }
45454
45695
  function collectAggregateOperandRefs(node, out) {
@@ -45559,7 +45800,7 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext, materia
45559
45800
  const base = info.semantics ?? resolveFieldSemantics(info);
45560
45801
  return info.fieldType === "STATUS" && statusOrdersByApp.has(appId) ? { ...base, optionOrder: statusOrdersByApp.get(appId) } : base;
45561
45802
  };
45562
- return (ref) => {
45803
+ const resolveRef2 = (ref) => {
45563
45804
  let info;
45564
45805
  if (ref.tableAlias !== null) {
45565
45806
  if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
@@ -45593,6 +45834,7 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext, materia
45593
45834
  const sourceTable = ref.tableAlias !== null ? tables.find((table) => effectiveTableAlias(table) === ref.tableAlias) : stmt.joins.length === 0 ? stmt.from : void 0;
45594
45835
  return semanticsForInfo(info, sourceTable?.appId ?? stmt.from.appId);
45595
45836
  };
45837
+ return resolveRef2;
45596
45838
  }
45597
45839
  function fieldCodeForTypeLookup(table, field) {
45598
45840
  if (table.subtableCode && field.startsWith("_p.")) return field.slice(3);
@@ -45702,9 +45944,19 @@ function mergeExpressionColumnMeta(candidates) {
45702
45944
  }
45703
45945
  return unknownStringColumnMeta();
45704
45946
  }
45947
+ function inferAggregateArgMeta(arg, resolveField2) {
45948
+ if (arg.type === "FIELD_REF") return resolveField2(aggregateFieldRef(arg.field)) ?? unknownStringColumnMeta();
45949
+ if (arg.type === "FIELD") return resolveField2(arg) ?? unknownStringColumnMeta();
45950
+ if (arg.type === "NUMBER" || arg.type === "ARITH" || arg.type === "SCALAR_ARITH") return syntheticColumnMeta("number");
45951
+ if (arg.type === "STRING" || arg.type === "CONCAT_OP" || arg.type === "VARIABLE") return syntheticColumnMeta("string");
45952
+ if (arg.type === "STRING_FUNC") return stringFunctionColumnMeta(arg);
45953
+ const results = arg.branches.map((branch) => caseResultColumnMeta(branch.result, resolveField2));
45954
+ if (arg.elseResult) results.push(caseResultColumnMeta(arg.elseResult, resolveField2));
45955
+ return mergeExpressionColumnMeta(results);
45956
+ }
45705
45957
  function selectNeedsSourceColumnMeta(stmt) {
45706
45958
  return stmt.columns.some(
45707
- (column) => column.type === "FIELD" || column.type === "WILDCARD" || column.type === "PARENT_WILDCARD" || column.type === "CASE_COL" || column.type === "AGGREGATE" && (column.func === "MIN" || column.func === "MAX" || column.func === "MODE") && column.arg.type === "FIELD_REF"
45959
+ (column) => column.type === "FIELD" || column.type === "WILDCARD" || column.type === "PARENT_WILDCARD" || column.type === "CASE_COL" || column.type === "AGGREGATE" && (column.func === "MIN" || column.func === "MAX" || column.func === "MODE")
45708
45960
  );
45709
45961
  }
45710
45962
  async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext, materializedTables) {
@@ -45775,11 +46027,8 @@ async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext,
45775
46027
  meta3 = syntheticColumnMeta("string");
45776
46028
  } else if (column.func === "COUNT" || column.func === "SUM" || column.func === "AVG" || column.func === "STDDEV_POP" || column.func === "STDDEV_SAMP" || column.func === "VAR_POP" || column.func === "VAR_SAMP" || column.func === "MEDIAN") {
45777
46029
  meta3 = syntheticColumnMeta("number");
45778
- } else if ((column.func === "MIN" || column.func === "MAX" || column.func === "MODE") && column.arg.type === "FIELD_REF") {
45779
- const source = resolveField2(aggregateFieldRef(column.arg.field));
45780
- if (source) meta3 = source;
45781
- } else if (column.func === "MODE") {
45782
- meta3 = syntheticColumnMeta("number");
46030
+ } else if ((column.func === "MIN" || column.func === "MAX" || column.func === "MODE") && column.arg.type !== "WILDCARD") {
46031
+ meta3 = inferAggregateArgMeta(column.arg, resolveField2);
45783
46032
  }
45784
46033
  } else if (column.type === "ARITH_AGG_COL" || column.type === "ARITH_COL") {
45785
46034
  meta3 = syntheticColumnMeta("number");
@@ -46545,7 +46794,7 @@ async function buildOrderSemanticsForSelect(stmt, client, cacheContext, material
46545
46794
  meta3 = mergeExpressionColumnMeta(candidates);
46546
46795
  } else if (column.type === "AGGREGATE") {
46547
46796
  if (column.func === "MIN" || column.func === "MAX" || column.func === "MODE") {
46548
- meta3 = column.arg.type === "FIELD_REF" ? resolveField2(aggregateFieldRef(column.arg.field)) : syntheticColumnMeta("number");
46797
+ if (column.arg.type !== "WILDCARD") meta3 = inferAggregateArgMeta(column.arg, resolveField2);
46549
46798
  } else {
46550
46799
  meta3 = column.func === "GROUP_CONCAT" ? syntheticColumnMeta("string") : syntheticColumnMeta("number");
46551
46800
  }
@@ -53923,7 +54172,7 @@ Nested JSON/CSV subtable mutation is fail-closed on MCP: use VALIDATE ONLY/EXPLA
53923
54172
  JSON child IDs are rejected and replacement renumbers all rows.
53924
54173
  `);
53925
54174
  }
53926
- var SERVER_VERSION = true ? "3.15.0" : "0.0.0-dev";
54175
+ var SERVER_VERSION = true ? "3.16.0" : "0.0.0-dev";
53927
54176
  var FUNCTION_CATALOG_PARAGRAPH = `Complete function catalog \u2014 Scalar: ${KSQL_FUNCTION_CATALOG.scalar.join(" ")}. Aggregate: ${KSQL_FUNCTION_CATALOG.aggregate.join(" ")}. Variance and standard-deviation aggregates use explicit POP/SAMP names; unqualified STDDEV and VARIANCE are unsupported. Window: ${KSQL_FUNCTION_CATALOG.window.join(" ")} (OVER and AS alias required). Contextual: ${KSQL_FUNCTION_CATALOG.contextual.join(" ")} (kintone predicates; LOGINUSER resolves to an empty string in Node/MCP). Aliases: ${KSQL_FUNCTION_CATALOG.aliases.join(" ")}. Syntax: ${KSQL_FUNCTION_CATALOG.syntax.join(" ")}. This list is complete; functions from other dialects such as IFNULL do not exist. Use ksql_docs for arguments and constraints.`;
53928
54177
  var KSQL_MCP_INSTRUCTIONS = `kSQL is a SQL-like dialect for kintone, not generic SQL. Supports cataloged families plus JOIN, aggregates, windows, subtable virtual tables, CHECK, KLIKE, KORDER BY, @variables, and LAPP_<NAME>.
53929
54178