@rex0220/kintone-sql-tools 3.42.0 → 3.44.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.
@@ -30555,6 +30555,7 @@ function arithLabel(node, topLevel = false) {
30555
30555
  function fieldValueLabel(value) {
30556
30556
  if (value.type === "FIELD") return value.tableAlias ? `${value.tableAlias}.${value.field}` : value.field;
30557
30557
  if (value.type === "FUNC_FIELD") return stringFuncLabel(value.expr);
30558
+ if (value.type === "AGG_FIELD") return aggregateOperandLabel(value.expr);
30558
30559
  if (value.type === "ARITH_FIELD") return arithLabel(value.expr);
30559
30560
  if (value.type === "GROUPING_FIELD") {
30560
30561
  const field = value.ref.field;
@@ -30608,6 +30609,8 @@ function whereLabel(expr) {
30608
30609
  }
30609
30610
  function caseResultLabel(result) {
30610
30611
  if (result.type === "ARRAY") return `[${result.elements.map((entry) => quote(entry.value)).join(",")}]`;
30612
+ if (result.type === "AGG_REF") return aggregateSyntheticName(result.func, result.distinct, result.arg);
30613
+ if (result.type === "AGG_ARITH") return aggregateOperandLabel(result);
30611
30614
  if (result.type === "FIELD_REF" || result.type === "ARITH") return arithLabel(result);
30612
30615
  return scalarValueLabel(result);
30613
30616
  }
@@ -30911,8 +30914,9 @@ function needsSpaceBetween(prev, cur) {
30911
30914
  return true;
30912
30915
  }
30913
30916
  var ParseError = class extends Error {
30914
- constructor(message, token) {
30915
- super(`${message}\uFF08\u4F4D\u7F6E ${token.pos}\u3001\u30C8\u30FC\u30AF\u30F3: \u300C${token.value}\u300D\uFF09`);
30917
+ constructor(rawMessage, token) {
30918
+ super(`${rawMessage}\uFF08\u4F4D\u7F6E ${token.pos}\u3001\u30C8\u30FC\u30AF\u30F3: \u300C${token.value}\u300D\uFF09`);
30919
+ this.rawMessage = rawMessage;
30916
30920
  this.token = token;
30917
30921
  this.name = "ParseError";
30918
30922
  }
@@ -31951,8 +31955,17 @@ var Parser = class {
31951
31955
  if (column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL") return true;
31952
31956
  if (column.type === "STRFUNC_COL") return column.expr.args.some((arg) => this.stringFuncArgHasAggregate(arg));
31953
31957
  if (column.type === "SCALAR_VALUE_COL") return this.scalarValueHasAggregate(column.expr);
31958
+ if (column.type === "CASE_COL") return this.nodeHasAggregate(column.expr);
31954
31959
  return false;
31955
31960
  }
31961
+ nodeHasAggregate(node) {
31962
+ if (node === null || typeof node !== "object") return false;
31963
+ if (Array.isArray(node)) return node.some((value2) => this.nodeHasAggregate(value2));
31964
+ const value = node;
31965
+ if (value["type"] === "AGG_REF" || value["type"] === "AGG_ARITH") return true;
31966
+ if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return false;
31967
+ return Object.values(value).some((child) => this.nodeHasAggregate(child));
31968
+ }
31956
31969
  stringFuncArgHasAggregate(arg) {
31957
31970
  if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
31958
31971
  return this.scalarValueHasAggregate(arg);
@@ -31963,11 +31976,7 @@ var Parser = class {
31963
31976
  return this.scalarValueHasAggregate(expr.left) || this.scalarValueHasAggregate(expr.right);
31964
31977
  }
31965
31978
  if (expr.type === "CASE_WHEN") {
31966
- const results = [...expr.branches.map((b) => b.result), ...expr.elseResult ? [expr.elseResult] : []];
31967
- return results.some((result) => {
31968
- if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return false;
31969
- return this.scalarValueHasAggregate(result);
31970
- });
31979
+ return this.nodeHasAggregate(expr);
31971
31980
  }
31972
31981
  return false;
31973
31982
  }
@@ -32224,9 +32233,9 @@ var Parser = class {
32224
32233
  this.expect("(" /* LPAREN */);
32225
32234
  const condition = this.parseCaseCondition(allowGroupingCondition);
32226
32235
  this.expect("," /* COMMA */);
32227
- const thenResult = this.parseCaseResult();
32236
+ const thenResult = this.parseCaseResult(allowGroupingCondition);
32228
32237
  this.expect("," /* COMMA */);
32229
- const elseResult = this.parseCaseResult();
32238
+ const elseResult = this.parseCaseResult(allowGroupingCondition);
32230
32239
  this.expect(")" /* RPAREN */);
32231
32240
  return {
32232
32241
  type: "CASE_WHEN",
@@ -32241,7 +32250,7 @@ var Parser = class {
32241
32250
  this.advance();
32242
32251
  const condition = this.parseCaseCondition(allowGroupingCondition);
32243
32252
  this.expect("THEN" /* THEN */);
32244
- const result = this.parseCaseResult();
32253
+ const result = this.parseCaseResult(allowGroupingCondition);
32245
32254
  branches.push({ condition, result });
32246
32255
  }
32247
32256
  if (branches.length === 0) {
@@ -32249,7 +32258,7 @@ var Parser = class {
32249
32258
  }
32250
32259
  let elseResult = null;
32251
32260
  if (this.consume("ELSE" /* ELSE */)) {
32252
- elseResult = this.parseCaseResult();
32261
+ elseResult = this.parseCaseResult(allowGroupingCondition);
32253
32262
  }
32254
32263
  this.expect("END" /* END */);
32255
32264
  return { type: "CASE_WHEN", branches, elseResult };
@@ -32259,7 +32268,7 @@ var Parser = class {
32259
32268
  return this.parseWhereExpr("SELECT_CASE");
32260
32269
  }
32261
32270
  /** THEN / ELSE の結果値。`||` を含む場合だけ新スカラー文法へ渡す。 */
32262
- parseCaseResult() {
32271
+ parseCaseResult(allowAggregateResult = false) {
32263
32272
  const tok = this.peek();
32264
32273
  if (this.insideAggregateArg > 0 && this.tryAggregateFunc() !== null) {
32265
32274
  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);
@@ -32267,6 +32276,10 @@ var Parser = class {
32267
32276
  if (tok.kind === "[" /* LBRACKET */) {
32268
32277
  return this.parseArrayLiteral();
32269
32278
  }
32279
+ const aggregateFunc = this.tryAggregateFunc();
32280
+ if (aggregateFunc !== null && allowAggregateResult) {
32281
+ return this.continueAggArith(this.parseAggregateRef(aggregateFunc));
32282
+ }
32270
32283
  if (this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
32271
32284
  return this.parseScalarValueExpr({ allowAggregateArgs: true });
32272
32285
  }
@@ -32298,16 +32311,33 @@ var Parser = class {
32298
32311
  const byKind = PARSER_SCALAR_FUNCTION_TOKEN_MAP[this.peek().kind] ?? null;
32299
32312
  if (byKind !== null && byKind !== "LEFT" && byKind !== "RIGHT") return byKind;
32300
32313
  if (this.peek().kind === "IDENT" /* IDENT */) {
32301
- const name = this.peek().value.toUpperCase();
32314
+ const nameToken = this.peek();
32315
+ const name = nameToken.value.toUpperCase();
32302
32316
  if (PARSER_IDENT_SCALAR_FUNCTIONS.includes(name)) {
32303
32317
  if (this.peekAt(1).kind === "(" /* LPAREN */) {
32304
32318
  return name;
32305
32319
  }
32306
32320
  }
32321
+ if (this.peekAt(1).kind === "(" /* LPAREN */) {
32322
+ const hint = name === "DATE_SUB" ? "\u3002\u65E5\u4ED8\u3092\u6E1B\u7B97\u3059\u308B\u306B\u306F DATE_ADD \u306E\u52A0\u7B97\u5024\u3078\u8CA0\u6570\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044" : "";
32323
+ throw new ParseError(`\u300C${nameToken.value}\u300D\u3068\u3044\u3046\u95A2\u6570\u306F\u3042\u308A\u307E\u305B\u3093${hint}`, nameToken);
32324
+ }
32307
32325
  }
32308
32326
  return null;
32309
32327
  }
32310
32328
  parseStringFuncExpr() {
32329
+ const nameToken = this.peek();
32330
+ const func = this.tryStringFuncName();
32331
+ try {
32332
+ return this.parseStringFuncExprBody();
32333
+ } catch (error51) {
32334
+ if (!(error51 instanceof ParseError)) throw error51;
32335
+ const displayName = nameToken.value.toUpperCase();
32336
+ const guidance = func === "DATE_ADD" ? `${displayName} \u306E\u69CB\u6587\u306F DATE_ADD(\u5217, n, '\u5358\u4F4D') \u3067\u3059\u3002` : `${displayName} \u306E\u5F15\u6570\u69CB\u6587\u304C\u4E0D\u6B63\u3067\u3059\u3002`;
32337
+ throw new ParseError(`${guidance}${error51.rawMessage}`, error51.token);
32338
+ }
32339
+ }
32340
+ parseStringFuncExprBody() {
32311
32341
  const tokenKind = this.peek().kind;
32312
32342
  const func = this.tryStringFuncName();
32313
32343
  this.advance();
@@ -32773,8 +32803,19 @@ var Parser = class {
32773
32803
  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());
32774
32804
  }
32775
32805
  const ref = this.parseAggregateRef(aggFunc);
32806
+ if (this.isArithOp(this.peek().kind)) {
32807
+ return {
32808
+ type: "AGG_FIELD",
32809
+ expr: this.continueAggArith(ref)
32810
+ };
32811
+ }
32776
32812
  const syntheticName = aggregateSyntheticName(ref.func, ref.distinct, ref.arg);
32777
- return { type: "FIELD", tableAlias: null, field: syntheticName };
32813
+ return {
32814
+ type: "FIELD",
32815
+ tableAlias: null,
32816
+ field: syntheticName,
32817
+ ...this.groupingFieldContext === "SELECT_CASE" || this.groupingFieldContext === "HAVING" ? { aggregateRef: ref } : {}
32818
+ };
32778
32819
  }
32779
32820
  if (this.peek().kind === "CASE" /* CASE */) {
32780
32821
  const expr = this.parseCaseWhenExpr();
@@ -34977,6 +35018,9 @@ function convertField(field) {
34977
35018
  `WHERE \u53E5\u306E\u95A2\u6570\uFF08${field.expr.func}\uFF09\u306F kintone \u30AF\u30A8\u30EA\u306B\u5909\u63DB\u3067\u304D\u307E\u305B\u3093`
34978
35019
  );
34979
35020
  }
35021
+ if (field.type === "AGG_FIELD") {
35022
+ throw new KintoneQueryError("HAVING \u53E5\u306E\u96C6\u8A08\u7B97\u8853\u5F0F\u306F kintone \u30AF\u30A8\u30EA\u306B\u5909\u63DB\u3067\u304D\u307E\u305B\u3093");
35023
+ }
34980
35024
  if (field.type === "ARITH_FIELD") {
34981
35025
  throw new KintoneQueryError("WHERE \u53E5\u306E\u7B97\u8853\u5F0F\u306F kintone \u30AF\u30A8\u30EA\u306B\u5909\u63DB\u3067\u304D\u307E\u305B\u3093");
34982
35026
  }
@@ -35115,189 +35159,464 @@ var KintoneQueryError = class extends Error {
35115
35159
  }
35116
35160
  };
35117
35161
 
35118
- // src/converter/selectToKintone.ts
35119
- function hasWindowColumns(columns) {
35120
- return columns.some((column) => column.type === "WINDOW_COL");
35121
- }
35122
- function resolveSelectMode(stmt) {
35123
- if (stmt.from.subtableCode) return "FULL_SCAN";
35124
- if (stmt.joins.some((j) => j.table.subtableCode)) return "FULL_SCAN";
35125
- if (stmt.joins.length > 0) return "FULL_SCAN";
35126
- if (normalizeGroupingSpec(stmt).type !== "NONE") return "FULL_SCAN";
35127
- if (stmt.distinct) return "FULL_SCAN";
35128
- if (hasWindowColumns(stmt.columns)) return "FULL_SCAN";
35129
- if (stmt.columns.some(
35130
- (c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "SCALAR_SUBQUERY_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr(c.expr) || c.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate(c.expr)
35131
- )) return "FULL_SCAN";
35132
- if (whereRequiresJsEval(stmt.where)) return "FULL_SCAN";
35133
- if (stmt.orderBy.some((o) => o.key.type !== "FIELD_NAME")) return "FULL_SCAN";
35134
- return "SIMPLE";
35162
+ // src/core/groupingValidation.ts
35163
+ init_define_KSQL_DOCS();
35164
+
35165
+ // src/engine/groupingRowMeta.ts
35166
+ init_define_KSQL_DOCS();
35167
+ var groupingRowMetaKey = /* @__PURE__ */ Symbol("ksql.groupingRowMeta");
35168
+ var groupingRefCanonicalIds = /* @__PURE__ */ new WeakMap();
35169
+ function attachGroupingRowMeta(row, includedCanonicalIds) {
35170
+ Object.defineProperty(row, groupingRowMetaKey, {
35171
+ value: { includedCanonicalIds },
35172
+ enumerable: false,
35173
+ configurable: false,
35174
+ writable: false
35175
+ });
35176
+ return row;
35135
35177
  }
35136
- function whereRequiresJsEval(where) {
35137
- if (where === null) return false;
35138
- switch (where.type) {
35139
- case "BOOLEAN":
35140
- return true;
35141
- case "BINARY":
35142
- return isFunc(where.left) || where.right.type === "ARITH_VALUE" || where.right.type === "CASE_VALUE" || where.right.type === "SUBQUERY_IN_LIST" || where.right.type === "SCALAR_SUBQUERY" || isLike(where);
35143
- case "NULL_CHECK":
35144
- return isFunc(where.field);
35145
- case "LOGICAL":
35146
- return whereRequiresJsEval(where.left) || whereRequiresJsEval(where.right);
35147
- case "NOT":
35148
- case "GROUP":
35149
- return whereRequiresJsEval(where.expr);
35150
- case "EXISTS":
35151
- return true;
35152
- }
35178
+ function getGroupingRowMeta(row) {
35179
+ return row[groupingRowMetaKey];
35153
35180
  }
35154
- function isFunc(fv) {
35155
- return fv.type === "FUNC_FIELD" || fv.type === "ARITH_FIELD" || fv.type === "CASE_FIELD";
35181
+ function readGroupingMembership(row) {
35182
+ return getGroupingRowMeta(row)?.includedCanonicalIds;
35156
35183
  }
35157
- function selectToKintoneParams(stmt) {
35158
- const queryParts = [];
35159
- const hasPagination = stmt.limit !== null || stmt.offset !== null;
35160
- const shouldInjectDefaultOrder = hasPagination && stmt.orderBy.length === 0;
35161
- if (stmt.where !== null) {
35162
- queryParts.push(whereToKintone(stmt.where));
35163
- }
35164
- if (stmt.orderBy.length > 0) {
35165
- const orderStr = stmt.orderBy.map(convertOrderBy).join(", ");
35166
- queryParts.push(`order by ${orderStr}`);
35167
- } else if (shouldInjectDefaultOrder) {
35168
- queryParts.push("order by $id asc");
35169
- }
35170
- if (stmt.limit !== null) {
35171
- queryParts.push(`limit ${stmt.limit}`);
35172
- }
35173
- if (stmt.offset !== null) {
35174
- queryParts.push(`offset ${stmt.offset}`);
35175
- }
35176
- return {
35177
- app: stmt.from.appId,
35178
- query: queryParts.join(" "),
35179
- fields: extractFields(stmt.columns),
35180
- totalCount: false
35181
- };
35184
+ function bindGroupingRefCanonicalId(ref, canonicalId) {
35185
+ groupingRefCanonicalIds.set(ref, canonicalId);
35182
35186
  }
35183
- function selectToFetchAllParams(stmt, appId) {
35184
- const queryParts = [];
35185
- if (stmt.where !== null && stmt.joins.length === 0 && !whereRequiresJsEval(stmt.where)) {
35186
- queryParts.push(whereToKintone(stmt.where));
35187
+ function evalGroupingRef(ref, row) {
35188
+ const membership = readGroupingMembership(row);
35189
+ if (!membership) {
35190
+ throw new Error("internal error: GROUPING() evaluation requires B65 grouping row membership.");
35187
35191
  }
35188
- return {
35189
- app: appId,
35190
- query: queryParts.join(" "),
35191
- fields: []
35192
- // 全件取得なので全フィールドを取得する
35193
- };
35194
- }
35195
- function selectToFetchAllFields(stmt, targetTable, plainGroupByPlan) {
35196
- const plan = collectRequiredFieldsByTable(stmt, plainGroupByPlan);
35197
- const target = plan.get(targetTable);
35198
- if (!target) return [];
35199
- if (target.allFields) return [];
35200
- const fields = new Set(target.fields);
35201
- if (target.table.subtableCode) {
35202
- fields.add(target.table.subtableCode);
35192
+ const canonicalId = groupingRefCanonicalIds.get(ref);
35193
+ if (!canonicalId) {
35194
+ throw new Error("internal error: GROUPING() reference was not resolved during B65 planning.");
35203
35195
  }
35204
- if (fields.size === 0) fields.add("$id");
35205
- return [...fields];
35196
+ return membership.has(canonicalId) ? "0" : "1";
35206
35197
  }
35207
- function convertOrderBy(item) {
35208
- const dir = item.direction === "ASC" ? "asc" : "desc";
35209
- if (item.key.type !== "FIELD_NAME") {
35210
- throw new Error("ORDER BY \u5F0F\u306F kintone \u30AF\u30A8\u30EA\u306B\u5909\u63DB\u3067\u304D\u307E\u305B\u3093\uFF08FULL_SCAN \u304C\u5FC5\u8981\u3067\u3059\uFF09");
35198
+
35199
+ // src/core/groupingValidation.ts
35200
+ var enforceGroupingPlanningCandidateLimits = (facts) => {
35201
+ if (facts.expandedSetCount > B65_MAX_GROUPING_SETS) {
35202
+ throw new Error(
35203
+ `ArgumentError: B65 expanded grouping set count ${facts.expandedSetCount} exceeds limit ${B65_MAX_GROUPING_SETS} (reason=GROUPING_SET_LIMIT_EXCEEDED).`
35204
+ );
35211
35205
  }
35212
- return `${item.key.name} ${dir}`;
35213
- }
35214
- function extractFields(columns) {
35215
- const hasWildcard = columns.some(
35216
- (c) => c.type === "WILDCARD" || c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "CASE_COL" || c.type === "SCALAR_SUBQUERY_COL"
35217
- );
35218
- if (hasWildcard) return [];
35219
- const fields = [];
35220
- for (const col of columns) {
35221
- if (col.type === "FIELD") {
35222
- fields.push(normalizeSimpleFieldRef(col.field));
35223
- } else if (col.type === "ARITH_COL") {
35224
- collectArithNode(col.expr, fields);
35225
- } else if (col.type === "STRFUNC_COL") {
35226
- collectStringFuncFields(col.expr, fields);
35227
- } else if (col.type === "SCALAR_VALUE_COL") {
35228
- collectScalarValueFields(col.expr, fields);
35229
- }
35206
+ if (facts.canonicalItemCount > B65_MAX_GROUPING_ITEMS) {
35207
+ throw new Error(
35208
+ `ArgumentError: B65 canonical grouping item count ${facts.canonicalItemCount} exceeds limit ${B65_MAX_GROUPING_ITEMS} (reason=GROUPING_ITEM_LIMIT_EXCEEDED).`
35209
+ );
35230
35210
  }
35231
- return [...new Set(fields)];
35232
- }
35233
- function collectArithFields(expr, out) {
35234
- collectArithNode(expr.left, out);
35235
- collectArithNode(expr.right, out);
35236
- }
35237
- function collectArithNode(node, out) {
35238
- if (node.type === "VARIABLE") throw new Error(
35239
- `InternalError: unresolved arithmetic variable @${node.name} reached SELECT field collection.`
35240
- );
35241
- if (node.type === "FIELD_REF") out.push(normalizeSimpleFieldRef(node.field));
35242
- else if (node.type === "ARITH") collectArithFields(node, out);
35243
- else if (node.type === "STRING_FUNC") collectStringFuncFields(node, out);
35244
- }
35245
- function normalizeSimpleFieldRef(field) {
35246
- const dot = field.indexOf(".");
35247
- if (dot <= 0) return field;
35248
- const unqualified = field.slice(dot + 1);
35249
- return unqualified || field;
35211
+ };
35212
+ function displayField(field) {
35213
+ return field.tableAlias ? `${field.tableAlias}.${field.field}` : field.field;
35250
35214
  }
35251
- function collectStringFuncFields(expr, out) {
35252
- for (const arg of expr.args) {
35253
- collectStringFuncArgFields(arg, out);
35254
- }
35215
+ function refFromName(name) {
35216
+ const dot = name.indexOf(".");
35217
+ return dot > 0 ? { type: "FIELD", tableAlias: name.slice(0, dot), field: name.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field: name };
35255
35218
  }
35256
- function collectStringFuncArgFields(arg, out) {
35257
- if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
35258
- collectAggOperandFields(arg, out);
35219
+ function collectGroupingRefs(node, out) {
35220
+ if (node === null || typeof node !== "object") return;
35221
+ if (Array.isArray(node)) {
35222
+ node.forEach((item) => collectGroupingRefs(item, out));
35259
35223
  return;
35260
35224
  }
35261
- collectScalarValueFields(arg, out);
35262
- }
35263
- function collectScalarValueFields(expr, out) {
35264
- if (expr.type === "FIELD") {
35265
- out.push(normalizeSimpleFieldRef(expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field));
35225
+ const value = node;
35226
+ if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
35227
+ if (value["type"] === "GROUPING_REF") {
35228
+ out.push(value);
35266
35229
  return;
35267
35230
  }
35268
- if (expr.type === "STRING_FUNC") {
35269
- collectStringFuncFields(expr, out);
35231
+ Object.values(value).forEach((item) => collectGroupingRefs(item, out));
35232
+ }
35233
+ function collectAggregateArgumentGroupingRefs(node, out) {
35234
+ if (node === null || typeof node !== "object") return;
35235
+ if (Array.isArray(node)) {
35236
+ node.forEach((item) => collectAggregateArgumentGroupingRefs(item, out));
35270
35237
  return;
35271
35238
  }
35272
- if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
35273
- collectScalarValueFields(expr.left, out);
35274
- collectScalarValueFields(expr.right, out);
35239
+ const value = node;
35240
+ if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
35241
+ if (value["type"] === "AGGREGATE" || value["type"] === "AGG_REF") {
35242
+ collectGroupingRefs(value["arg"], out);
35275
35243
  return;
35276
35244
  }
35277
- if (expr.type === "CASE_WHEN") {
35278
- for (const branch of expr.branches) collectCaseResultScalarFields(branch.result, out);
35279
- if (expr.elseResult) collectCaseResultScalarFields(expr.elseResult, out);
35280
- }
35245
+ Object.values(value).forEach((item) => collectAggregateArgumentGroupingRefs(item, out));
35281
35246
  }
35282
- function collectCaseResultScalarFields(result, out) {
35283
- if (result.type === "ARRAY") return;
35284
- if (result.type === "FIELD_REF" || result.type === "ARITH") {
35285
- collectArithNode(result, out);
35247
+ function collectNonAggregateFieldRefs(node, out) {
35248
+ if (node === null || typeof node !== "object") return;
35249
+ if (Array.isArray(node)) {
35250
+ node.forEach((item) => collectNonAggregateFieldRefs(item, out));
35286
35251
  return;
35287
35252
  }
35288
- collectScalarValueFields(result, out);
35289
- }
35290
- function collectAggOperandFields(node, out) {
35291
- if (node.type === "AGG_REF") {
35292
- if (node.arg.type !== "WILDCARD") collectAggregateArgFields(node.arg, out);
35253
+ const value = node;
35254
+ const type = value["type"];
35255
+ if (type === "SELECT" || type === "SCALAR_SUBQUERY" || type === "GROUPING_REF" || type === "AGG_REF" || type === "AGG_ARITH") return;
35256
+ if (type === "FIELD" && value["aggregateRef"] !== void 0) return;
35257
+ if (type === "FIELD" && typeof value["field"] === "string") {
35258
+ out.push({
35259
+ type: "FIELD",
35260
+ tableAlias: typeof value["tableAlias"] === "string" ? value["tableAlias"] : null,
35261
+ field: value["field"]
35262
+ });
35293
35263
  return;
35294
35264
  }
35295
- if (node.type === "AGG_ARITH") {
35296
- collectAggOperandFields(node.left, out);
35297
- collectAggOperandFields(node.right, out);
35265
+ if (type === "FIELD_REF" && typeof value["field"] === "string") {
35266
+ out.push(refFromName(value["field"]));
35267
+ return;
35298
35268
  }
35269
+ Object.values(value).forEach((item) => collectNonAggregateFieldRefs(item, out));
35299
35270
  }
35300
- function collectAggregateArgFields(node, out) {
35271
+ function containsAggregate2(node) {
35272
+ if (node === null || typeof node !== "object") return false;
35273
+ if (Array.isArray(node)) return node.some(containsAggregate2);
35274
+ const value = node;
35275
+ if (value["type"] === "AGG_REF" || value["type"] === "AGG_ARITH") return true;
35276
+ if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return false;
35277
+ return Object.values(value).some(containsAggregate2);
35278
+ }
35279
+ function isAggregateMaterializedAlias(column) {
35280
+ if (!("alias" in column) || column.alias === null) return false;
35281
+ if (column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL") return true;
35282
+ if (column.type === "STRFUNC_COL" || column.type === "SCALAR_VALUE_COL" || column.type === "CASE_COL") {
35283
+ return containsAggregate2(column);
35284
+ }
35285
+ return false;
35286
+ }
35287
+ function outputAliases(columns) {
35288
+ return new Set(columns.flatMap(
35289
+ (column) => "alias" in column && typeof column.alias === "string" ? [column.alias] : []
35290
+ ));
35291
+ }
35292
+ function isAggregateSyntheticReference(ref) {
35293
+ return ref.tableAlias === null && /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/.test(ref.field);
35294
+ }
35295
+ function validateGroupingRefMembership(ref, resolve3, canonicalItems) {
35296
+ const resolved = resolve3(ref.field);
35297
+ if (!resolved.physical) {
35298
+ throw new Error(`ArgumentError: B65 grouping reference ${displayField(ref.field)} must resolve to a physical APP field.`);
35299
+ }
35300
+ if (!canonicalItems.has(resolved.canonicalId)) {
35301
+ throw new Error(
35302
+ `ArgumentError: B65 GROUPING argument ${displayField(ref.field)} is not present in grouping allItems (reason=B65_GROUPING_ARG_NOT_ITEM).`
35303
+ );
35304
+ }
35305
+ bindGroupingRefCanonicalId(ref, resolved.canonicalId);
35306
+ }
35307
+ function validateDependency(ref, resolve3, canonicalItems, context) {
35308
+ const resolved = resolve3(ref);
35309
+ if (!resolved.physical || !canonicalItems.has(resolved.canonicalId)) {
35310
+ throw new Error(
35311
+ `ArgumentError: B65 non-aggregate field ${displayField(ref)} in ${context} is not a grouping item (reason=B65_NON_GROUPED_DEPENDENCY).`
35312
+ );
35313
+ }
35314
+ }
35315
+ function keyDependencies(key) {
35316
+ if (key.type === "GROUPING_KEY") return [];
35317
+ if (key.type === "FIELD_NAME") return [refFromName(key.name)];
35318
+ const refs = [];
35319
+ collectNonAggregateFieldRefs(key, refs);
35320
+ return refs;
35321
+ }
35322
+ function validateGroupingStatic(stmt) {
35323
+ const normalized = normalizeGroupingSpec(stmt);
35324
+ const groupingRefs = [];
35325
+ for (const column of stmt.columns) {
35326
+ if (column.type !== "WINDOW_COL") collectGroupingRefs(column, groupingRefs);
35327
+ }
35328
+ collectGroupingRefs(stmt.having, groupingRefs);
35329
+ collectGroupingRefs(stmt.orderBy, groupingRefs);
35330
+ const forbiddenGroupingRefs = [];
35331
+ collectGroupingRefs(stmt.where, forbiddenGroupingRefs);
35332
+ collectGroupingRefs(stmt.joins, forbiddenGroupingRefs);
35333
+ collectAggregateArgumentGroupingRefs(stmt.columns, forbiddenGroupingRefs);
35334
+ collectAggregateArgumentGroupingRefs(stmt.having, forbiddenGroupingRefs);
35335
+ for (const column of stmt.columns) {
35336
+ if (column.type === "WINDOW_COL") collectGroupingRefs(column, forbiddenGroupingRefs);
35337
+ }
35338
+ if (forbiddenGroupingRefs.length > 0) {
35339
+ throw new Error(
35340
+ "ArgumentError: B65 GROUPING() is not allowed in WHERE, JOIN, window, aggregate arguments, or DML expressions."
35341
+ );
35342
+ }
35343
+ if (normalized.type !== "GROUPING_SETS") {
35344
+ if (groupingRefs.length > 0) {
35345
+ throw new Error("ArgumentError: B65 GROUPING() requires GROUP BY ROLLUP or GROUPING SETS.");
35346
+ }
35347
+ return;
35348
+ }
35349
+ if (stmt.orderMode === "KINTONE_NATIVE") {
35350
+ throw new Error("ArgumentError: B65 KORDER BY is not supported in Phase1.");
35351
+ }
35352
+ if (stmt.columns.some((column) => column.type === "WINDOW_COL")) {
35353
+ throw new Error("ArgumentError: B65 window functions are not supported in Phase1.");
35354
+ }
35355
+ if (stmt.columns.some(
35356
+ (column) => column.type === "WILDCARD" || column.type === "PARENT_WILDCARD"
35357
+ )) {
35358
+ throw new Error("ArgumentError: B65 wildcard projection is not supported in Phase1.");
35359
+ }
35360
+ }
35361
+ function validateGroupingPlanning(stmt, resolve3, planningGuardHook = () => void 0) {
35362
+ validateGroupingStatic(stmt);
35363
+ const normalized = normalizeGroupingSpec(stmt);
35364
+ const groupingRefs = [];
35365
+ for (const column of stmt.columns) {
35366
+ if (column.type !== "WINDOW_COL") collectGroupingRefs(column, groupingRefs);
35367
+ }
35368
+ collectGroupingRefs(stmt.having, groupingRefs);
35369
+ collectGroupingRefs(stmt.orderBy, groupingRefs);
35370
+ if (normalized.type !== "GROUPING_SETS") {
35371
+ return null;
35372
+ }
35373
+ const resolvedSpec = resolveGroupingSpec(stmt, resolve3);
35374
+ const canonicalItems = /* @__PURE__ */ new Set();
35375
+ const resolvedItems = [];
35376
+ for (const item of resolvedSpec.allItems) {
35377
+ const resolved = item;
35378
+ if (!resolved.physical) {
35379
+ throw new Error(`ArgumentError: B65 grouping item ${displayField(item.field)} must resolve to a physical APP field.`);
35380
+ }
35381
+ if (!canonicalItems.has(resolved.canonicalId)) {
35382
+ canonicalItems.add(resolved.canonicalId);
35383
+ resolvedItems.push(resolved);
35384
+ }
35385
+ }
35386
+ planningGuardHook({
35387
+ expandedSetCount: normalized.sets.length,
35388
+ canonicalItemCount: canonicalItems.size
35389
+ });
35390
+ for (const ref of groupingRefs) {
35391
+ validateGroupingRefMembership(ref, resolve3, canonicalItems);
35392
+ }
35393
+ const aliases = outputAliases(stmt.columns);
35394
+ for (const column of stmt.columns) {
35395
+ if (column.type === "GROUPING_COL" || column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL" || column.type === "LITERAL_COL" || column.type === "VARIABLE_COL" || column.type === "SCALAR_SUBQUERY_COL") continue;
35396
+ const refs = [];
35397
+ if (column.type === "FIELD") refs.push(refFromName(column.field));
35398
+ else collectNonAggregateFieldRefs(column, refs);
35399
+ for (const ref of refs) validateDependency(ref, resolve3, canonicalItems, "SELECT");
35400
+ }
35401
+ if (stmt.having) {
35402
+ const refs = [];
35403
+ collectNonAggregateFieldRefs(stmt.having, refs);
35404
+ for (const ref of refs) {
35405
+ if (ref.tableAlias === null && aliases.has(ref.field) || isAggregateSyntheticReference(ref)) continue;
35406
+ validateDependency(ref, resolve3, canonicalItems, "HAVING");
35407
+ }
35408
+ }
35409
+ for (const order of stmt.orderBy) {
35410
+ for (const ref of keyDependencies(order.key)) {
35411
+ if (ref.tableAlias === null && aliases.has(ref.field) || isAggregateSyntheticReference(ref)) continue;
35412
+ validateDependency(ref, resolve3, canonicalItems, "ORDER BY");
35413
+ }
35414
+ }
35415
+ const collisionKeys = /* @__PURE__ */ new Set();
35416
+ for (const item of resolvedItems) {
35417
+ collisionKeys.add(item.directKey);
35418
+ if (item.unqualifiedBridgeKey !== null) collisionKeys.add(item.unqualifiedBridgeKey);
35419
+ }
35420
+ for (const column of stmt.columns) {
35421
+ if (!isAggregateMaterializedAlias(column)) continue;
35422
+ const alias = "alias" in column ? column.alias : null;
35423
+ if (alias === null) continue;
35424
+ if (collisionKeys.has(alias)) {
35425
+ throw new Error(
35426
+ `ArgumentError: B65 aggregate alias ${alias} collides with a grouping runtime key (reason=B65_AGGREGATE_ALIAS_COLLISION).`
35427
+ );
35428
+ }
35429
+ }
35430
+ return resolvedSpec;
35431
+ }
35432
+
35433
+ // src/converter/selectToKintone.ts
35434
+ function hasWindowColumns(columns) {
35435
+ return columns.some((column) => column.type === "WINDOW_COL");
35436
+ }
35437
+ function resolveSelectMode(stmt) {
35438
+ if (stmt.from.subtableCode) return "FULL_SCAN";
35439
+ if (stmt.joins.some((j) => j.table.subtableCode)) return "FULL_SCAN";
35440
+ if (stmt.joins.length > 0) return "FULL_SCAN";
35441
+ if (normalizeGroupingSpec(stmt).type !== "NONE") return "FULL_SCAN";
35442
+ if (stmt.distinct) return "FULL_SCAN";
35443
+ if (hasWindowColumns(stmt.columns)) return "FULL_SCAN";
35444
+ if (stmt.columns.some(
35445
+ (c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "SCALAR_SUBQUERY_COL" || c.type === "CASE_COL" && containsAggregate2(c.expr) || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr(c.expr) || c.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate(c.expr)
35446
+ )) return "FULL_SCAN";
35447
+ if (whereRequiresJsEval(stmt.where)) return "FULL_SCAN";
35448
+ if (stmt.orderBy.some((o) => o.key.type !== "FIELD_NAME")) return "FULL_SCAN";
35449
+ return "SIMPLE";
35450
+ }
35451
+ function whereRequiresJsEval(where) {
35452
+ if (where === null) return false;
35453
+ switch (where.type) {
35454
+ case "BOOLEAN":
35455
+ return true;
35456
+ case "BINARY":
35457
+ return isFunc(where.left) || where.right.type === "ARITH_VALUE" || where.right.type === "CASE_VALUE" || where.right.type === "SUBQUERY_IN_LIST" || where.right.type === "SCALAR_SUBQUERY" || isLike(where);
35458
+ case "NULL_CHECK":
35459
+ return isFunc(where.field);
35460
+ case "LOGICAL":
35461
+ return whereRequiresJsEval(where.left) || whereRequiresJsEval(where.right);
35462
+ case "NOT":
35463
+ case "GROUP":
35464
+ return whereRequiresJsEval(where.expr);
35465
+ case "EXISTS":
35466
+ return true;
35467
+ }
35468
+ }
35469
+ function isFunc(fv) {
35470
+ return fv.type === "FUNC_FIELD" || fv.type === "ARITH_FIELD" || fv.type === "CASE_FIELD";
35471
+ }
35472
+ function selectToKintoneParams(stmt) {
35473
+ const queryParts = [];
35474
+ const hasPagination = stmt.limit !== null || stmt.offset !== null;
35475
+ const shouldInjectDefaultOrder = hasPagination && stmt.orderBy.length === 0;
35476
+ if (stmt.where !== null) {
35477
+ queryParts.push(whereToKintone(stmt.where));
35478
+ }
35479
+ if (stmt.orderBy.length > 0) {
35480
+ const orderStr = stmt.orderBy.map(convertOrderBy).join(", ");
35481
+ queryParts.push(`order by ${orderStr}`);
35482
+ } else if (shouldInjectDefaultOrder) {
35483
+ queryParts.push("order by $id asc");
35484
+ }
35485
+ if (stmt.limit !== null) {
35486
+ queryParts.push(`limit ${stmt.limit}`);
35487
+ }
35488
+ if (stmt.offset !== null) {
35489
+ queryParts.push(`offset ${stmt.offset}`);
35490
+ }
35491
+ return {
35492
+ app: stmt.from.appId,
35493
+ query: queryParts.join(" "),
35494
+ fields: extractFields(stmt.columns),
35495
+ totalCount: false
35496
+ };
35497
+ }
35498
+ function selectToFetchAllParams(stmt, appId) {
35499
+ const queryParts = [];
35500
+ if (stmt.where !== null && stmt.joins.length === 0 && !whereRequiresJsEval(stmt.where)) {
35501
+ queryParts.push(whereToKintone(stmt.where));
35502
+ }
35503
+ return {
35504
+ app: appId,
35505
+ query: queryParts.join(" "),
35506
+ fields: []
35507
+ // 全件取得なので全フィールドを取得する
35508
+ };
35509
+ }
35510
+ function selectToFetchAllFields(stmt, targetTable, plainGroupByPlan) {
35511
+ const plan = collectRequiredFieldsByTable(stmt, plainGroupByPlan);
35512
+ const target = plan.get(targetTable);
35513
+ if (!target) return [];
35514
+ if (target.allFields) return [];
35515
+ const fields = new Set(target.fields);
35516
+ if (target.table.subtableCode) {
35517
+ fields.add(target.table.subtableCode);
35518
+ }
35519
+ if (fields.size === 0) fields.add("$id");
35520
+ return [...fields];
35521
+ }
35522
+ function convertOrderBy(item) {
35523
+ const dir = item.direction === "ASC" ? "asc" : "desc";
35524
+ if (item.key.type !== "FIELD_NAME") {
35525
+ throw new Error("ORDER BY \u5F0F\u306F kintone \u30AF\u30A8\u30EA\u306B\u5909\u63DB\u3067\u304D\u307E\u305B\u3093\uFF08FULL_SCAN \u304C\u5FC5\u8981\u3067\u3059\uFF09");
35526
+ }
35527
+ return `${item.key.name} ${dir}`;
35528
+ }
35529
+ function extractFields(columns) {
35530
+ const hasWildcard = columns.some(
35531
+ (c) => c.type === "WILDCARD" || c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "CASE_COL" || c.type === "SCALAR_SUBQUERY_COL"
35532
+ );
35533
+ if (hasWildcard) return [];
35534
+ const fields = [];
35535
+ for (const col of columns) {
35536
+ if (col.type === "FIELD") {
35537
+ fields.push(normalizeSimpleFieldRef(col.field));
35538
+ } else if (col.type === "ARITH_COL") {
35539
+ collectArithNode(col.expr, fields);
35540
+ } else if (col.type === "STRFUNC_COL") {
35541
+ collectStringFuncFields(col.expr, fields);
35542
+ } else if (col.type === "SCALAR_VALUE_COL") {
35543
+ collectScalarValueFields(col.expr, fields);
35544
+ }
35545
+ }
35546
+ return [...new Set(fields)];
35547
+ }
35548
+ function collectArithFields(expr, out) {
35549
+ collectArithNode(expr.left, out);
35550
+ collectArithNode(expr.right, out);
35551
+ }
35552
+ function collectArithNode(node, out) {
35553
+ if (node.type === "VARIABLE") throw new Error(
35554
+ `InternalError: unresolved arithmetic variable @${node.name} reached SELECT field collection.`
35555
+ );
35556
+ if (node.type === "FIELD_REF") out.push(normalizeSimpleFieldRef(node.field));
35557
+ else if (node.type === "ARITH") collectArithFields(node, out);
35558
+ else if (node.type === "STRING_FUNC") collectStringFuncFields(node, out);
35559
+ }
35560
+ function normalizeSimpleFieldRef(field) {
35561
+ const dot = field.indexOf(".");
35562
+ if (dot <= 0) return field;
35563
+ const unqualified = field.slice(dot + 1);
35564
+ return unqualified || field;
35565
+ }
35566
+ function collectStringFuncFields(expr, out) {
35567
+ for (const arg of expr.args) {
35568
+ collectStringFuncArgFields(arg, out);
35569
+ }
35570
+ }
35571
+ function collectStringFuncArgFields(arg, out) {
35572
+ if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
35573
+ collectAggOperandFields(arg, out);
35574
+ return;
35575
+ }
35576
+ collectScalarValueFields(arg, out);
35577
+ }
35578
+ function collectScalarValueFields(expr, out) {
35579
+ if (expr.type === "FIELD") {
35580
+ out.push(normalizeSimpleFieldRef(expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field));
35581
+ return;
35582
+ }
35583
+ if (expr.type === "STRING_FUNC") {
35584
+ collectStringFuncFields(expr, out);
35585
+ return;
35586
+ }
35587
+ if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
35588
+ collectScalarValueFields(expr.left, out);
35589
+ collectScalarValueFields(expr.right, out);
35590
+ return;
35591
+ }
35592
+ if (expr.type === "CASE_WHEN") {
35593
+ for (const branch of expr.branches) collectCaseResultScalarFields(branch.result, out);
35594
+ if (expr.elseResult) collectCaseResultScalarFields(expr.elseResult, out);
35595
+ }
35596
+ }
35597
+ function collectCaseResultScalarFields(result, out) {
35598
+ if (result.type === "ARRAY") return;
35599
+ if (result.type === "AGG_REF" || result.type === "AGG_ARITH") {
35600
+ collectAggOperandFields(result, out);
35601
+ return;
35602
+ }
35603
+ if (result.type === "FIELD_REF" || result.type === "ARITH") {
35604
+ collectArithNode(result, out);
35605
+ return;
35606
+ }
35607
+ collectScalarValueFields(result, out);
35608
+ }
35609
+ function collectAggOperandFields(node, out) {
35610
+ if (node.type === "AGG_REF") {
35611
+ if (node.arg.type !== "WILDCARD") collectAggregateArgFields(node.arg, out);
35612
+ return;
35613
+ }
35614
+ if (node.type === "AGG_ARITH") {
35615
+ collectAggOperandFields(node.left, out);
35616
+ collectAggOperandFields(node.right, out);
35617
+ }
35618
+ }
35619
+ function collectAggregateArgFields(node, out) {
35301
35620
  if (node.type === "FIELD_REF" || node.type === "ARITH") collectArithNode(node, out);
35302
35621
  else collectScalarValueFields(node, out);
35303
35622
  }
@@ -35318,6 +35637,7 @@ function scalarValueHasAggregate(expr) {
35318
35637
  return false;
35319
35638
  }
35320
35639
  function caseResultHasAggregate(result) {
35640
+ if (result.type === "AGG_REF" || result.type === "AGG_ARITH") return true;
35321
35641
  if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return false;
35322
35642
  return scalarValueHasAggregate(result);
35323
35643
  }
@@ -35526,6 +35846,10 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
35526
35846
  };
35527
35847
  const walkCaseResult = (result, phase = "select") => {
35528
35848
  if (result.type === "ARRAY") return;
35849
+ if (result.type === "AGG_REF" || result.type === "AGG_ARITH") {
35850
+ walkAgg(result, phase);
35851
+ return;
35852
+ }
35529
35853
  if (result.type === "FIELD_REF" || result.type === "ARITH") {
35530
35854
  walkArith(result, phase);
35531
35855
  return;
@@ -35541,6 +35865,10 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
35541
35865
  };
35542
35866
  const walkFieldValue = (fv, phase = "select") => {
35543
35867
  if (fv.type === "FIELD") {
35868
+ if (fv.aggregateRef) {
35869
+ walkAgg(fv.aggregateRef, phase);
35870
+ return;
35871
+ }
35544
35872
  addFieldRef(fv.field, fv.tableAlias, phase);
35545
35873
  return;
35546
35874
  }
@@ -35548,6 +35876,10 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
35548
35876
  walkStringFunc(fv.expr, phase);
35549
35877
  return;
35550
35878
  }
35879
+ if (fv.type === "AGG_FIELD") {
35880
+ walkAgg(fv.expr, phase);
35881
+ return;
35882
+ }
35551
35883
  if (fv.type === "ARITH_FIELD") {
35552
35884
  walkArith(fv.expr, phase);
35553
35885
  return;
@@ -36292,410 +36624,225 @@ function validateOwnKlikeExpressions(stmt) {
36292
36624
  }
36293
36625
  function validateNestedSelects(node) {
36294
36626
  walkObjects(node, (obj) => {
36295
- if (obj.type === "SELECT") validateSelect(obj);
36296
- }, true);
36297
- }
36298
- function containsKlike(node) {
36299
- let found = false;
36300
- walkObjects(node, (obj) => {
36301
- if (obj.type === "BINARY" && (obj.op === "KLIKE" || obj.op === "NOT_KLIKE")) found = true;
36302
- });
36303
- return found;
36304
- }
36305
- function containsKlikeOutsideWhereAndNestedSelects(node, allowedWhere) {
36306
- let found = false;
36307
- const visit = (value) => {
36308
- if (found || value === allowedWhere || value === null || typeof value !== "object") return;
36309
- if (Array.isArray(value)) {
36310
- for (const item of value) visit(item);
36311
- return;
36312
- }
36313
- const obj = value;
36314
- if (obj.type === "SELECT") return;
36315
- if (obj.type === "BINARY" && (obj.op === "KLIKE" || obj.op === "NOT_KLIKE")) {
36316
- found = true;
36317
- return;
36318
- }
36319
- for (const child of Object.values(obj)) visit(child);
36320
- };
36321
- visit(node);
36322
- return found;
36323
- }
36324
- function isDescendantOf(root, target) {
36325
- if (root === null) return false;
36326
- if (root === target) return true;
36327
- switch (root.type) {
36328
- case "LOGICAL":
36329
- return isDescendantOf(root.left, target) || isDescendantOf(root.right, target);
36330
- case "NOT":
36331
- case "GROUP":
36332
- return isDescendantOf(root.expr, target);
36333
- case "BINARY":
36334
- case "NULL_CHECK":
36335
- case "EXISTS":
36336
- return false;
36337
- case "BOOLEAN":
36338
- return false;
36339
- }
36340
- }
36341
- function walkWithoutNestedSelects(node, visitWhere) {
36342
- if (Array.isArray(node)) {
36343
- for (const value of node) walkWithoutNestedSelects(value, visitWhere);
36344
- return;
36345
- }
36346
- if (node === null || typeof node !== "object") return;
36347
- const obj = node;
36348
- if (obj.type === "BINARY" || obj.type === "NULL_CHECK" || obj.type === "LOGICAL" || obj.type === "NOT" || obj.type === "GROUP" || obj.type === "EXISTS") {
36349
- visitWhere(obj);
36350
- }
36351
- for (const value of Object.values(obj)) {
36352
- if (value !== node && isSelectObject(value)) continue;
36353
- walkWithoutNestedSelects(value, visitWhere);
36354
- }
36355
- }
36356
- function walkObjects(node, visit, skipRoot = false) {
36357
- if (Array.isArray(node)) {
36358
- for (const value of node) walkObjects(value, visit);
36359
- return;
36360
- }
36361
- if (node === null || typeof node !== "object") return;
36362
- const obj = node;
36363
- if (!skipRoot) visit(obj);
36364
- for (const value of Object.values(obj)) walkObjects(value, visit);
36365
- }
36366
- function isSelectObject(value) {
36367
- return value !== null && typeof value === "object" && value.type === "SELECT";
36368
- }
36369
-
36370
- // src/core/primaryOrganizationDmlValidation.ts
36371
- init_define_KSQL_DOCS();
36372
- var PrimaryOrganizationDmlValidationError = class extends Error {
36373
- constructor() {
36374
- super(
36375
- "ArgumentError: PRIMARY_ORGANIZATION() \u306F DML \u306E WHERE \u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093"
36376
- );
36377
- this.name = "ArgumentError";
36378
- }
36379
- };
36380
- function validatePrimaryOrganizationDmlStatement(stmt) {
36381
- const target = stmt.type === "EXPLAIN" ? stmt.query : stmt;
36382
- switch (target.type) {
36383
- case "UPDATE":
36384
- case "DELETE":
36385
- case "UPSERT":
36386
- case "UPSERT_SELECT":
36387
- case "INSERT_SELECT":
36388
- if (hasPrimaryOrganizationInWhere(target)) {
36389
- throw new PrimaryOrganizationDmlValidationError();
36390
- }
36391
- return;
36392
- default:
36393
- return;
36394
- }
36627
+ if (obj.type === "SELECT") validateSelect(obj);
36628
+ }, true);
36395
36629
  }
36396
- function hasPrimaryOrganizationInWhere(node) {
36630
+ function containsKlike(node) {
36397
36631
  let found = false;
36398
- walkObjects2(node, (obj) => {
36399
- if (found || !Object.prototype.hasOwnProperty.call(obj, "where")) return;
36400
- if (containsPrimaryOrganization(obj.where)) found = true;
36632
+ walkObjects(node, (obj) => {
36633
+ if (obj.type === "BINARY" && (obj.op === "KLIKE" || obj.op === "NOT_KLIKE")) found = true;
36401
36634
  });
36402
36635
  return found;
36403
36636
  }
36404
- function containsPrimaryOrganization(node) {
36637
+ function containsKlikeOutsideWhereAndNestedSelects(node, allowedWhere) {
36405
36638
  let found = false;
36406
- walkObjects2(node, (obj) => {
36407
- if (obj.type === "KINTONE_FUNC" && obj.name === "PRIMARY_ORGANIZATION") {
36639
+ const visit = (value) => {
36640
+ if (found || value === allowedWhere || value === null || typeof value !== "object") return;
36641
+ if (Array.isArray(value)) {
36642
+ for (const item of value) visit(item);
36643
+ return;
36644
+ }
36645
+ const obj = value;
36646
+ if (obj.type === "SELECT") return;
36647
+ if (obj.type === "BINARY" && (obj.op === "KLIKE" || obj.op === "NOT_KLIKE")) {
36408
36648
  found = true;
36649
+ return;
36409
36650
  }
36410
- });
36651
+ for (const child of Object.values(obj)) visit(child);
36652
+ };
36653
+ visit(node);
36411
36654
  return found;
36412
36655
  }
36413
- function walkObjects2(node, visit) {
36414
- if (Array.isArray(node)) {
36415
- for (const value of node) walkObjects2(value, visit);
36416
- return;
36417
- }
36418
- if (node === null || typeof node !== "object") return;
36419
- const obj = node;
36420
- visit(obj);
36421
- for (const value of Object.values(obj)) walkObjects2(value, visit);
36422
- }
36423
-
36424
- // src/core/statementValidation.ts
36425
- init_define_KSQL_DOCS();
36426
- function validateStatementStatic(stmt) {
36427
- validatePrimaryOrganizationDmlStatement(stmt);
36428
- validateKlikeStatement(stmt);
36429
- }
36430
-
36431
- // src/core/groupingValidation.ts
36432
- init_define_KSQL_DOCS();
36433
-
36434
- // src/engine/groupingRowMeta.ts
36435
- init_define_KSQL_DOCS();
36436
- var groupingRowMetaKey = /* @__PURE__ */ Symbol("ksql.groupingRowMeta");
36437
- var groupingRefCanonicalIds = /* @__PURE__ */ new WeakMap();
36438
- function attachGroupingRowMeta(row, includedCanonicalIds) {
36439
- Object.defineProperty(row, groupingRowMetaKey, {
36440
- value: { includedCanonicalIds },
36441
- enumerable: false,
36442
- configurable: false,
36443
- writable: false
36444
- });
36445
- return row;
36446
- }
36447
- function getGroupingRowMeta(row) {
36448
- return row[groupingRowMetaKey];
36449
- }
36450
- function readGroupingMembership(row) {
36451
- return getGroupingRowMeta(row)?.includedCanonicalIds;
36452
- }
36453
- function bindGroupingRefCanonicalId(ref, canonicalId) {
36454
- groupingRefCanonicalIds.set(ref, canonicalId);
36455
- }
36456
- function evalGroupingRef(ref, row) {
36457
- const membership = readGroupingMembership(row);
36458
- if (!membership) {
36459
- throw new Error("internal error: GROUPING() evaluation requires B65 grouping row membership.");
36460
- }
36461
- const canonicalId = groupingRefCanonicalIds.get(ref);
36462
- if (!canonicalId) {
36463
- throw new Error("internal error: GROUPING() reference was not resolved during B65 planning.");
36464
- }
36465
- return membership.has(canonicalId) ? "0" : "1";
36466
- }
36467
-
36468
- // src/core/groupingValidation.ts
36469
- var enforceGroupingPlanningCandidateLimits = (facts) => {
36470
- if (facts.expandedSetCount > B65_MAX_GROUPING_SETS) {
36471
- throw new Error(
36472
- `ArgumentError: B65 expanded grouping set count ${facts.expandedSetCount} exceeds limit ${B65_MAX_GROUPING_SETS} (reason=GROUPING_SET_LIMIT_EXCEEDED).`
36473
- );
36474
- }
36475
- if (facts.canonicalItemCount > B65_MAX_GROUPING_ITEMS) {
36476
- throw new Error(
36477
- `ArgumentError: B65 canonical grouping item count ${facts.canonicalItemCount} exceeds limit ${B65_MAX_GROUPING_ITEMS} (reason=GROUPING_ITEM_LIMIT_EXCEEDED).`
36478
- );
36656
+ function isDescendantOf(root, target) {
36657
+ if (root === null) return false;
36658
+ if (root === target) return true;
36659
+ switch (root.type) {
36660
+ case "LOGICAL":
36661
+ return isDescendantOf(root.left, target) || isDescendantOf(root.right, target);
36662
+ case "NOT":
36663
+ case "GROUP":
36664
+ return isDescendantOf(root.expr, target);
36665
+ case "BINARY":
36666
+ case "NULL_CHECK":
36667
+ case "EXISTS":
36668
+ return false;
36669
+ case "BOOLEAN":
36670
+ return false;
36479
36671
  }
36480
- };
36481
- function displayField(field) {
36482
- return field.tableAlias ? `${field.tableAlias}.${field.field}` : field.field;
36483
- }
36484
- function refFromName(name) {
36485
- const dot = name.indexOf(".");
36486
- return dot > 0 ? { type: "FIELD", tableAlias: name.slice(0, dot), field: name.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field: name };
36487
36672
  }
36488
- function collectGroupingRefs(node, out) {
36489
- if (node === null || typeof node !== "object") return;
36673
+ function walkWithoutNestedSelects(node, visitWhere) {
36490
36674
  if (Array.isArray(node)) {
36491
- node.forEach((item) => collectGroupingRefs(item, out));
36492
- return;
36493
- }
36494
- const value = node;
36495
- if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
36496
- if (value["type"] === "GROUPING_REF") {
36497
- out.push(value);
36675
+ for (const value of node) walkWithoutNestedSelects(value, visitWhere);
36498
36676
  return;
36499
36677
  }
36500
- Object.values(value).forEach((item) => collectGroupingRefs(item, out));
36501
- }
36502
- function collectAggregateArgumentGroupingRefs(node, out) {
36503
36678
  if (node === null || typeof node !== "object") return;
36504
- if (Array.isArray(node)) {
36505
- node.forEach((item) => collectAggregateArgumentGroupingRefs(item, out));
36506
- return;
36679
+ const obj = node;
36680
+ if (obj.type === "BINARY" || obj.type === "NULL_CHECK" || obj.type === "LOGICAL" || obj.type === "NOT" || obj.type === "GROUP" || obj.type === "EXISTS") {
36681
+ visitWhere(obj);
36507
36682
  }
36508
- const value = node;
36509
- if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
36510
- if (value["type"] === "AGGREGATE" || value["type"] === "AGG_REF") {
36511
- collectGroupingRefs(value["arg"], out);
36512
- return;
36683
+ for (const value of Object.values(obj)) {
36684
+ if (value !== node && isSelectObject(value)) continue;
36685
+ walkWithoutNestedSelects(value, visitWhere);
36513
36686
  }
36514
- Object.values(value).forEach((item) => collectAggregateArgumentGroupingRefs(item, out));
36515
36687
  }
36516
- function collectNonAggregateFieldRefs(node, out) {
36517
- if (node === null || typeof node !== "object") return;
36688
+ function walkObjects(node, visit, skipRoot = false) {
36518
36689
  if (Array.isArray(node)) {
36519
- node.forEach((item) => collectNonAggregateFieldRefs(item, out));
36520
- return;
36521
- }
36522
- const value = node;
36523
- const type = value["type"];
36524
- if (type === "SELECT" || type === "SCALAR_SUBQUERY" || type === "GROUPING_REF" || type === "AGG_REF" || type === "AGG_ARITH") return;
36525
- if (type === "FIELD" && typeof value["field"] === "string") {
36526
- out.push({
36527
- type: "FIELD",
36528
- tableAlias: typeof value["tableAlias"] === "string" ? value["tableAlias"] : null,
36529
- field: value["field"]
36530
- });
36531
- return;
36532
- }
36533
- if (type === "FIELD_REF" && typeof value["field"] === "string") {
36534
- out.push(refFromName(value["field"]));
36535
- return;
36536
- }
36537
- Object.values(value).forEach((item) => collectNonAggregateFieldRefs(item, out));
36538
- }
36539
- function containsAggregate2(node) {
36540
- if (node === null || typeof node !== "object") return false;
36541
- if (Array.isArray(node)) return node.some(containsAggregate2);
36542
- const value = node;
36543
- if (value["type"] === "AGG_REF" || value["type"] === "AGG_ARITH") return true;
36544
- if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return false;
36545
- return Object.values(value).some(containsAggregate2);
36546
- }
36547
- function isAggregateMaterializedAlias(column) {
36548
- if (!("alias" in column) || column.alias === null) return false;
36549
- if (column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL") return true;
36550
- if (column.type === "STRFUNC_COL" || column.type === "SCALAR_VALUE_COL") {
36551
- return containsAggregate2(column);
36552
- }
36553
- return false;
36554
- }
36555
- function outputAliases(columns) {
36556
- return new Set(columns.flatMap(
36557
- (column) => "alias" in column && typeof column.alias === "string" ? [column.alias] : []
36558
- ));
36559
- }
36560
- function isAggregateSyntheticReference(ref) {
36561
- return ref.tableAlias === null && /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/.test(ref.field);
36562
- }
36563
- function validateGroupingRefMembership(ref, resolve3, canonicalItems) {
36564
- const resolved = resolve3(ref.field);
36565
- if (!resolved.physical) {
36566
- throw new Error(`ArgumentError: B65 grouping reference ${displayField(ref.field)} must resolve to a physical APP field.`);
36567
- }
36568
- if (!canonicalItems.has(resolved.canonicalId)) {
36569
- throw new Error(
36570
- `ArgumentError: B65 GROUPING argument ${displayField(ref.field)} is not present in grouping allItems (reason=B65_GROUPING_ARG_NOT_ITEM).`
36571
- );
36572
- }
36573
- bindGroupingRefCanonicalId(ref, resolved.canonicalId);
36574
- }
36575
- function validateDependency(ref, resolve3, canonicalItems, context) {
36576
- const resolved = resolve3(ref);
36577
- if (!resolved.physical || !canonicalItems.has(resolved.canonicalId)) {
36578
- throw new Error(
36579
- `ArgumentError: B65 non-aggregate field ${displayField(ref)} in ${context} is not a grouping item (reason=B65_NON_GROUPED_DEPENDENCY).`
36580
- );
36581
- }
36582
- }
36583
- function keyDependencies(key) {
36584
- if (key.type === "GROUPING_KEY") return [];
36585
- if (key.type === "FIELD_NAME") return [refFromName(key.name)];
36586
- const refs = [];
36587
- collectNonAggregateFieldRefs(key, refs);
36588
- return refs;
36589
- }
36590
- function validateGroupingStatic(stmt) {
36591
- const normalized = normalizeGroupingSpec(stmt);
36592
- const groupingRefs = [];
36593
- for (const column of stmt.columns) {
36594
- if (column.type !== "WINDOW_COL") collectGroupingRefs(column, groupingRefs);
36595
- }
36596
- collectGroupingRefs(stmt.having, groupingRefs);
36597
- collectGroupingRefs(stmt.orderBy, groupingRefs);
36598
- const forbiddenGroupingRefs = [];
36599
- collectGroupingRefs(stmt.where, forbiddenGroupingRefs);
36600
- collectGroupingRefs(stmt.joins, forbiddenGroupingRefs);
36601
- collectAggregateArgumentGroupingRefs(stmt.columns, forbiddenGroupingRefs);
36602
- collectAggregateArgumentGroupingRefs(stmt.having, forbiddenGroupingRefs);
36603
- for (const column of stmt.columns) {
36604
- if (column.type === "WINDOW_COL") collectGroupingRefs(column, forbiddenGroupingRefs);
36605
- }
36606
- if (forbiddenGroupingRefs.length > 0) {
36607
- throw new Error(
36608
- "ArgumentError: B65 GROUPING() is not allowed in WHERE, JOIN, window, aggregate arguments, or DML expressions."
36609
- );
36610
- }
36611
- if (normalized.type !== "GROUPING_SETS") {
36612
- if (groupingRefs.length > 0) {
36613
- throw new Error("ArgumentError: B65 GROUPING() requires GROUP BY ROLLUP or GROUPING SETS.");
36614
- }
36690
+ for (const value of node) walkObjects(value, visit);
36615
36691
  return;
36616
36692
  }
36617
- if (stmt.orderMode === "KINTONE_NATIVE") {
36618
- throw new Error("ArgumentError: B65 KORDER BY is not supported in Phase1.");
36619
- }
36620
- if (stmt.columns.some((column) => column.type === "WINDOW_COL")) {
36621
- throw new Error("ArgumentError: B65 window functions are not supported in Phase1.");
36622
- }
36623
- if (stmt.columns.some(
36624
- (column) => column.type === "WILDCARD" || column.type === "PARENT_WILDCARD"
36625
- )) {
36626
- throw new Error("ArgumentError: B65 wildcard projection is not supported in Phase1.");
36627
- }
36693
+ if (node === null || typeof node !== "object") return;
36694
+ const obj = node;
36695
+ if (!skipRoot) visit(obj);
36696
+ for (const value of Object.values(obj)) walkObjects(value, visit);
36628
36697
  }
36629
- function validateGroupingPlanning(stmt, resolve3, planningGuardHook = () => void 0) {
36630
- validateGroupingStatic(stmt);
36631
- const normalized = normalizeGroupingSpec(stmt);
36632
- const groupingRefs = [];
36633
- for (const column of stmt.columns) {
36634
- if (column.type !== "WINDOW_COL") collectGroupingRefs(column, groupingRefs);
36698
+ function isSelectObject(value) {
36699
+ return value !== null && typeof value === "object" && value.type === "SELECT";
36700
+ }
36701
+
36702
+ // src/core/primaryOrganizationDmlValidation.ts
36703
+ init_define_KSQL_DOCS();
36704
+ var PrimaryOrganizationDmlValidationError = class extends Error {
36705
+ constructor() {
36706
+ super(
36707
+ "ArgumentError: PRIMARY_ORGANIZATION() \u306F DML \u306E WHERE \u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093"
36708
+ );
36709
+ this.name = "ArgumentError";
36635
36710
  }
36636
- collectGroupingRefs(stmt.having, groupingRefs);
36637
- collectGroupingRefs(stmt.orderBy, groupingRefs);
36638
- if (normalized.type !== "GROUPING_SETS") {
36639
- return null;
36711
+ };
36712
+ function validatePrimaryOrganizationDmlStatement(stmt) {
36713
+ const target = stmt.type === "EXPLAIN" ? stmt.query : stmt;
36714
+ switch (target.type) {
36715
+ case "UPDATE":
36716
+ case "DELETE":
36717
+ case "UPSERT":
36718
+ case "UPSERT_SELECT":
36719
+ case "INSERT_SELECT":
36720
+ if (hasPrimaryOrganizationInWhere(target)) {
36721
+ throw new PrimaryOrganizationDmlValidationError();
36722
+ }
36723
+ return;
36724
+ default:
36725
+ return;
36640
36726
  }
36641
- const resolvedSpec = resolveGroupingSpec(stmt, resolve3);
36642
- const canonicalItems = /* @__PURE__ */ new Set();
36643
- const resolvedItems = [];
36644
- for (const item of resolvedSpec.allItems) {
36645
- const resolved = item;
36646
- if (!resolved.physical) {
36647
- throw new Error(`ArgumentError: B65 grouping item ${displayField(item.field)} must resolve to a physical APP field.`);
36648
- }
36649
- if (!canonicalItems.has(resolved.canonicalId)) {
36650
- canonicalItems.add(resolved.canonicalId);
36651
- resolvedItems.push(resolved);
36727
+ }
36728
+ function hasPrimaryOrganizationInWhere(node) {
36729
+ let found = false;
36730
+ walkObjects2(node, (obj) => {
36731
+ if (found || !Object.prototype.hasOwnProperty.call(obj, "where")) return;
36732
+ if (containsPrimaryOrganization(obj.where)) found = true;
36733
+ });
36734
+ return found;
36735
+ }
36736
+ function containsPrimaryOrganization(node) {
36737
+ let found = false;
36738
+ walkObjects2(node, (obj) => {
36739
+ if (obj.type === "KINTONE_FUNC" && obj.name === "PRIMARY_ORGANIZATION") {
36740
+ found = true;
36652
36741
  }
36653
- }
36654
- planningGuardHook({
36655
- expandedSetCount: normalized.sets.length,
36656
- canonicalItemCount: canonicalItems.size
36657
36742
  });
36658
- for (const ref of groupingRefs) {
36659
- validateGroupingRefMembership(ref, resolve3, canonicalItems);
36660
- }
36661
- const aliases = outputAliases(stmt.columns);
36662
- for (const column of stmt.columns) {
36663
- if (column.type === "GROUPING_COL" || column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL" || column.type === "LITERAL_COL" || column.type === "VARIABLE_COL" || column.type === "SCALAR_SUBQUERY_COL") continue;
36664
- const refs = [];
36665
- if (column.type === "FIELD") refs.push(refFromName(column.field));
36666
- else collectNonAggregateFieldRefs(column, refs);
36667
- for (const ref of refs) validateDependency(ref, resolve3, canonicalItems, "SELECT");
36743
+ return found;
36744
+ }
36745
+ function walkObjects2(node, visit) {
36746
+ if (Array.isArray(node)) {
36747
+ for (const value of node) walkObjects2(value, visit);
36748
+ return;
36668
36749
  }
36669
- if (stmt.having) {
36670
- const refs = [];
36671
- collectNonAggregateFieldRefs(stmt.having, refs);
36672
- for (const ref of refs) {
36673
- if (ref.tableAlias === null && aliases.has(ref.field) || isAggregateSyntheticReference(ref)) continue;
36674
- validateDependency(ref, resolve3, canonicalItems, "HAVING");
36675
- }
36750
+ if (node === null || typeof node !== "object") return;
36751
+ const obj = node;
36752
+ visit(obj);
36753
+ for (const value of Object.values(obj)) walkObjects2(value, visit);
36754
+ }
36755
+
36756
+ // src/core/statementValidation.ts
36757
+ init_define_KSQL_DOCS();
36758
+
36759
+ // src/core/functionArity.ts
36760
+ init_define_KSQL_DOCS();
36761
+ function assertArity(func, args, min, max = Number.POSITIVE_INFINITY) {
36762
+ if (args.length >= min && args.length <= max) return;
36763
+ const expected = min === max ? String(min) : max === Number.POSITIVE_INFINITY ? `${min} or more` : `${min} to ${max}`;
36764
+ throw new Error(`ArgumentError: ${func} expects ${expected} argument(s).`);
36765
+ }
36766
+ function assertStringFunctionArity(func, args) {
36767
+ switch (func) {
36768
+ case "UPPER":
36769
+ case "LOWER":
36770
+ case "TRIM":
36771
+ case "LTRIM":
36772
+ case "RTRIM":
36773
+ case "LENGTH":
36774
+ case "LENGTH_CHAR":
36775
+ case "YEAR":
36776
+ case "MONTH":
36777
+ case "DAY":
36778
+ case "DAYOFWEEK":
36779
+ case "QUARTER":
36780
+ case "WEEK":
36781
+ case "LAST_DAY":
36782
+ case "ABS":
36783
+ case "SQRT":
36784
+ return assertArity(func, args, 1, 1);
36785
+ case "SUBSTRING":
36786
+ case "LPAD":
36787
+ case "RPAD":
36788
+ case "REGEXP_LIKE":
36789
+ case "REGEXP_SUBSTR":
36790
+ return assertArity(func, args, 2, 3);
36791
+ case "LEFT":
36792
+ case "RIGHT":
36793
+ case "INSTR":
36794
+ case "ISNULL":
36795
+ case "NULLIF":
36796
+ case "MOD":
36797
+ case "POWER":
36798
+ case "FORMAT":
36799
+ case "CAST":
36800
+ case "DATE_FORMAT":
36801
+ case "DATEDIFF":
36802
+ return assertArity(func, args, 2, 2);
36803
+ case "CONCAT":
36804
+ case "COALESCE":
36805
+ case "GREATEST":
36806
+ case "LEAST":
36807
+ return assertArity(func, args, 2);
36808
+ case "REPLACE":
36809
+ case "TRANSLATE":
36810
+ case "DATE_ADD":
36811
+ return assertArity(func, args, 3, 3);
36812
+ case "REGEXP_REPLACE":
36813
+ return assertArity(func, args, 3, 5);
36814
+ case "ROUND":
36815
+ case "FLOOR":
36816
+ case "CEIL":
36817
+ case "TRUNCATE":
36818
+ return assertArity(func, args, 1, 2);
36819
+ case "CURRENT_DATE":
36820
+ case "CURRENT_TIMESTAMP":
36821
+ return assertArity(func, args, 0, 0);
36676
36822
  }
36677
- for (const order of stmt.orderBy) {
36678
- for (const ref of keyDependencies(order.key)) {
36679
- if (ref.tableAlias === null && aliases.has(ref.field) || isAggregateSyntheticReference(ref)) continue;
36680
- validateDependency(ref, resolve3, canonicalItems, "ORDER BY");
36823
+ }
36824
+
36825
+ // src/core/statementValidation.ts
36826
+ function validateStatementStatic(stmt) {
36827
+ validateStringFunctionArities(stmt);
36828
+ validatePrimaryOrganizationDmlStatement(stmt);
36829
+ validateKlikeStatement(stmt);
36830
+ }
36831
+ function validateStringFunctionArities(stmt) {
36832
+ const visit = (value) => {
36833
+ if (value === null || typeof value !== "object") return;
36834
+ if (Array.isArray(value)) {
36835
+ value.forEach(visit);
36836
+ return;
36681
36837
  }
36682
- }
36683
- const collisionKeys = /* @__PURE__ */ new Set();
36684
- for (const item of resolvedItems) {
36685
- collisionKeys.add(item.directKey);
36686
- if (item.unqualifiedBridgeKey !== null) collisionKeys.add(item.unqualifiedBridgeKey);
36687
- }
36688
- for (const column of stmt.columns) {
36689
- if (!isAggregateMaterializedAlias(column)) continue;
36690
- const alias = "alias" in column ? column.alias : null;
36691
- if (alias === null) continue;
36692
- if (collisionKeys.has(alias)) {
36693
- throw new Error(
36694
- `ArgumentError: B65 aggregate alias ${alias} collides with a grouping runtime key (reason=B65_AGGREGATE_ALIAS_COLLISION).`
36695
- );
36838
+ const node = value;
36839
+ if (node.type === "STRING_FUNC") {
36840
+ const expr = node;
36841
+ assertStringFunctionArity(expr.func, expr.args);
36696
36842
  }
36697
- }
36698
- return resolvedSpec;
36843
+ Object.values(node).forEach(visit);
36844
+ };
36845
+ visit(stmt);
36699
36846
  }
36700
36847
 
36701
36848
  // src/core/batch.ts
@@ -37474,6 +37621,7 @@ function replaceNthMatch(input, globalRe, replacement, n) {
37474
37621
  });
37475
37622
  }
37476
37623
  function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
37624
+ assertStringFunctionArity(expr.func, expr.args);
37477
37625
  const args = expr.args.map((a) => evalStringFuncArg(a, row, resolveFieldType, resolveFieldSemantics2));
37478
37626
  switch (expr.func) {
37479
37627
  case "UPPER":
@@ -37489,7 +37637,6 @@ function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
37489
37637
  case "LENGTH":
37490
37638
  return String((args[0] ?? "").length);
37491
37639
  case "LENGTH_CHAR":
37492
- assertArity("LENGTH_CHAR", args, 1, 1);
37493
37640
  return String([...args[0] ?? ""].length);
37494
37641
  case "SUBSTRING": {
37495
37642
  const str = args[0] ?? "";
@@ -37498,23 +37645,19 @@ function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
37498
37645
  return sliceSafeRange(str, start, len !== void 0 ? start + len : str.length);
37499
37646
  }
37500
37647
  case "LEFT": {
37501
- assertArity("LEFT", args, 2, 2);
37502
37648
  const str = args[0];
37503
37649
  const n = Math.trunc(Number(args[1]));
37504
37650
  return Number.isNaN(n) || n <= 0 ? "" : sliceSafePrefix(str, n);
37505
37651
  }
37506
37652
  case "RIGHT": {
37507
- assertArity("RIGHT", args, 2, 2);
37508
37653
  const str = args[0];
37509
37654
  const n = Math.trunc(Number(args[1]));
37510
37655
  return Number.isNaN(n) || n <= 0 ? "" : sliceSafeSuffix(str, n);
37511
37656
  }
37512
37657
  case "INSTR":
37513
- assertArity("INSTR", args, 2, 2);
37514
37658
  return String(args[0].indexOf(args[1]) + 1);
37515
37659
  case "LPAD":
37516
37660
  case "RPAD": {
37517
- assertArity(expr.func, args, 2, 3);
37518
37661
  const str = args[0];
37519
37662
  const n = Math.trunc(Number(args[1]));
37520
37663
  if (Number.isNaN(n) || n <= 0) return "";
@@ -37526,7 +37669,6 @@ function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
37526
37669
  }
37527
37670
  case "GREATEST":
37528
37671
  case "LEAST":
37529
- assertArity(expr.func, args, 2);
37530
37672
  return selectScalarExtreme(args, expr.func === "GREATEST" ? "greatest" : "least");
37531
37673
  case "CONCAT":
37532
37674
  return args.join("");
@@ -37537,22 +37679,18 @@ function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
37537
37679
  return from === "" ? str : str.split(from).join(to);
37538
37680
  }
37539
37681
  case "REGEXP_LIKE": {
37540
- assertArity("REGEXP_LIKE", args, 2, 3);
37541
37682
  return compileRegexp(args[1], args[2] ?? "").test(args[0]) ? "1" : "0";
37542
37683
  }
37543
37684
  case "REGEXP_REPLACE": {
37544
- assertArity("REGEXP_REPLACE", args, 3, 5);
37545
37685
  assertRegexpReplacement(args[2]);
37546
37686
  const occurrence = parseRegexpOccurrence(args[4]);
37547
37687
  const regexp = compileRegexp(args[1], args[3] ?? "", true);
37548
37688
  return occurrence === 0 ? args[0].replace(regexp, args[2]) : replaceNthMatch(args[0], regexp, args[2], occurrence);
37549
37689
  }
37550
37690
  case "REGEXP_SUBSTR": {
37551
- assertArity("REGEXP_SUBSTR", args, 2, 3);
37552
37691
  return compileRegexp(args[1], args[2] ?? "").exec(args[0])?.[0] ?? "";
37553
37692
  }
37554
37693
  case "TRANSLATE": {
37555
- assertArity("TRANSLATE", args, 3, 3);
37556
37694
  const from = [...args[1]];
37557
37695
  const to = [...args[2]];
37558
37696
  if (from.length !== to.length) {
@@ -37579,7 +37717,6 @@ function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
37579
37717
  case "CEIL":
37580
37718
  return applyRoundOp("ceil", Number(args[0] ?? "0"), Number(args[1] ?? "0"));
37581
37719
  case "TRUNCATE":
37582
- assertArity("TRUNCATE", args, 1, 2);
37583
37720
  return applyRoundOp("trunc", Number(args[0]), Number(args[1] ?? "0"));
37584
37721
  case "CAST": {
37585
37722
  const val = args[0] ?? "";
@@ -37608,13 +37745,10 @@ function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
37608
37745
  return d.length >= 10 ? String(parseInt(d.slice(8, 10), 10)) : "";
37609
37746
  }
37610
37747
  case "DAYOFWEEK":
37611
- assertArity(expr.func, args, 1, 1);
37612
37748
  return isValidYmd(args[0]) ? String(dayOfWeekIndex(args[0]) + 1) : "";
37613
37749
  case "QUARTER":
37614
- assertArity(expr.func, args, 1, 1);
37615
37750
  return isValidYmd(args[0]) ? String(Math.ceil(Number(args[0].slice(5, 7)) / 3)) : "";
37616
37751
  case "WEEK":
37617
- assertArity(expr.func, args, 1, 1);
37618
37752
  return isValidYmd(args[0]) ? String(isoWeekNumber(args[0])) : "";
37619
37753
  case "DATE_FORMAT":
37620
37754
  return applyDateFormat(args[0] ?? "", args[1] ?? "");
@@ -37623,7 +37757,6 @@ function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
37623
37757
  case "DATE_ADD":
37624
37758
  return applyDateAdd(args[0] ?? "", Number(args[1] ?? "0"), (args[2] ?? "DAY").toUpperCase());
37625
37759
  case "LAST_DAY":
37626
- assertArity("LAST_DAY", args, 1, 1);
37627
37760
  return applyLastDay(args[0]);
37628
37761
  case "ABS":
37629
37762
  return String(Math.abs(Number(args[0] ?? "0")));
@@ -37647,11 +37780,6 @@ function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
37647
37780
  return (/* @__PURE__ */ new Date()).toISOString();
37648
37781
  }
37649
37782
  }
37650
- function assertArity(func, args, min, max = Number.POSITIVE_INFINITY) {
37651
- if (args.length >= min && args.length <= max) return;
37652
- const expected = min === max ? String(min) : max === Number.POSITIVE_INFINITY ? `${min} or more` : `${min} to ${max}`;
37653
- throw new Error(`ArgumentError: ${func} expects ${expected} argument(s).`);
37654
- }
37655
37783
  function parseDateParts(s) {
37656
37784
  return {
37657
37785
  y: s.slice(0, 4) || "0000",
@@ -37812,10 +37940,32 @@ function formatWithComma(num, digits) {
37812
37940
  return decStr ? `${intFmt}.${decStr}` : intFmt;
37813
37941
  }
37814
37942
  function evalStringFuncArg(arg, row, resolveFieldType, resolveFieldSemantics2) {
37815
- if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return "";
37943
+ if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
37944
+ return String(evalMaterializedAggregateOperand(arg, row));
37945
+ }
37816
37946
  if (arg.type === "NUMBER") return numberLiteralText(arg);
37817
37947
  return String(evalScalarValueExpr(arg, row, resolveFieldType, resolveFieldSemantics2));
37818
37948
  }
37949
+ function evalMaterializedAggregateOperand(node, row) {
37950
+ if (node.type === "NUMBER") return node.value;
37951
+ if (node.type === "AGG_REF") {
37952
+ return row[aggregateSyntheticName(node.func, node.distinct, node.arg)] ?? "";
37953
+ }
37954
+ const left = Number(evalMaterializedAggregateOperand(node.left, row));
37955
+ const right = Number(evalMaterializedAggregateOperand(node.right, row));
37956
+ switch (node.op) {
37957
+ case "+":
37958
+ return left + right;
37959
+ case "-":
37960
+ return left - right;
37961
+ case "*":
37962
+ return left * right;
37963
+ case "/":
37964
+ return right !== 0 ? left / right : NaN;
37965
+ case "%":
37966
+ return right !== 0 ? left % right : NaN;
37967
+ }
37968
+ }
37819
37969
  function resolveFieldRef(row, field) {
37820
37970
  const direct = row[field];
37821
37971
  if (direct !== void 0) return direct;
@@ -37910,7 +38060,7 @@ function semanticsForLeft(left, fieldType, resolveSemantics) {
37910
38060
  if (left.type === "FIELD") {
37911
38061
  return resolveSemantics?.(left) ?? (fieldType ? resolveFieldSemantics({ fieldType }) : syntheticSemantics("string"));
37912
38062
  }
37913
- if (left.type === "ARITH_FIELD") return syntheticSemantics("number");
38063
+ if (left.type === "ARITH_FIELD" || left.type === "AGG_FIELD") return syntheticSemantics("number");
37914
38064
  if (left.type === "FUNC_FIELD") {
37915
38065
  return syntheticSemantics(NUMERIC_STRING_FUNCTIONS.has(left.expr.func) ? "number" : "string");
37916
38066
  }
@@ -38003,6 +38153,7 @@ function evalLogical(expr, row, resolveFieldType, appliedKlikes, resolveFieldSem
38003
38153
  }
38004
38154
  function resolveField(field, row, resolveFieldType, resolveFieldSemantics2) {
38005
38155
  if (field.type === "FUNC_FIELD") return evalStringFunc(field.expr, row);
38156
+ if (field.type === "AGG_FIELD") return String(evalMaterializedAggregateOperand(field.expr, row));
38006
38157
  if (field.type === "ARITH_FIELD") return String(evalArithExpr(field.expr, row));
38007
38158
  if (field.type === "CASE_FIELD") return evalCaseWhen(field.expr, row, resolveFieldType, resolveFieldSemantics2);
38008
38159
  if (field.type === "GROUPING_FIELD") return evalGroupingRef(field.ref, row);
@@ -38060,12 +38211,20 @@ function evalCaseWhenNullable(expr, row, resolveFieldType, resolveFieldSemantics
38060
38211
  }
38061
38212
  function evalCaseResultNullable(result, row, resolveFieldType, resolveFieldSemantics2) {
38062
38213
  if (result.type === "ARRAY") return result.elements.map((entry) => entry.value).join(",");
38214
+ if (result.type === "AGG_REF") {
38215
+ return row[aggregateSyntheticName(result.func, result.distinct, result.arg)] ?? "";
38216
+ }
38217
+ if (result.type === "AGG_ARITH") return row[aggregateOperandLabel(result)] ?? "";
38063
38218
  if (result.type === "FIELD_REF") return row[result.field] ?? "";
38064
38219
  if (result.type === "ARITH") return evalArithExpr(result, row);
38065
38220
  return evalScalarValueExprNullable(result, row, resolveFieldType, resolveFieldSemantics2);
38066
38221
  }
38067
38222
  function evalCaseResult(result, row, resolveFieldType, resolveFieldSemantics2) {
38068
38223
  if (result.type === "ARRAY") return result.elements.map((e) => e.value).join(",");
38224
+ if (result.type === "AGG_REF") {
38225
+ return row[aggregateSyntheticName(result.func, result.distinct, result.arg)] ?? "";
38226
+ }
38227
+ if (result.type === "AGG_ARITH") return row[aggregateOperandLabel(result)] ?? "";
38069
38228
  if (result.type === "FIELD_REF") {
38070
38229
  return row[result.field] ?? "";
38071
38230
  }
@@ -38331,6 +38490,10 @@ function collectAggregateArgFields2(node, out) {
38331
38490
  }
38332
38491
  function collectCaseResultFields(result, out) {
38333
38492
  if (result.type === "ARRAY") return;
38493
+ if (result.type === "AGG_REF" || result.type === "AGG_ARITH") {
38494
+ collectAggOperandFields2(result, out);
38495
+ return;
38496
+ }
38334
38497
  if (result.type === "FIELD_REF" || result.type === "ARITH") {
38335
38498
  collectArithNode2(result, out);
38336
38499
  return;
@@ -38552,6 +38715,9 @@ function evalCaseResultValue(result, row, fieldType) {
38552
38715
  if (result.type === "ARRAY") {
38553
38716
  return convertArray(result.elements.map((e) => e.value), fieldType);
38554
38717
  }
38718
+ if (result.type === "AGG_REF" || result.type === "AGG_ARITH") {
38719
+ throw new Error("InternalError: aggregate CASE result reached DML evaluation.");
38720
+ }
38555
38721
  if (result.type === "STRING") {
38556
38722
  return convertString2(result.value, fieldType);
38557
38723
  }
@@ -42787,7 +42953,7 @@ function applyFilter(rows, where, resolveFieldType, appliedKlikes, resolveFieldS
42787
42953
  }
42788
42954
  function hasAggregateColumns(columns) {
42789
42955
  return columns.some(
42790
- (c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(c.expr) || c.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate2(c.expr)
42956
+ (c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "CASE_COL" && containsAggregate2(c.expr) || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(c.expr) || c.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate2(c.expr)
42791
42957
  );
42792
42958
  }
42793
42959
  function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind, resolutionPlan, aliasEvaluationContext = {}) {
@@ -42892,26 +43058,72 @@ function groupingItemValue(item, row) {
42892
43058
  return row[item.directKey] ?? (item.unqualifiedBridgeKey === null ? void 0 : row[item.unqualifiedBridgeKey]) ?? "";
42893
43059
  }
42894
43060
  function materializeAggregateColumns(outRow, groupRows, columns, resolveAggSortKind) {
42895
- for (const col of columns) {
43061
+ for (const [columnIndex, col] of columns.entries()) {
42896
43062
  if (col.type === "AGGREGATE") {
42897
43063
  const syntheticKey = aggregateSyntheticName(col.func, col.distinct, col.arg);
42898
43064
  const value = String(evalAggregate(col.func, col.distinct, col.arg, col.separator, groupRows, resolveAggSortKind));
42899
43065
  outRow[col.alias ?? syntheticKey] = value;
42900
43066
  if (col.alias) outRow[syntheticKey] = value;
42901
43067
  } else if (col.type === "ARITH_AGG_COL") {
43068
+ materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
42902
43069
  const outputKey = col.alias ?? aggArithDefaultKey(col.expr);
42903
43070
  outRow[outputKey] = String(evalAggArithExpr(col.expr, groupRows, resolveAggSortKind));
42904
43071
  } else if (col.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(col.expr)) {
43072
+ materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
42905
43073
  const outputKey = col.alias ?? stringFuncDefaultKey(col.expr);
42906
43074
  const resolvedExpr = resolveAggInStringFuncExpr(col.expr, groupRows, resolveAggSortKind);
42907
43075
  outRow[outputKey] = evalStringFunc(resolvedExpr, outRow);
42908
43076
  } else if (col.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate2(col.expr)) {
43077
+ materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
42909
43078
  const outputKey = col.alias ?? scalarValueDefaultKey(col.expr);
42910
43079
  const resolvedExpr = resolveAggInScalarValue(col.expr, groupRows, resolveAggSortKind);
42911
43080
  outRow[outputKey] = String(evalScalarValueExpr(resolvedExpr, outRow));
43081
+ } else if (col.type === "CASE_COL" && containsAggregate2(col.expr)) {
43082
+ materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
43083
+ const resolvedExpr = resolveAggInCaseExpr(col.expr, groupRows, resolveAggSortKind);
43084
+ const resolveAggregateSemantics = (field) => field.aggregateRef ? aggregateResultSemantics(field.aggregateRef, resolveAggSortKind) : void 0;
43085
+ outRow[caseMaterializedKey(col.alias, columnIndex)] = evalCaseWhen(
43086
+ resolvedExpr,
43087
+ outRow,
43088
+ void 0,
43089
+ resolveAggregateSemantics
43090
+ );
42912
43091
  }
42913
43092
  }
42914
43093
  }
43094
+ function caseMaterializedKey(alias, columnIndex) {
43095
+ return alias ?? `__ksql_case_column_${columnIndex}`;
43096
+ }
43097
+ function collectAggregateRefs(node, out) {
43098
+ if (node === null || typeof node !== "object") return;
43099
+ if (Array.isArray(node)) {
43100
+ node.forEach((value2) => collectAggregateRefs(value2, out));
43101
+ return;
43102
+ }
43103
+ const value = node;
43104
+ if (value["type"] === "AGG_REF") {
43105
+ out.push(value);
43106
+ return;
43107
+ }
43108
+ if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
43109
+ Object.values(value).forEach((child) => collectAggregateRefs(child, out));
43110
+ }
43111
+ function materializeAggregateDependencies(outRow, rows, node, resolveAggSortKind) {
43112
+ const refs = [];
43113
+ collectAggregateRefs(node, refs);
43114
+ for (const ref of refs) {
43115
+ const key = aggregateSyntheticName(ref.func, ref.distinct, ref.arg);
43116
+ if (outRow[key] !== void 0) continue;
43117
+ outRow[key] = String(evalAggregate(
43118
+ ref.func,
43119
+ ref.distinct,
43120
+ ref.arg,
43121
+ ref.separator,
43122
+ rows,
43123
+ resolveAggSortKind
43124
+ ));
43125
+ }
43126
+ }
42915
43127
  function evalGroupByKey(key, row, resolution, columns, aliasEvaluationContext) {
42916
43128
  if (key.type === "FIELD_NAME") {
42917
43129
  if (!resolution) return row[key.name] ?? "";
@@ -42952,7 +43164,7 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
42952
43164
  const raw = row[arg.field];
42953
43165
  if (raw === void 0 || raw === "" && func !== "MIN" && func !== "MAX") continue;
42954
43166
  strVal = raw;
42955
- } else if (arg.type === "ARITH" || arg.type === "NUMBER" || arg.type === "STRING_FUNC") {
43167
+ } else if (arg.type === "ARITH" || arg.type === "NUMBER") {
42956
43168
  const n = evalArithExpr(arg, row);
42957
43169
  if (isNaN(n)) continue;
42958
43170
  strVal = String(n);
@@ -43084,6 +43296,16 @@ function resolveAggregateArgSemantics(arg, resolver) {
43084
43296
  const first = results[0];
43085
43297
  return results.every((result) => JSON.stringify(result) === JSON.stringify(first)) ? first : kinds[0];
43086
43298
  }
43299
+ function aggregateResultSemantics(ref, resolver) {
43300
+ if (ref.func === "COUNT" || ref.func === "SUM" || ref.func === "AVG" || ref.func === "STDDEV_POP" || ref.func === "STDDEV_SAMP" || ref.func === "VAR_POP" || ref.func === "VAR_SAMP" || ref.func === "MEDIAN") {
43301
+ return syntheticSemantics("number");
43302
+ }
43303
+ if (ref.func === "GROUP_CONCAT" || ref.func === "MODE") {
43304
+ return syntheticSemantics("string");
43305
+ }
43306
+ const semantics = ref.arg.type === "WILDCARD" ? "string" : resolveAggregateArgSemantics(ref.arg, resolver) ?? "string";
43307
+ return typeof semantics === "string" ? syntheticSemantics(semantics) : semantics;
43308
+ }
43087
43309
  function applyHaving(rows, having, resolveFieldType, resolveFieldSemantics2) {
43088
43310
  if (having === null) return rows;
43089
43311
  return rows.filter((row) => evalWhere(having, row, resolveFieldType, void 0, resolveFieldSemantics2));
@@ -43243,7 +43465,7 @@ function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, reso
43243
43465
  break;
43244
43466
  }
43245
43467
  case "CASE_COL":
43246
- evaluators.set(alias, (row) => evalCaseWhen(column.expr, row, resolveFieldType, resolveFieldSemantics2));
43468
+ evaluators.set(alias, (row) => containsAggregate2(column.expr) ? row[alias] ?? "" : evalCaseWhen(column.expr, row, resolveFieldType, resolveFieldSemantics2));
43247
43469
  break;
43248
43470
  case "SCALAR_VALUE_COL": {
43249
43471
  const source = scalarValueDefaultKey(column.expr);
@@ -43332,7 +43554,7 @@ function evaluateSelectColumnValue(column, row, columnIndex, context = {}) {
43332
43554
  case "ARITH_COL":
43333
43555
  return String(evalArithExpr(column.expr, row));
43334
43556
  case "CASE_COL":
43335
- return evalCaseWhen(
43557
+ return containsAggregate2(column.expr) ? row[caseMaterializedKey(column.alias, columnIndex)] ?? "" : evalCaseWhen(
43336
43558
  column.expr,
43337
43559
  row,
43338
43560
  context.resolveFieldType,
@@ -43397,13 +43619,14 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns2, r
43397
43619
  return { rows: projected2, columns: cols };
43398
43620
  }
43399
43621
  const defaultFieldKeys = buildDefaultFieldOutputKeys(columns);
43622
+ const defaultCaseKeys = buildDefaultCaseOutputKeys(columns);
43400
43623
  const hasWildcard = columns.some(
43401
43624
  (col) => col.type === "WILDCARD" || col.type === "PARENT_WILDCARD"
43402
43625
  );
43403
- const outputKeys = hasWildcard ? null : computeOutputKeys(columns, defaultFieldKeys);
43626
+ const outputKeys = hasWildcard ? null : computeOutputKeys(columns, defaultFieldKeys, defaultCaseKeys);
43404
43627
  const orderedKeys = outputKeys ?? [];
43405
43628
  if (hasWildcard && rows.length === 0) {
43406
- return { rows: [], columns: computeExplicitOutputKeys(columns, defaultFieldKeys) };
43629
+ return { rows: [], columns: computeExplicitOutputKeys(columns, defaultFieldKeys, defaultCaseKeys) };
43407
43630
  }
43408
43631
  const projected = rows.map((row, rowIdx) => {
43409
43632
  const out = {};
@@ -43470,7 +43693,7 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns2, r
43470
43693
  break;
43471
43694
  }
43472
43695
  case "CASE_COL": {
43473
- const key = outputKeys?.[colIdx] ?? col.alias ?? "case";
43696
+ const key = outputKeys?.[colIdx] ?? col.alias ?? defaultCaseKeys.get(colIdx) ?? "case";
43474
43697
  out[key] = value;
43475
43698
  if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
43476
43699
  break;
@@ -43511,15 +43734,15 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns2, r
43511
43734
  });
43512
43735
  return { rows: projected, columns: orderedKeys };
43513
43736
  }
43514
- function computeOutputKeys(columns, defaultFieldKeys) {
43515
- return columns.map((col, colIdx) => computeOutputKey(col, colIdx, defaultFieldKeys));
43737
+ function computeOutputKeys(columns, defaultFieldKeys, defaultCaseKeys) {
43738
+ return columns.map((col, colIdx) => computeOutputKey(col, colIdx, defaultFieldKeys, defaultCaseKeys));
43516
43739
  }
43517
- function computeExplicitOutputKeys(columns, defaultFieldKeys) {
43740
+ function computeExplicitOutputKeys(columns, defaultFieldKeys, defaultCaseKeys) {
43518
43741
  const keys = [];
43519
43742
  const seen = /* @__PURE__ */ new Set();
43520
43743
  for (const [colIdx, col] of columns.entries()) {
43521
43744
  if (col.type === "WILDCARD" || col.type === "PARENT_WILDCARD") continue;
43522
- const key = computeOutputKey(col, colIdx, defaultFieldKeys);
43745
+ const key = computeOutputKey(col, colIdx, defaultFieldKeys, defaultCaseKeys);
43523
43746
  if (!seen.has(key)) {
43524
43747
  seen.add(key);
43525
43748
  keys.push(key);
@@ -43527,7 +43750,7 @@ function computeExplicitOutputKeys(columns, defaultFieldKeys) {
43527
43750
  }
43528
43751
  return keys;
43529
43752
  }
43530
- function computeOutputKey(col, colIdx, defaultFieldKeys) {
43753
+ function computeOutputKey(col, colIdx, defaultFieldKeys, defaultCaseKeys) {
43531
43754
  switch (col.type) {
43532
43755
  case "VARIABLE_COL":
43533
43756
  throw new Error(`internal error: unresolved SELECT variable @${col.name}`);
@@ -43542,7 +43765,7 @@ function computeOutputKey(col, colIdx, defaultFieldKeys) {
43542
43765
  case "ARITH_COL":
43543
43766
  return col.alias ?? arithColDefaultKey(col.expr);
43544
43767
  case "CASE_COL":
43545
- return col.alias ?? "case";
43768
+ return col.alias ?? defaultCaseKeys.get(colIdx) ?? "case";
43546
43769
  case "STRFUNC_COL":
43547
43770
  return col.alias ?? stringFuncDefaultKey(col.expr);
43548
43771
  case "SCALAR_VALUE_COL":
@@ -43558,6 +43781,24 @@ function computeOutputKey(col, colIdx, defaultFieldKeys) {
43558
43781
  throw new Error("internal: computeOutputKey received a wildcard column");
43559
43782
  }
43560
43783
  }
43784
+ function buildDefaultCaseOutputKeys(columns) {
43785
+ const used = new Set(columns.flatMap(
43786
+ (column) => "alias" in column && column.alias !== null ? [column.alias] : []
43787
+ ));
43788
+ const keys = /* @__PURE__ */ new Map();
43789
+ let suffix = 1;
43790
+ for (const [columnIndex, column] of columns.entries()) {
43791
+ if (column.type !== "CASE_COL" || column.alias !== null) continue;
43792
+ let key;
43793
+ do {
43794
+ key = suffix === 1 ? "case" : `case_${suffix}`;
43795
+ suffix++;
43796
+ } while (used.has(key));
43797
+ used.add(key);
43798
+ keys.set(columnIndex, key);
43799
+ }
43800
+ return keys;
43801
+ }
43561
43802
  function buildDefaultFieldOutputKeys(columns) {
43562
43803
  const qualifierCollisionCount = /* @__PURE__ */ new Map();
43563
43804
  for (const col of columns) {
@@ -43647,6 +43888,7 @@ function scalarValueHasAggregate2(expr) {
43647
43888
  return false;
43648
43889
  }
43649
43890
  function caseResultHasAggregate2(result) {
43891
+ if (result.type === "AGG_REF" || result.type === "AGG_ARITH") return true;
43650
43892
  if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return false;
43651
43893
  return scalarValueHasAggregate2(result);
43652
43894
  }
@@ -43669,6 +43911,7 @@ function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
43669
43911
  }
43670
43912
  function resolveAggInScalarValue(expr, rows, resolveAggSortKind) {
43671
43913
  if (expr.type === "STRING_FUNC") return resolveAggInStringFuncExpr(expr, rows, resolveAggSortKind);
43914
+ if (expr.type === "CASE_WHEN") return resolveAggInCaseExpr(expr, rows, resolveAggSortKind);
43672
43915
  if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
43673
43916
  return {
43674
43917
  ...expr,
@@ -43678,6 +43921,35 @@ function resolveAggInScalarValue(expr, rows, resolveAggSortKind) {
43678
43921
  }
43679
43922
  return expr;
43680
43923
  }
43924
+ function resolveAggInCaseResult(result, rows, resolveAggSortKind) {
43925
+ if (result.type === "AGG_REF") {
43926
+ const value = evalAggregate(
43927
+ result.func,
43928
+ result.distinct,
43929
+ result.arg,
43930
+ result.separator,
43931
+ rows,
43932
+ resolveAggSortKind
43933
+ );
43934
+ return typeof value === "number" ? { type: "NUMBER", value, raw: String(value) } : { type: "STRING", value };
43935
+ }
43936
+ if (result.type === "AGG_ARITH") {
43937
+ const value = evalAggArithExpr(result, rows, resolveAggSortKind);
43938
+ return { type: "NUMBER", value, raw: String(value) };
43939
+ }
43940
+ if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return result;
43941
+ return resolveAggInScalarValue(result, rows, resolveAggSortKind);
43942
+ }
43943
+ function resolveAggInCaseExpr(expr, rows, resolveAggSortKind) {
43944
+ return {
43945
+ ...expr,
43946
+ branches: expr.branches.map((branch) => ({
43947
+ ...branch,
43948
+ result: resolveAggInCaseResult(branch.result, rows, resolveAggSortKind)
43949
+ })),
43950
+ elseResult: expr.elseResult === null ? null : resolveAggInCaseResult(expr.elseResult, rows, resolveAggSortKind)
43951
+ };
43952
+ }
43681
43953
  function resolveAggInStringFuncExpr(expr, rows, resolveAggSortKind) {
43682
43954
  return {
43683
43955
  type: "STRING_FUNC",
@@ -43800,7 +44072,8 @@ function runFullScan(input) {
43800
44072
  }
43801
44073
  );
43802
44074
  }
43803
- rows = applyHaving(rows, stmt.having, havingFieldTypeResolver, havingFieldSemanticsResolver);
44075
+ const resolveHavingSemantics = (field) => field.aggregateRef ? aggregateResultSemantics(field.aggregateRef, aggregateSortKindResolver) : havingFieldSemanticsResolver?.(field);
44076
+ rows = applyHaving(rows, stmt.having, havingFieldTypeResolver, resolveHavingSemantics);
43804
44077
  rows = applyWindow(rows, stmt.columns, optionOrders, sortKinds, effectiveOrderSemantics);
43805
44078
  if (stmt.distinct) {
43806
44079
  rows = applyDistinct(
@@ -47367,7 +47640,7 @@ function scalarValueHasFieldRef(expr) {
47367
47640
  }
47368
47641
  if (expr.type === "CASE_WHEN") {
47369
47642
  const results = [...expr.branches.map((branch) => branch.result), ...expr.elseResult ? [expr.elseResult] : []];
47370
- return results.some((result) => result.type !== "ARRAY" && (result.type === "FIELD_REF" || result.type === "ARITH" ? arithHasFieldRef(result) : scalarValueHasFieldRef(result)));
47643
+ return results.some((result) => result.type !== "ARRAY" && (result.type === "FIELD_REF" || result.type === "ARITH" ? arithHasFieldRef(result) : result.type === "AGG_REF" || result.type === "AGG_ARITH" ? true : scalarValueHasFieldRef(result)));
47371
47644
  }
47372
47645
  return false;
47373
47646
  }
@@ -47919,7 +48192,8 @@ function collectAggregateArgFieldRefs(arg, out) {
47919
48192
  }
47920
48193
  if (arg.type === "CASE_WHEN") {
47921
48194
  for (const result of [...arg.branches.map((branch) => branch.result), ...arg.elseResult ? [arg.elseResult] : []]) {
47922
- if (result.type !== "ARRAY") collectAggregateArgFieldRefs(result, out);
48195
+ if (result.type === "AGG_REF" || result.type === "AGG_ARITH") collectAggregateOperandRefs(result, out);
48196
+ else if (result.type !== "ARRAY") collectAggregateArgFieldRefs(result, out);
47923
48197
  }
47924
48198
  }
47925
48199
  }
@@ -47956,10 +48230,29 @@ function collectScalarAggregateRefs(expr, out) {
47956
48230
  const results = [...expr.branches.map((branch) => branch.result), ...expr.elseResult ? [expr.elseResult] : []];
47957
48231
  for (const result of results) {
47958
48232
  if (result.type === "STRING_FUNC") collectStringFuncAggregateRefs(result, out);
48233
+ else if (result.type === "AGG_REF" || result.type === "AGG_ARITH") collectAggregateOperandRefs(result, out);
47959
48234
  else if (result.type !== "ARRAY" && result.type !== "FIELD_REF" && result.type !== "ARITH") collectScalarAggregateRefs(result, out);
47960
48235
  }
47961
48236
  }
47962
48237
  }
48238
+ function collectCaseAggregateRefs(expr, out) {
48239
+ const visit = (node) => {
48240
+ if (node === null || typeof node !== "object") return;
48241
+ if (Array.isArray(node)) {
48242
+ node.forEach(visit);
48243
+ return;
48244
+ }
48245
+ const value = node;
48246
+ if (value["type"] === "AGG_REF") {
48247
+ const aggregate = value;
48248
+ collectAggregateRef(aggregate.func, aggregate.arg, out);
48249
+ return;
48250
+ }
48251
+ if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
48252
+ Object.values(value).forEach(visit);
48253
+ };
48254
+ visit(expr);
48255
+ }
47963
48256
  function collectSelectAggregateSortRefs(columns) {
47964
48257
  const refs = [];
47965
48258
  for (const column of columns) {
@@ -47971,6 +48264,8 @@ function collectSelectAggregateSortRefs(columns) {
47971
48264
  collectStringFuncAggregateRefs(column.expr, refs);
47972
48265
  } else if (column.type === "SCALAR_VALUE_COL") {
47973
48266
  collectScalarAggregateRefs(column.expr, refs);
48267
+ } else if (column.type === "CASE_COL") {
48268
+ collectCaseAggregateRefs(column.expr, refs);
47974
48269
  }
47975
48270
  }
47976
48271
  return refs;
@@ -48148,6 +48443,13 @@ function stringFunctionColumnMeta(expr) {
48148
48443
  function caseResultColumnMeta(result, resolveField2) {
48149
48444
  if (result.type === "STRING") return syntheticColumnMeta("string");
48150
48445
  if (result.type === "ARRAY") return unsupportedColumnMeta();
48446
+ if (result.type === "AGG_REF") {
48447
+ if (result.func === "MIN" || result.func === "MAX" || result.func === "MODE") {
48448
+ return result.arg.type === "WILDCARD" ? unknownStringColumnMeta() : inferAggregateArgMeta(result.arg, resolveField2);
48449
+ }
48450
+ return result.func === "GROUP_CONCAT" ? syntheticColumnMeta("string") : syntheticColumnMeta("number");
48451
+ }
48452
+ if (result.type === "AGG_ARITH") return syntheticColumnMeta("number");
48151
48453
  if (result.type === "NUMBER" || result.type === "ARITH" || result.type === "SCALAR_ARITH") return syntheticColumnMeta("number");
48152
48454
  if (result.type === "STRING_FUNC") return stringFunctionColumnMeta(result);
48153
48455
  if (result.type === "FIELD_REF") return resolveField2(aggregateFieldRef(result.field)) ?? unknownStringColumnMeta();
@@ -57424,7 +57726,7 @@ Nested JSON/CSV subtable mutation is fail-closed on MCP: use VALIDATE ONLY/EXPLA
57424
57726
  JSON child IDs are rejected and replacement renumbers all rows.
57425
57727
  `);
57426
57728
  }
57427
- var SERVER_VERSION = true ? "3.42.0" : "0.0.0-dev";
57729
+ var SERVER_VERSION = true ? "3.44.0" : "0.0.0-dev";
57428
57730
  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; WHERE server-only/fail-closed; INNER JOIN direct-APP exact pushdown supported; local LOGINUSER is empty on all surfaces). 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.`;
57429
57731
  var KSQL_MCP_INSTRUCTIONS = `kSQL MCP server version ${SERVER_VERSION}.
57430
57732