@rex0220/kintone-sql-tools 3.44.0 → 3.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist-cli/ksql.js CHANGED
@@ -577,6 +577,9 @@ function compareDecimal(left, right) {
577
577
 
578
578
  // src/types/ast.ts
579
579
  var NO_FROM_CTE_NAME = "__NO_FROM__";
580
+ function isRankingWindow(column) {
581
+ return column.windowKind !== "AGGREGATE";
582
+ }
580
583
  function makeNumberLiteral(raw) {
581
584
  return { type: "NUMBER", value: Number(raw), raw };
582
585
  }
@@ -749,7 +752,7 @@ function caseLabel(expr) {
749
752
  }
750
753
  function stringFuncArgLabel(arg) {
751
754
  if (arg.type === "AGG_REF") return aggregateSyntheticName(arg.func, arg.distinct, arg.arg);
752
- if (arg.type === "AGG_ARITH") return aggregateOperandLabel(arg);
755
+ if (arg.type === "AGG_ARITH" || arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") return aggregateOperandLabel(arg);
753
756
  return scalarValueLabel(arg);
754
757
  }
755
758
  function stringFuncLabel(expr) {
@@ -787,6 +790,8 @@ function aggregateSyntheticName(func, distinct, arg) {
787
790
  function aggregateOperandLabel(node) {
788
791
  if (node.type === "NUMBER") return numberLiteralText(node);
789
792
  if (node.type === "AGG_REF") return aggregateSyntheticName(node.func, node.distinct, node.arg);
793
+ if (node.type === "AGG_GROUP_KEY") return node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field;
794
+ if (node.type === "VARIABLE") return `@${node.name}`;
790
795
  return `${aggregateOperandLabel(node.left)}${node.op}${aggregateOperandLabel(node.right)}`;
791
796
  }
792
797
 
@@ -1065,6 +1070,8 @@ var Parser = class {
1065
1070
  this.cteNames = /* @__PURE__ */ new Set();
1066
1071
  /** パース中に出現した一時テーブル参照(#name)のトークン。単文 API での拒否に使う */
1067
1072
  this.tempTableRefs = [];
1073
+ /** GROUP BY を読む前に作る B124 候補 leaf の診断位置。AST 公開型へ位置情報を足さない。 */
1074
+ this.aggregateGroupKeyTokens = /* @__PURE__ */ new WeakMap();
1068
1075
  this.allowSelectArithVariable = false;
1069
1076
  }
1070
1077
  // ----------------------------------------------------------
@@ -1318,6 +1325,11 @@ var Parser = class {
1318
1325
  }
1319
1326
  throw new ParseError(msg, tok);
1320
1327
  }
1328
+ consumeSoftKeyword(word) {
1329
+ if (!this.isSoftKeyword(word)) return false;
1330
+ this.advance();
1331
+ return true;
1332
+ }
1321
1333
  parseTempTableName() {
1322
1334
  const tok = this.peek();
1323
1335
  if (tok.kind === "IDENT" /* IDENT */ && tok.value.startsWith("#")) {
@@ -1871,6 +1883,7 @@ var Parser = class {
1871
1883
  if (grouping && orderMode === "KINTONE_NATIVE") {
1872
1884
  throw new ParseError("B65: KORDER BY cannot be combined with grouping sets in Phase1.", this.peek());
1873
1885
  }
1886
+ this.validateAggregateGroupKeyRefs(columns, having, groupBy, grouping);
1874
1887
  return {
1875
1888
  type: "SELECT",
1876
1889
  distinct,
@@ -1957,6 +1970,18 @@ var Parser = class {
1957
1970
  const parsedAlias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
1958
1971
  return this.withAliasDisplay({ type: "GROUPING_COL", ref, alias: parsedAlias2?.alias ?? null }, parsedAlias2);
1959
1972
  }
1973
+ if (this.tryAggregateFunc() === null && this.hasNestedAggregateWindowInSelectColumn()) {
1974
+ throw new ParseError(
1975
+ "\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306E\u7D50\u679C\u3092\u5F0F\u306B\u542B\u3081\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002CTE \u3067\u4E00\u5EA6\u5B9F\u4F53\u5316\u3057\u3066\u304F\u3060\u3055\u3044",
1976
+ this.peek()
1977
+ );
1978
+ }
1979
+ if (this.isNonAggregateArithmeticStartWithAggregate()) {
1980
+ throw new ParseError(
1981
+ `\u96C6\u8A08\u7B97\u8853\u5F0F\u306F\u96C6\u8A08\u95A2\u6570\u304B\u3089\u59CB\u307E\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08${this.peek().value}\uFF09\u3002`,
1982
+ this.peek()
1983
+ );
1984
+ }
1960
1985
  if (this.tryAggregateFunc() === null && this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
1961
1986
  const expr = this.parseScalarValueExpr({ allowAggregateArgs: true });
1962
1987
  const parsedAlias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
@@ -2001,6 +2026,9 @@ var Parser = class {
2001
2026
  const aggFunc = this.tryAggregateFunc();
2002
2027
  if (aggFunc !== null) {
2003
2028
  const ref = this.parseAggregateRef(aggFunc);
2029
+ if (this.isSoftKeyword("OVER")) {
2030
+ return this.parseAggregateWindowColumn(ref);
2031
+ }
2004
2032
  if (this.isArithOp(this.peek().kind)) {
2005
2033
  const expr = this.continueAggArith(ref);
2006
2034
  const parsedAlias3 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
@@ -2052,6 +2080,28 @@ var Parser = class {
2052
2080
  tryWindowFunc() {
2053
2081
  return PARSER_WINDOW_FUNCTION_TOKEN_MAP[this.peek().kind] ?? null;
2054
2082
  }
2083
+ hasNestedAggregateWindowInSelectColumn() {
2084
+ let depth = 0;
2085
+ for (let index = this.pos; index < this.tokens.length; index++) {
2086
+ const token = this.tokens[index];
2087
+ if (depth === 0 && (token.kind === "," /* COMMA */ || token.kind === "FROM" /* FROM */ || token.kind === ";" /* SEMICOLON */ || token.kind === "EOF" /* EOF */)) return false;
2088
+ if (PARSER_AGGREGATE_FUNCTION_TOKEN_MAP[token.kind] !== void 0 && this.tokens[index + 1]?.kind === "(" /* LPAREN */) {
2089
+ let aggregateDepth = 0;
2090
+ for (let cursor = index + 1; cursor < this.tokens.length; cursor++) {
2091
+ const candidate = this.tokens[cursor];
2092
+ if (candidate.kind === "(" /* LPAREN */) aggregateDepth++;
2093
+ else if (candidate.kind === ")" /* RPAREN */ && --aggregateDepth === 0) {
2094
+ const next = this.tokens[cursor + 1];
2095
+ if (next?.kind === "IDENT" /* IDENT */ && next.value.toUpperCase() === "OVER") return true;
2096
+ break;
2097
+ }
2098
+ }
2099
+ }
2100
+ if (token.kind === "(" /* LPAREN */) depth++;
2101
+ else if (token.kind === ")" /* RPAREN */) depth--;
2102
+ }
2103
+ return false;
2104
+ }
2055
2105
  parseWindowColumn(func) {
2056
2106
  this.advance();
2057
2107
  this.expect("(" /* LPAREN */);
@@ -2078,6 +2128,66 @@ var Parser = class {
2078
2128
  const parsedAlias = this.parseAliasName();
2079
2129
  return this.withAliasDisplay({ type: "WINDOW_COL", func, partitionBy, orderBy, alias: parsedAlias.alias }, parsedAlias);
2080
2130
  }
2131
+ parseAggregateWindowColumn(ref) {
2132
+ const supported = /* @__PURE__ */ new Set(["SUM", "COUNT", "AVG", "MIN", "MAX"]);
2133
+ if (!supported.has(ref.func)) {
2134
+ throw new ParseError(
2135
+ `${ref.func} \u306E\u30A6\u30A3\u30F3\u30C9\u30A6\u96C6\u8A08\u306F\u672A\u5BFE\u5FDC\u3067\u3059\u3002\u5BFE\u5FDC\u306F SUM / COUNT / AVG / MIN / MAX \u3067\u3059`,
2136
+ this.peek()
2137
+ );
2138
+ }
2139
+ if (ref.distinct) {
2140
+ throw new ParseError("\u30A6\u30A3\u30F3\u30C9\u30A6\u96C6\u8A08\u3067\u306F\u5F15\u6570\u306E DISTINCT \u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", this.peek());
2141
+ }
2142
+ this.advance();
2143
+ this.expect("(" /* LPAREN */);
2144
+ const partitionBy = [];
2145
+ if (this.isSoftKeyword("PARTITION")) {
2146
+ this.advance();
2147
+ this.expect("BY" /* BY */, "PARTITION \u306E\u5F8C\u306B\u306F BY \u304C\u5FC5\u8981\u3067\u3059");
2148
+ do {
2149
+ const field = this.parseQualifiedIdent();
2150
+ partitionBy.push({ type: "FIELD", tableAlias: field.tableAlias, field: field.field });
2151
+ } while (this.consume("," /* COMMA */));
2152
+ }
2153
+ const orderBy = this.consume("ORDER" /* ORDER */) ? (this.expect("BY" /* BY */), this.parseOrderBy(false)) : [];
2154
+ let frame = orderBy.length > 0 ? { unit: "RANGE", source: "DEFAULT" } : null;
2155
+ if (this.isSoftKeyword("ROWS") || this.isSoftKeyword("RANGE")) {
2156
+ if (orderBy.length === 0) {
2157
+ throw new ParseError("\u30D5\u30EC\u30FC\u30E0\u53E5\u306B\u306F OVER (ORDER BY ...) \u304C\u5FC5\u8981\u3067\u3059", this.peek());
2158
+ }
2159
+ const unit = this.advance().value.toUpperCase();
2160
+ const valid = this.consume("BETWEEN" /* BETWEEN */) && this.consumeSoftKeyword("UNBOUNDED") && this.consumeSoftKeyword("PRECEDING") && this.consume("AND" /* AND */) && this.consumeSoftKeyword("CURRENT") && this.consumeSoftKeyword("ROW");
2161
+ if (!valid) {
2162
+ throw new ParseError(
2163
+ "\u5BFE\u5FDC\u3059\u308B\u30D5\u30EC\u30FC\u30E0\u306F BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW \u3060\u3051\u3067\u3059",
2164
+ this.peek()
2165
+ );
2166
+ }
2167
+ frame = { unit, source: "EXPLICIT" };
2168
+ }
2169
+ this.expect(")" /* RPAREN */);
2170
+ if (this.isArithOp(this.peek().kind)) {
2171
+ throw new ParseError(
2172
+ "\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306E\u7D50\u679C\u3092\u5F0F\u306B\u542B\u3081\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002CTE \u3067\u4E00\u5EA6\u5B9F\u4F53\u5316\u3057\u3066\u304F\u3060\u3055\u3044",
2173
+ this.peek()
2174
+ );
2175
+ }
2176
+ if (!this.consume("AS" /* AS */)) {
2177
+ throw new ParseError("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306B\u306F AS alias \u304C\u5FC5\u8981\u3067\u3059", this.peek());
2178
+ }
2179
+ const parsedAlias = this.parseAliasName();
2180
+ return this.withAliasDisplay({
2181
+ type: "WINDOW_COL",
2182
+ windowKind: "AGGREGATE",
2183
+ aggFunc: ref.func,
2184
+ arg: ref.arg,
2185
+ frame,
2186
+ partitionBy,
2187
+ orderBy,
2188
+ alias: parsedAlias.alias
2189
+ }, parsedAlias);
2190
+ }
2081
2191
  selectColumnHasAggregate(column) {
2082
2192
  if (column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL") return true;
2083
2193
  if (column.type === "STRFUNC_COL") return column.expr.args.some((arg) => this.stringFuncArgHasAggregate(arg));
@@ -2095,6 +2205,7 @@ var Parser = class {
2095
2205
  }
2096
2206
  stringFuncArgHasAggregate(arg) {
2097
2207
  if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
2208
+ if (arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") return false;
2098
2209
  return this.scalarValueHasAggregate(arg);
2099
2210
  }
2100
2211
  scalarValueHasAggregate(expr) {
@@ -2137,7 +2248,7 @@ var Parser = class {
2137
2248
  parseAggArithMulDiv() {
2138
2249
  return this.continueAggArithMulDiv(this.parseAggPrimary());
2139
2250
  }
2140
- /** 集計算術式の一次式: 集計関数 / 数値リテラル / 括弧 */
2251
+ /** 集計算術式の一次式: 集計関数 / 数値 / 変数 / GROUP BY キー候補 / 括弧 */
2141
2252
  parseAggPrimary() {
2142
2253
  if (this.consume("(" /* LPAREN */)) {
2143
2254
  const inner = this.continueAggArith(this.parseAggPrimary());
@@ -2154,12 +2265,99 @@ var Parser = class {
2154
2265
  const tok = this.advance();
2155
2266
  return makeNumberLiteral(tok.value);
2156
2267
  }
2268
+ if (this.peek().kind === "VARIABLE" /* VARIABLE */) {
2269
+ const tok = this.advance();
2270
+ return { type: "VARIABLE", name: tok.value.slice(1).toLowerCase() };
2271
+ }
2157
2272
  const aggFunc = this.tryAggregateFunc();
2158
2273
  if (aggFunc !== null) {
2159
- return this.parseAggregateRef(aggFunc);
2274
+ const ref = this.parseAggregateRef(aggFunc);
2275
+ this.rejectAggregateWindowOutsideSelect();
2276
+ return ref;
2277
+ }
2278
+ if (this.peek().kind === "IDENT" /* IDENT */ || this.peek().kind === "BIDENT" /* BIDENT */) {
2279
+ const tok = this.peek();
2280
+ const parsed = this.parseQualifiedIdent();
2281
+ const ref = {
2282
+ type: "AGG_GROUP_KEY",
2283
+ field: parsed.field,
2284
+ ...parsed.tableAlias ? { tableAlias: parsed.tableAlias } : {}
2285
+ };
2286
+ this.aggregateGroupKeyTokens.set(ref, tok);
2287
+ return ref;
2160
2288
  }
2161
2289
  throw new ParseError("\u96C6\u8A08\u7B97\u8853\u5F0F\u306B\u306F\u96C6\u8A08\u95A2\u6570\u307E\u305F\u306F\u6570\u5024\u304C\u5FC5\u8981\u3067\u3059", this.peek());
2162
2290
  }
2291
+ /** B124 Phase 1 はトップレベルの非集計オペランド開始形を明示拒否する。 */
2292
+ isNonAggregateArithmeticStartWithAggregate() {
2293
+ const first = this.peek();
2294
+ if (this.tryAggregateFunc() !== null || first.kind === "CASE" /* CASE */ || first.kind === "IF" /* IF */) return false;
2295
+ if (this.isGroupingFunctionStart()) return false;
2296
+ if (this.tryStringFuncName() !== null) return false;
2297
+ if (!["IDENT" /* IDENT */, "BIDENT" /* BIDENT */, "VARIABLE" /* VARIABLE */, "(" /* LPAREN */].includes(first.kind)) return false;
2298
+ let depth = 0;
2299
+ let sawArithmetic = false;
2300
+ for (let index = this.pos; index < this.tokens.length; index++) {
2301
+ const token = this.tokens[index];
2302
+ if (depth === 0 && index > this.pos && (token.kind === "," /* COMMA */ || token.kind === "AS" /* AS */ || token.kind === "FROM" /* FROM */ || token.kind === ";" /* SEMICOLON */ || token.kind === "EOF" /* EOF */ || token.kind === "=" /* EQ */ || token.kind === "!=" /* NEQ */ || token.kind === "<>" /* LT_GT */ || token.kind === ">" /* GT */ || token.kind === "<" /* LT */ || token.kind === ">=" /* GTE */ || token.kind === "<=" /* LTE */ || token.kind === "AND" /* AND */ || token.kind === "OR" /* OR */)) break;
2303
+ if (this.isArithOp(token.kind)) sawArithmetic = true;
2304
+ if (PARSER_AGGREGATE_FUNCTION_TOKEN_MAP[token.kind] !== void 0 && this.tokens[index + 1]?.kind === "(" /* LPAREN */) return sawArithmetic;
2305
+ if (token.kind === "(" /* LPAREN */) depth++;
2306
+ else if (token.kind === ")" /* RPAREN */) {
2307
+ depth--;
2308
+ if (depth < 0) break;
2309
+ }
2310
+ }
2311
+ return false;
2312
+ }
2313
+ /** SELECT ローカルの B124 leaf だけを ordinary GROUP BY の表記と照合する。 */
2314
+ validateAggregateGroupKeyRefs(columns, having, groupBy, grouping) {
2315
+ const refs = [];
2316
+ const visit = (node) => {
2317
+ if (Array.isArray(node)) {
2318
+ node.forEach(visit);
2319
+ return;
2320
+ }
2321
+ if (node === null || typeof node !== "object") return;
2322
+ const value = node;
2323
+ if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
2324
+ if (value["type"] === "AGG_GROUP_KEY") {
2325
+ refs.push(node);
2326
+ return;
2327
+ }
2328
+ Object.values(value).forEach(visit);
2329
+ };
2330
+ visit(columns);
2331
+ visit(having);
2332
+ if (refs.length === 0) return;
2333
+ const first = refs[0];
2334
+ const firstToken = this.aggregateGroupKeyTokens.get(first) ?? this.peek();
2335
+ if (grouping !== void 0) {
2336
+ throw new ParseError(
2337
+ "ROLLUP / CUBE / GROUPING SETS \u3067\u306F\u96C6\u8A08\u7B97\u8853\u5F0F\u306B\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u66F8\u3051\u307E\u305B\u3093\uFF08\u5C0F\u8A08\u30FB\u7DCF\u8A08\u884C\u3067\u5024\u304C\u5B9A\u307E\u3089\u306A\u3044\u305F\u3081\u3067\u3059\uFF09\u3002",
2338
+ firstToken
2339
+ );
2340
+ }
2341
+ if (groupBy.length === 0) {
2342
+ throw new ParseError(
2343
+ `\u96C6\u8A08\u7B97\u8853\u5F0F\u306B\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u66F8\u304F\u306B\u306F GROUP BY \u304C\u5FC5\u8981\u3067\u3059\uFF08${this.aggregateGroupKeyDisplay(first)}\uFF09\u3002`,
2344
+ firstToken
2345
+ );
2346
+ }
2347
+ const ordinaryNames = new Set(groupBy.filter((key) => key.type === "FIELD_NAME").map((key) => key.name));
2348
+ for (const ref of refs) {
2349
+ const display = this.aggregateGroupKeyDisplay(ref);
2350
+ if (!ordinaryNames.has(display)) {
2351
+ throw new ParseError(
2352
+ `\u96C6\u8A08\u7B97\u8853\u5F0F\u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u53C2\u7167\u306F GROUP BY \u306B\u66F8\u3044\u305F\u8868\u8A18\u3068\u4E00\u81F4\u3059\u308B\u5217\u3060\u3051\u3067\u3059\uFF08${display}\uFF09\u3002\u30B0\u30EB\u30FC\u30D7\u5185\u3067\u5024\u304C\u5B9A\u307E\u3089\u306A\u3044\u305F\u3081\u3067\u3059\u3002`,
2353
+ this.aggregateGroupKeyTokens.get(ref) ?? firstToken
2354
+ );
2355
+ }
2356
+ }
2357
+ }
2358
+ aggregateGroupKeyDisplay(ref) {
2359
+ return ref.tableAlias ? `${ref.tableAlias}.${ref.field}` : ref.field;
2360
+ }
2163
2361
  // ──────────────────────────────────────────────────
2164
2362
  // 汎用スカラー値式パーサー(B38)
2165
2363
  // ──────────────────────────────────────────────────
@@ -2405,7 +2603,9 @@ var Parser = class {
2405
2603
  }
2406
2604
  const aggregateFunc = this.tryAggregateFunc();
2407
2605
  if (aggregateFunc !== null && allowAggregateResult) {
2408
- return this.continueAggArith(this.parseAggregateRef(aggregateFunc));
2606
+ const ref = this.parseAggregateRef(aggregateFunc);
2607
+ this.rejectAggregateWindowOutsideSelect();
2608
+ return this.continueAggArith(ref);
2409
2609
  }
2410
2610
  if (this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
2411
2611
  return this.parseScalarValueExpr({ allowAggregateArgs: true });
@@ -2905,6 +3105,12 @@ var Parser = class {
2905
3105
  // - 集計関数(HAVING のみ): COUNT(*) / SUM(f) ...
2906
3106
  // - 通常フィールド参照: [alias.]field
2907
3107
  parseFieldValue() {
3108
+ if (this.groupingFieldContext === "HAVING" && this.isNonAggregateArithmeticStartWithAggregate()) {
3109
+ throw new ParseError(
3110
+ `\u96C6\u8A08\u7B97\u8853\u5F0F\u306F\u96C6\u8A08\u95A2\u6570\u304B\u3089\u59CB\u307E\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08${this.peek().value}\uFF09\u3002`,
3111
+ this.peek()
3112
+ );
3113
+ }
2908
3114
  if (this.isUnsupportedGroupingIdStart()) {
2909
3115
  throw new ParseError("B65: GROUPING_ID is not supported in Phase1.", this.peek());
2910
3116
  }
@@ -2930,6 +3136,7 @@ var Parser = class {
2930
3136
  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());
2931
3137
  }
2932
3138
  const ref = this.parseAggregateRef(aggFunc);
3139
+ this.rejectAggregateWindowOutsideSelect();
2933
3140
  if (this.isArithOp(this.peek().kind)) {
2934
3141
  return {
2935
3142
  type: "AGG_FIELD",
@@ -3388,6 +3595,16 @@ var Parser = class {
3388
3595
  * フィールド名/alias: 名前 / total
3389
3596
  */
3390
3597
  parseOrderByKey(allowGrouping = true) {
3598
+ const aggregateStart = this.tryAggregateFunc();
3599
+ if (aggregateStart !== null) {
3600
+ const start = this.pos;
3601
+ const ref = this.parseAggregateRef(aggregateStart);
3602
+ if (this.isSoftKeyword("OVER")) {
3603
+ throw new ParseError("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306F SELECT \u5217\u306B\u306E\u307F\u8A18\u8FF0\u3067\u304D\u307E\u3059", this.peek());
3604
+ }
3605
+ this.pos = start;
3606
+ void ref;
3607
+ }
3391
3608
  if (this.isUnsupportedGroupingIdStart()) {
3392
3609
  throw new ParseError("B65: GROUPING_ID is not supported in Phase1.", this.peek());
3393
3610
  }
@@ -3911,6 +4128,11 @@ var Parser = class {
3911
4128
  isSoftKeyword(value) {
3912
4129
  return this.peek().kind === "IDENT" /* IDENT */ && this.peek().value.toUpperCase() === value;
3913
4130
  }
4131
+ rejectAggregateWindowOutsideSelect() {
4132
+ if (this.isSoftKeyword("OVER")) {
4133
+ throw new ParseError("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306F SELECT \u5217\u306B\u306E\u307F\u8A18\u8FF0\u3067\u304D\u307E\u3059", this.peek());
4134
+ }
4135
+ }
3914
4136
  validateUpdateFromAssignments(assignments, sourceAlias, tok) {
3915
4137
  for (const assignment of assignments) {
3916
4138
  if (assignment.value.type === "STRING_FUNC") {
@@ -4426,7 +4648,11 @@ function selectCompleteInputReasons(stmt) {
4426
4648
  if (stmt.distinct) reasons.add("DISTINCT");
4427
4649
  if (stmt.orderBy.length > 0) reasons.add("LOCAL_ORDER");
4428
4650
  for (const column of stmt.columns) {
4429
- if (column.type === "WINDOW_COL" && column.orderBy.length > 0) reasons.add("WINDOW_ORDER");
4651
+ if (column.type === "WINDOW_COL" && column.windowKind === "AGGREGATE") {
4652
+ reasons.add("AGGREGATE_WINDOW");
4653
+ } else if (column.type === "WINDOW_COL" && column.orderBy.length > 0) {
4654
+ reasons.add("WINDOW_ORDER");
4655
+ }
4430
4656
  if (column.type === "SCALAR_SUBQUERY_COL") addReasons(reasons, selectCompleteInputReasons(column.query));
4431
4657
  if (column.type === "CASE_COL") {
4432
4658
  for (const branch of column.expr.branches) addReasons(reasons, whereCompleteInputReasons(branch.condition));
@@ -5688,7 +5914,7 @@ function collectStringFuncFields(expr, out) {
5688
5914
  }
5689
5915
  }
5690
5916
  function collectStringFuncArgFields(arg, out) {
5691
- if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
5917
+ if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH" || arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") {
5692
5918
  collectAggOperandFields(arg, out);
5693
5919
  return;
5694
5920
  }
@@ -5734,6 +5960,9 @@ function collectAggOperandFields(node, out) {
5734
5960
  collectAggOperandFields(node.left, out);
5735
5961
  collectAggOperandFields(node.right, out);
5736
5962
  }
5963
+ if (node.type === "AGG_GROUP_KEY") {
5964
+ out.push(normalizeSimpleFieldRef(node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field));
5965
+ }
5737
5966
  }
5738
5967
  function collectAggregateArgFields(node, out) {
5739
5968
  if (node.type === "FIELD_REF" || node.type === "ARITH") collectArithNode(node, out);
@@ -5742,6 +5971,7 @@ function collectAggregateArgFields(node, out) {
5742
5971
  function hasAggregateInStringFuncExpr(expr) {
5743
5972
  return expr.args.some((arg) => {
5744
5973
  if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
5974
+ if (arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") return false;
5745
5975
  return scalarValueHasAggregate(arg);
5746
5976
  });
5747
5977
  }
@@ -5929,9 +6159,12 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
5929
6159
  walkAgg(node.left, phase);
5930
6160
  walkAgg(node.right, phase);
5931
6161
  }
6162
+ if (node.type === "AGG_GROUP_KEY") {
6163
+ addFieldRef(node.field, node.tableAlias ?? null, phase);
6164
+ }
5932
6165
  };
5933
6166
  const walkStringArg = (arg, phase = "select") => {
5934
- if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
6167
+ if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH" || arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") {
5935
6168
  walkAgg(arg, phase);
5936
6169
  return;
5937
6170
  }
@@ -6104,6 +6337,9 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
6104
6337
  case "SCALAR_SUBQUERY_COL":
6105
6338
  break;
6106
6339
  case "WINDOW_COL":
6340
+ if (col.windowKind === "AGGREGATE" && col.arg.type !== "WILDCARD") {
6341
+ walkAggregateArg(col.arg, "select");
6342
+ }
6107
6343
  for (const ref of col.partitionBy) addFieldRef(ref.field, ref.tableAlias, "select");
6108
6344
  for (const item of col.orderBy) walkOrderByKey(item.key, "select");
6109
6345
  break;
@@ -8029,7 +8265,7 @@ function formatWithComma(num, digits) {
8029
8265
  return decStr ? `${intFmt}.${decStr}` : intFmt;
8030
8266
  }
8031
8267
  function evalStringFuncArg(arg, row, resolveFieldType, resolveFieldSemantics2) {
8032
- if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
8268
+ if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH" || arg.type === "AGG_GROUP_KEY") {
8033
8269
  return String(evalMaterializedAggregateOperand(arg, row));
8034
8270
  }
8035
8271
  if (arg.type === "NUMBER") return numberLiteralText(arg);
@@ -8040,6 +8276,13 @@ function evalMaterializedAggregateOperand(node, row) {
8040
8276
  if (node.type === "AGG_REF") {
8041
8277
  return row[aggregateSyntheticName(node.func, node.distinct, node.arg)] ?? "";
8042
8278
  }
8279
+ if (node.type === "AGG_GROUP_KEY") {
8280
+ const field = node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field;
8281
+ return Number(resolveFieldRef(row, field));
8282
+ }
8283
+ if (node.type === "VARIABLE") {
8284
+ throw new Error(`InternalError: unresolved aggregate arithmetic variable @${node.name}.`);
8285
+ }
8043
8286
  const left = Number(evalMaterializedAggregateOperand(node.left, row));
8044
8287
  const right = Number(evalMaterializedAggregateOperand(node.right, row));
8045
8288
  switch (node.op) {
@@ -8541,7 +8784,7 @@ function collectStringFuncFields2(expr, out) {
8541
8784
  for (const arg of expr.args) collectStringFuncArgFields2(arg, out);
8542
8785
  }
8543
8786
  function collectStringFuncArgFields2(arg, out) {
8544
- if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
8787
+ if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH" || arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") {
8545
8788
  collectAggOperandFields2(arg, out);
8546
8789
  return;
8547
8790
  }
@@ -8572,6 +8815,7 @@ function collectAggOperandFields2(node, out) {
8572
8815
  collectAggOperandFields2(node.left, out);
8573
8816
  collectAggOperandFields2(node.right, out);
8574
8817
  }
8818
+ if (node.type === "AGG_GROUP_KEY") out.add(node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field);
8575
8819
  }
8576
8820
  function collectAggregateArgFields2(node, out) {
8577
8821
  if (node.type === "FIELD_REF" || node.type === "ARITH") collectArithNode2(node, out);
@@ -11076,7 +11320,7 @@ function valueNeedsFieldMetadata(value) {
11076
11320
  return Object.values(item).some(valueNeedsFieldMetadata);
11077
11321
  }
11078
11322
  function selectNeedsOwnMetadata(statement) {
11079
- return whereNeedsFieldMetadata(statement.where) || normalizeGroupingSpec(statement).type === "GROUPING_SETS" || statement.orderBy.length > 0 || statement.columns.some(
11323
+ return whereNeedsFieldMetadata(statement.where) || statement.groupBy.length > 0 || normalizeGroupingSpec(statement).type === "GROUPING_SETS" || statement.orderBy.length > 0 || statement.columns.some(
11080
11324
  (column) => column.type === "WINDOW_COL" && column.orderBy.length > 0
11081
11325
  );
11082
11326
  }
@@ -13199,26 +13443,7 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
13199
13443
  if (arg.type === "WILDCARD") {
13200
13444
  return func === "COUNT" ? rows.length : 0;
13201
13445
  }
13202
- const strValues = [];
13203
- for (const row of rows) {
13204
- let strVal;
13205
- if (arg.type === "FIELD_REF") {
13206
- const raw = row[arg.field];
13207
- if (raw === void 0 || raw === "" && func !== "MIN" && func !== "MAX") continue;
13208
- strVal = raw;
13209
- } else if (arg.type === "ARITH" || arg.type === "NUMBER") {
13210
- const n = evalArithExpr(arg, row);
13211
- if (isNaN(n)) continue;
13212
- strVal = String(n);
13213
- } else {
13214
- const value = evalScalarValueExprNullable(arg, row);
13215
- if (value === null) continue;
13216
- if (value === "" && func !== "MIN" && func !== "MAX") continue;
13217
- if (typeof value === "number" && Number.isNaN(value)) continue;
13218
- strVal = String(value);
13219
- }
13220
- strValues.push(strVal);
13221
- }
13446
+ const strValues = aggregateRowValues(func, arg, rows).filter((value) => value !== null);
13222
13447
  const statistical = func === "STDDEV_POP" || func === "STDDEV_SAMP" || func === "VAR_POP" || func === "VAR_SAMP" || func === "MEDIAN";
13223
13448
  const numericValues = statistical ? strValues.map((value) => {
13224
13449
  const numeric = Number(value);
@@ -13296,6 +13521,27 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
13296
13521
  }
13297
13522
  }
13298
13523
  }
13524
+ function aggregateRowValues(func, arg, rows) {
13525
+ return rows.map((row) => {
13526
+ let strVal;
13527
+ if (arg.type === "FIELD_REF") {
13528
+ const raw = row[arg.field];
13529
+ if (raw === void 0 || raw === "" && func !== "MIN" && func !== "MAX") return null;
13530
+ strVal = raw;
13531
+ } else if (arg.type === "ARITH" || arg.type === "NUMBER") {
13532
+ const n = evalArithExpr(arg, row);
13533
+ if (isNaN(n)) return null;
13534
+ strVal = String(n);
13535
+ } else {
13536
+ const value = evalScalarValueExprNullable(arg, row);
13537
+ if (value === null) return null;
13538
+ if (value === "" && func !== "MIN" && func !== "MAX") return null;
13539
+ if (typeof value === "number" && Number.isNaN(value)) return null;
13540
+ strVal = String(value);
13541
+ }
13542
+ return strVal;
13543
+ });
13544
+ }
13299
13545
  function toAggregateFieldRef(field) {
13300
13546
  const dot = field.indexOf(".");
13301
13547
  return dot > 0 ? { type: "FIELD", tableAlias: field.slice(0, dot), field: field.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field };
@@ -13303,6 +13549,13 @@ function toAggregateFieldRef(field) {
13303
13549
  function evalAggArithExpr(node, rows, resolveAggSortKind) {
13304
13550
  if (node.type === "NUMBER") return node.value;
13305
13551
  if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, node.separator, rows, resolveAggSortKind));
13552
+ if (node.type === "AGG_GROUP_KEY") {
13553
+ const field = node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field;
13554
+ return Number(resolveFieldRef(rows[0] ?? {}, field));
13555
+ }
13556
+ if (node.type === "VARIABLE") {
13557
+ throw new Error(`InternalError: unresolved aggregate arithmetic variable @${node.name}.`);
13558
+ }
13306
13559
  const l = evalAggArithExpr(node.left, rows, resolveAggSortKind);
13307
13560
  const r = evalAggArithExpr(node.right, rows, resolveAggSortKind);
13308
13561
  switch (node.op) {
@@ -13526,7 +13779,7 @@ function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, reso
13526
13779
  }
13527
13780
  return (name, row) => evaluators.get(name)?.(row);
13528
13781
  }
13529
- function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2) {
13782
+ function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2, resolveAggSortKind) {
13530
13783
  const windows = columns.filter((column) => column.type === "WINDOW_COL");
13531
13784
  if (rows.length === 0 || windows.length === 0) return rows;
13532
13785
  for (const window of windows) {
@@ -13540,6 +13793,10 @@ function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2) {
13540
13793
  for (const partition of partitions.values()) {
13541
13794
  const sortedResult = sortDecoratedRows(partition, window.orderBy, optionOrders, sortKinds, fieldSemantics2);
13542
13795
  const sorted = sortedResult.rows;
13796
+ if (!isRankingWindow(window)) {
13797
+ applyAggregateWindow(window, sortedResult, resolveAggSortKind);
13798
+ continue;
13799
+ }
13543
13800
  let rank = 1;
13544
13801
  let denseRank = 1;
13545
13802
  for (let index = 0; index < sorted.length; index++) {
@@ -13554,6 +13811,53 @@ function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2) {
13554
13811
  }
13555
13812
  return rows;
13556
13813
  }
13814
+ function applyAggregateWindow(window, sortedResult, resolveAggSortKind) {
13815
+ const sorted = sortedResult.rows;
13816
+ const values = window.arg.type === "WILDCARD" ? null : aggregateRowValues(window.aggFunc, window.arg, sorted.map((item) => item.row));
13817
+ const comparison = window.arg.type === "WILDCARD" ? void 0 : resolveAggregateArgSemantics(window.arg, resolveAggSortKind);
13818
+ const semantics = typeof comparison === "string" ? syntheticSemantics(comparison) : comparison ?? syntheticSemantics("string");
13819
+ const output = [];
13820
+ let count = 0;
13821
+ let sum = 0;
13822
+ let best;
13823
+ for (let index = 0; index < sorted.length; index++) {
13824
+ const value = values?.[index] ?? null;
13825
+ if (window.arg.type === "WILDCARD") {
13826
+ count++;
13827
+ } else if (value !== null) {
13828
+ if (window.aggFunc === "COUNT") {
13829
+ count++;
13830
+ } else if (window.aggFunc === "SUM" || window.aggFunc === "AVG") {
13831
+ sum += Number(value);
13832
+ count++;
13833
+ } else if (best === void 0) {
13834
+ best = value;
13835
+ } else {
13836
+ const cmp = compareCanonicalValues(value, best, semantics);
13837
+ if (window.aggFunc === "MAX" && cmp > 0 || window.aggFunc === "MIN" && cmp < 0) {
13838
+ best = value;
13839
+ }
13840
+ }
13841
+ }
13842
+ const result = window.aggFunc === "COUNT" ? count : window.aggFunc === "SUM" ? sum : window.aggFunc === "AVG" ? count === 0 ? 0 : sum / count : best ?? 0;
13843
+ output.push(String(result));
13844
+ }
13845
+ if (window.frame === null) {
13846
+ const finalValue = output[output.length - 1];
13847
+ for (const item of sorted) item.row[window.alias] = finalValue;
13848
+ return;
13849
+ }
13850
+ if (window.frame.unit === "RANGE") {
13851
+ for (let start = 0; start < sorted.length; ) {
13852
+ let end = start;
13853
+ while (end + 1 < sorted.length && sortedResult.compare(sorted[end], sorted[end + 1]) === 0) end++;
13854
+ for (let index = start; index <= end; index++) sorted[index].row[window.alias] = output[end];
13855
+ start = end + 1;
13856
+ }
13857
+ return;
13858
+ }
13859
+ for (let index = 0; index < sorted.length; index++) sorted[index].row[window.alias] = output[index];
13860
+ }
13557
13861
  function resolveWindowField(row, ref) {
13558
13862
  const name = ref.tableAlias ? `${ref.tableAlias}.${ref.field}` : ref.field;
13559
13863
  return resolveFieldRef(row, name);
@@ -13890,7 +14194,8 @@ function arithColDefaultKey(expr) {
13890
14194
  }
13891
14195
  function stringFuncDefaultKey(expr) {
13892
14196
  const argStrs = expr.args.map((a) => {
13893
- if (a.type === "AGG_REF" || a.type === "AGG_ARITH") return aggArithDefaultKey(a);
14197
+ if (a.type === "AGG_REF" || a.type === "AGG_ARITH" || a.type === "AGG_GROUP_KEY") return aggArithDefaultKey(a);
14198
+ if (a.type === "VARIABLE") return `@${a.name}`;
13894
14199
  return scalarValueDefaultKey(a);
13895
14200
  });
13896
14201
  return `${expr.func}(${argStrs.join(",")})`;
@@ -13917,6 +14222,7 @@ function scalarValueDefaultKey(expr) {
13917
14222
  }
13918
14223
  function hasAggregateInStringFuncArg(arg) {
13919
14224
  if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
14225
+ if (arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") return false;
13920
14226
  return scalarValueHasAggregate2(arg);
13921
14227
  }
13922
14228
  function scalarValueHasAggregate2(expr) {
@@ -13946,6 +14252,13 @@ function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
13946
14252
  const value = evalAggArithExpr(arg, rows, resolveAggSortKind);
13947
14253
  return { type: "NUMBER", value, raw: String(value) };
13948
14254
  }
14255
+ if (arg.type === "AGG_GROUP_KEY") {
14256
+ const field = arg.tableAlias ? `${arg.tableAlias}.${arg.field}` : arg.field;
14257
+ return { type: "NUMBER", value: Number(resolveFieldRef(rows[0] ?? {}, field)), raw: resolveFieldRef(rows[0] ?? {}, field) };
14258
+ }
14259
+ if (arg.type === "VARIABLE") {
14260
+ throw new Error(`InternalError: unresolved aggregate arithmetic variable @${arg.name}.`);
14261
+ }
13949
14262
  if (arg.type === "STRING_FUNC") {
13950
14263
  return resolveAggInStringFuncExpr(arg, rows, resolveAggSortKind);
13951
14264
  }
@@ -14020,12 +14333,19 @@ function mergeKnownColumns(left, right, rows) {
14020
14333
  ...Object.keys(rows[0] ?? {})
14021
14334
  ])];
14022
14335
  }
14023
- function deriveOutputOrderSemantics(columns) {
14336
+ function deriveOutputOrderSemantics(columns, resolveAggSortKind) {
14024
14337
  const result = /* @__PURE__ */ new Map();
14025
14338
  for (const column of columns) {
14026
14339
  if (!("alias" in column) || !column.alias) continue;
14027
- if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL" || column.type === "WINDOW_COL") {
14340
+ if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL") {
14028
14341
  result.set(column.alias, syntheticSemantics("number"));
14342
+ } else if (column.type === "WINDOW_COL") {
14343
+ if (isRankingWindow(column) || column.aggFunc === "COUNT" || column.aggFunc === "SUM" || column.aggFunc === "AVG") {
14344
+ result.set(column.alias, syntheticSemantics("number"));
14345
+ } else if (column.arg.type !== "WILDCARD") {
14346
+ const semantics = resolveAggregateArgSemantics(column.arg, resolveAggSortKind) ?? "string";
14347
+ result.set(column.alias, typeof semantics === "string" ? syntheticSemantics(semantics) : semantics);
14348
+ }
14029
14349
  } else if (column.type === "AGGREGATE") {
14030
14350
  if (column.func === "COUNT" || column.func === "SUM" || column.func === "AVG" || column.func === "STDDEV_POP" || column.func === "STDDEV_SAMP" || column.func === "VAR_POP" || column.func === "VAR_SAMP" || column.func === "MEDIAN") {
14031
14351
  result.set(column.alias, syntheticSemantics("number"));
@@ -14060,7 +14380,7 @@ function runFullScan(input) {
14060
14380
  resolvedGroupingSpec,
14061
14381
  plainGroupByPlan
14062
14382
  } = input;
14063
- const effectiveOrderSemantics = deriveOutputOrderSemantics(stmt.columns);
14383
+ const effectiveOrderSemantics = deriveOutputOrderSemantics(stmt.columns, aggregateSortKindResolver);
14064
14384
  for (const [key, value] of orderSemantics ?? []) effectiveOrderSemantics.set(key, value);
14065
14385
  let rows = [];
14066
14386
  const mainAlias = stmt.from.alias;
@@ -14116,7 +14436,14 @@ function runFullScan(input) {
14116
14436
  }
14117
14437
  const resolveHavingSemantics = (field) => field.aggregateRef ? aggregateResultSemantics(field.aggregateRef, aggregateSortKindResolver) : havingFieldSemanticsResolver?.(field);
14118
14438
  rows = applyHaving(rows, stmt.having, havingFieldTypeResolver, resolveHavingSemantics);
14119
- rows = applyWindow(rows, stmt.columns, optionOrders, sortKinds, effectiveOrderSemantics);
14439
+ rows = applyWindow(
14440
+ rows,
14441
+ stmt.columns,
14442
+ optionOrders,
14443
+ sortKinds,
14444
+ effectiveOrderSemantics,
14445
+ aggregateSortKindResolver
14446
+ );
14120
14447
  if (stmt.distinct) {
14121
14448
  rows = applyDistinct(
14122
14449
  rows,
@@ -16601,8 +16928,8 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
16601
16928
  tempTables
16602
16929
  );
16603
16930
  const first = resolvedStmt2.expr.query.columns[0];
16604
- let numeric = first?.type === "ARITH_COL" || first?.type === "ARITH_AGG_COL" || first?.type === "WINDOW_COL" || first?.type === "AGGREGATE" && (first.func === "COUNT" || first.func === "SUM" || first.func === "AVG" || first.func === "STDDEV_POP" || first.func === "STDDEV_SAMP" || first.func === "VAR_POP" || first.func === "VAR_SAMP" || first.func === "MEDIAN");
16605
- if (first?.type === "AGGREGATE" && first.func === "MODE") {
16931
+ let numeric = first?.type === "ARITH_COL" || first?.type === "ARITH_AGG_COL" || first?.type === "WINDOW_COL" && (first.windowKind !== "AGGREGATE" || first.aggFunc === "COUNT" || first.aggFunc === "SUM" || first.aggFunc === "AVG") || first?.type === "AGGREGATE" && (first.func === "COUNT" || first.func === "SUM" || first.func === "AVG" || first.func === "STDDEV_POP" || first.func === "STDDEV_SAMP" || first.func === "VAR_POP" || first.func === "VAR_SAMP" || first.func === "MEDIAN");
16932
+ if (first?.type === "AGGREGATE" && first.func === "MODE" || first?.type === "WINDOW_COL" && first.windowKind === "AGGREGATE" && (first.aggFunc === "MIN" || first.aggFunc === "MAX")) {
16606
16933
  const meta = (await inferSelectColumnMeta(
16607
16934
  resolvedStmt2.expr.query,
16608
16935
  ["__scalar__"],
@@ -16924,7 +17251,15 @@ function resolveBatchVariableReferencesInternal(node, variables, numericArithmet
16924
17251
  `ArgumentError: variable @${obj["name"]} is not numeric and cannot be used in arithmetic.`
16925
17252
  );
16926
17253
  }
16927
- return numericArithmeticOperand && value.type === "string" && value.placeholder === true ? { type: "NUMBER", value: 0, raw: value.value } : value.type === "number" ? { type: "NUMBER", value: value.value, raw: value.raw ?? String(value.value) } : { type: "STRING", value: value.value };
17254
+ return numericArithmeticOperand && value.type === "string" && value.placeholder === true ? {
17255
+ type: "NUMBER",
17256
+ value: 0,
17257
+ raw: numericArithmeticOperand === "AGG_ARITH" ? `@${obj["name"]}` : value.value
17258
+ } : value.type === "number" ? {
17259
+ type: "NUMBER",
17260
+ value: value.value,
17261
+ raw: numericArithmeticOperand === "AGG_ARITH" ? `@${obj["name"]}` : value.raw ?? String(value.value)
17262
+ } : { type: "STRING", value: value.value };
16928
17263
  }
16929
17264
  if (obj["type"] === "VARIABLE_COL" && typeof obj["name"] === "string" && typeof obj["alias"] === "string") {
16930
17265
  const value = variables.get(obj["name"]);
@@ -16943,7 +17278,7 @@ function resolveBatchVariableReferencesInternal(node, variables, numericArithmet
16943
17278
  resolveBatchVariableReferencesInternal(
16944
17279
  value,
16945
17280
  variables,
16946
- (obj["type"] === "ARITH" || obj["type"] === "SCALAR_ARITH" || obj["type"] === "AGG_ARITH") && (key === "left" || key === "right")
17281
+ key === "left" || key === "right" ? obj["type"] === "AGG_ARITH" ? "AGG_ARITH" : obj["type"] === "ARITH" || obj["type"] === "SCALAR_ARITH" ? "ARITH" : false : false
16947
17282
  )
16948
17283
  ])
16949
17284
  );
@@ -17228,8 +17563,21 @@ function buildHavingFieldSemanticsResolver(stmt, rowResolver) {
17228
17563
  if (!("alias" in column) || !column.alias) continue;
17229
17564
  let semantics;
17230
17565
  if (column.type === "FIELD") semantics = rowResolver(aggregateFieldRef(column.field));
17231
- else if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL" || column.type === "WINDOW_COL") {
17566
+ else if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL") {
17232
17567
  semantics = syntheticSemantics("number");
17568
+ } else if (column.type === "WINDOW_COL") {
17569
+ if (column.windowKind !== "AGGREGATE" || column.aggFunc === "COUNT" || column.aggFunc === "SUM" || column.aggFunc === "AVG") {
17570
+ semantics = syntheticSemantics("number");
17571
+ } else if (column.arg.type !== "WILDCARD") {
17572
+ semantics = inferAggregateArgMeta(column.arg, (ref) => {
17573
+ const resolved = rowResolver(ref);
17574
+ return resolved ? {
17575
+ sortKind: resolved.compareMode === "number" || resolved.compareMode === "recordNumber" ? "number" : "string",
17576
+ fieldType: resolved.fieldType,
17577
+ semantics: resolved
17578
+ } : void 0;
17579
+ }).semantics;
17580
+ }
17233
17581
  } else if (column.type === "AGGREGATE") {
17234
17582
  if (column.func === "MIN" || column.func === "MAX" || column.func === "MODE") {
17235
17583
  if (column.arg.type !== "WILDCARD") {
@@ -17591,6 +17939,7 @@ async function validateSelectGroupingPlanning(stmt, client, cacheContext, materi
17591
17939
  function completeInputErrorPrefix(reasons) {
17592
17940
  const reasonList = [...reasons].join(", ");
17593
17941
  const aggregateSubjects = [
17942
+ ["AGGREGATE_WINDOW", "\u96C6\u8A08\u30A6\u30A3\u30F3\u30C9\u30A6\u306E\u6B63\u3057\u3044\u7D50\u679C"],
17594
17943
  ["GROUPING_SETS", "\u5C0F\u8A08\u30FB\u7DCF\u8A08\u306E\u6B63\u3057\u3044\u7D50\u679C"],
17595
17944
  ["STATISTICAL_AGGREGATE", "\u7D71\u8A08\u96C6\u7D04\u306E\u6B63\u3057\u3044\u7D50\u679C"],
17596
17945
  ["AGGREGATE", "\u96C6\u8A08\u306E\u6B63\u3057\u3044\u7D50\u679C"],
@@ -17646,6 +17995,8 @@ function arithHasFieldRef(node) {
17646
17995
  return false;
17647
17996
  }
17648
17997
  function stringFuncArgHasFieldRef(arg) {
17998
+ if (arg.type === "AGG_GROUP_KEY") return true;
17999
+ if (arg.type === "VARIABLE") return false;
17649
18000
  if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
17650
18001
  return scalarValueHasFieldRef(arg);
17651
18002
  }
@@ -18203,7 +18554,11 @@ function collectAggregateArgFieldRefs(arg, out) {
18203
18554
  }
18204
18555
  if (arg.type === "STRING_FUNC") {
18205
18556
  for (const child of arg.args) {
18206
- if (child.type !== "AGG_REF" && child.type !== "AGG_ARITH") collectAggregateArgFieldRefs(child, out);
18557
+ if (child.type === "AGG_GROUP_KEY") {
18558
+ out.push({ type: "FIELD", tableAlias: child.tableAlias ?? null, field: child.field });
18559
+ } else if (child.type !== "AGG_REF" && child.type !== "AGG_ARITH" && child.type !== "VARIABLE") {
18560
+ collectAggregateArgFieldRefs(child, out);
18561
+ }
18207
18562
  }
18208
18563
  return;
18209
18564
  }
@@ -18223,11 +18578,16 @@ function collectAggregateOperandRefs(node, out) {
18223
18578
  collectAggregateOperandRefs(node.left, out);
18224
18579
  collectAggregateOperandRefs(node.right, out);
18225
18580
  }
18581
+ if (node.type === "AGG_GROUP_KEY") out.push({ type: "FIELD", tableAlias: node.tableAlias ?? null, field: node.field });
18226
18582
  }
18227
18583
  function collectStringFuncAggregateRefs(expr, out) {
18228
18584
  for (const arg of expr.args) {
18229
18585
  if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
18230
18586
  collectAggregateOperandRefs(arg, out);
18587
+ } else if (arg.type === "AGG_GROUP_KEY") {
18588
+ out.push({ type: "FIELD", tableAlias: arg.tableAlias ?? null, field: arg.field });
18589
+ } else if (arg.type === "VARIABLE") {
18590
+ continue;
18231
18591
  } else {
18232
18592
  collectScalarAggregateRefs(arg, out);
18233
18593
  }
@@ -18504,12 +18864,18 @@ function inferAggregateArgMeta(arg, resolveField2) {
18504
18864
  if (arg.elseResult) results.push(caseResultColumnMeta(arg.elseResult, resolveField2));
18505
18865
  return mergeExpressionColumnMeta(results);
18506
18866
  }
18867
+ function inferWindowColumnMeta(column, resolveField2) {
18868
+ if (column.windowKind !== "AGGREGATE" || column.aggFunc === "COUNT" || column.aggFunc === "SUM" || column.aggFunc === "AVG") {
18869
+ return syntheticColumnMeta("number");
18870
+ }
18871
+ return column.arg.type === "WILDCARD" ? unknownStringColumnMeta() : inferAggregateArgMeta(column.arg, resolveField2);
18872
+ }
18507
18873
  function withDisplayName(meta, displayName) {
18508
18874
  return { ...meta ?? {}, displayName };
18509
18875
  }
18510
18876
  function selectNeedsSourceColumnMeta(stmt) {
18511
18877
  return stmt.columns.some(
18512
- (column) => column.type === "FIELD" || column.type === "WILDCARD" || column.type === "PARENT_WILDCARD" || column.type === "CASE_COL" || column.type === "AGGREGATE" && (column.func === "MIN" || column.func === "MAX" || column.func === "MODE")
18878
+ (column) => column.type === "FIELD" || column.type === "WILDCARD" || column.type === "PARENT_WILDCARD" || column.type === "CASE_COL" || column.type === "AGGREGATE" && (column.func === "MIN" || column.func === "MAX" || column.func === "MODE") || column.type === "WINDOW_COL" && column.windowKind === "AGGREGATE" && (column.aggFunc === "MIN" || column.aggFunc === "MAX")
18513
18879
  );
18514
18880
  }
18515
18881
  async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext, materializedTables, forLibraryCapture = false) {
@@ -18615,7 +18981,7 @@ async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext,
18615
18981
  } else if (column.type === "STRFUNC_COL") {
18616
18982
  meta = stringFunctionColumnMeta(column.expr);
18617
18983
  } else if (column.type === "WINDOW_COL") {
18618
- meta = syntheticColumnMeta("number");
18984
+ meta = inferWindowColumnMeta(column, resolveField2);
18619
18985
  } else if (column.type === "CASE_COL") {
18620
18986
  const results = column.expr.branches.map((branch) => caseResultColumnMeta(branch.result, resolveField2));
18621
18987
  if (column.expr.elseResult) results.push(caseResultColumnMeta(column.expr.elseResult, resolveField2));
@@ -19542,8 +19908,10 @@ async function buildOrderSemanticsForSelect(stmt, client, cacheContext, material
19542
19908
  if (!("alias" in column) || !column.alias) continue;
19543
19909
  let meta;
19544
19910
  if (column.type === "FIELD") meta = resolveField2(aggregateFieldRef(column.field));
19545
- else if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL" || column.type === "WINDOW_COL") {
19911
+ else if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL") {
19546
19912
  meta = syntheticColumnMeta("number");
19913
+ } else if (column.type === "WINDOW_COL") {
19914
+ meta = inferWindowColumnMeta(column, resolveField2);
19547
19915
  } else if (column.type === "GROUPING_COL") {
19548
19916
  meta = syntheticColumnMeta("number");
19549
19917
  } else if (column.type === "LITERAL_COL" || column.type === "SCALAR_VALUE_COL") meta = syntheticColumnMeta("string");
@@ -23581,6 +23949,20 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlan
23581
23949
  }
23582
23950
  }
23583
23951
  }
23952
+ for (const column of stmt.columns) {
23953
+ if (column.type !== "WINDOW_COL" || column.windowKind !== "AGGREGATE") continue;
23954
+ const clauses = [];
23955
+ if (column.partitionBy.length > 0) {
23956
+ clauses.push(`PARTITION BY ${column.partitionBy.map(
23957
+ (ref) => ref.tableAlias ? `${ref.tableAlias}.${ref.field}` : ref.field
23958
+ ).join(", ")}`);
23959
+ }
23960
+ if (column.orderBy.length > 0) {
23961
+ clauses.push(`ORDER BY ${column.orderBy.map(formatOrderByItem).join(", ")}`);
23962
+ }
23963
+ lines.push(` window ${column.alias}: ${column.aggFunc} OVER (${clauses.join(" ")})`);
23964
+ lines.push(column.frame === null ? " frame: PARTITION ENTIRE" : ` frame: ${column.frame.unit} UNBOUNDED PRECEDING AND CURRENT ROW${column.frame.source === "DEFAULT" ? " (\u65E2\u5B9A)" : ""}`);
23965
+ }
23584
23966
  if (totalCountPlan) {
23585
23967
  const baseQuery = stmt.where === null ? "" : whereToKintone(stmt.where);
23586
23968
  lines.push(` app: APP${stmt.from.appId} (${stmt.from.appId})`);
@@ -24187,7 +24569,8 @@ function collectArithNodeRefs(node, out) {
24187
24569
  }
24188
24570
  if (node.type === "STRING_FUNC") {
24189
24571
  for (const arg of node.args) {
24190
- if (arg.type !== "AGG_REF" && arg.type !== "AGG_ARITH") collectScalarNodeRefs(arg, out);
24572
+ if (arg.type === "AGG_GROUP_KEY") out.add(arg.tableAlias ? `${arg.tableAlias}.${arg.field}` : arg.field);
24573
+ else if (arg.type !== "AGG_REF" && arg.type !== "AGG_ARITH" && arg.type !== "VARIABLE") collectScalarNodeRefs(arg, out);
24191
24574
  }
24192
24575
  }
24193
24576
  }
@@ -24249,7 +24632,10 @@ function collectScalarNodeRefs(node, out) {
24249
24632
  return;
24250
24633
  }
24251
24634
  if (node.type === "STRING_FUNC") {
24252
- for (const arg of node.args) if (arg.type !== "AGG_REF" && arg.type !== "AGG_ARITH") collectScalarNodeRefs(arg, out);
24635
+ for (const arg of node.args) {
24636
+ if (arg.type === "AGG_GROUP_KEY") out.add(arg.tableAlias ? `${arg.tableAlias}.${arg.field}` : arg.field);
24637
+ else if (arg.type !== "AGG_REF" && arg.type !== "AGG_ARITH" && arg.type !== "VARIABLE") collectScalarNodeRefs(arg, out);
24638
+ }
24253
24639
  return;
24254
24640
  }
24255
24641
  if (node.type === "SCALAR_ARITH" || node.type === "CONCAT_OP") {