@rex0220/kintone-sql-tools 3.43.0 → 3.45.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/README.md +0 -2
- package/dist-cli/ksql.js +1193 -746
- package/dist-engine/index.cjs +12 -12
- package/dist-engine/index.mjs +12 -12
- package/dist-engine/ksql-engine.umd.js +12 -12
- package/dist-engine/meta/bundle-baseline.json +7 -7
- package/dist-engine/meta/cjs.json +71 -51
- package/dist-engine/meta/esm.json +71 -51
- package/dist-engine/meta/umd.json +71 -51
- package/dist-mcp/ksql-mcp.js +804 -341
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
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
|
}
|
|
@@ -683,6 +686,7 @@ function arithLabel(node, topLevel = false) {
|
|
|
683
686
|
function fieldValueLabel(value) {
|
|
684
687
|
if (value.type === "FIELD") return value.tableAlias ? `${value.tableAlias}.${value.field}` : value.field;
|
|
685
688
|
if (value.type === "FUNC_FIELD") return stringFuncLabel(value.expr);
|
|
689
|
+
if (value.type === "AGG_FIELD") return aggregateOperandLabel(value.expr);
|
|
686
690
|
if (value.type === "ARITH_FIELD") return arithLabel(value.expr);
|
|
687
691
|
if (value.type === "GROUPING_FIELD") {
|
|
688
692
|
const field = value.ref.field;
|
|
@@ -736,6 +740,8 @@ function whereLabel(expr) {
|
|
|
736
740
|
}
|
|
737
741
|
function caseResultLabel(result) {
|
|
738
742
|
if (result.type === "ARRAY") return `[${result.elements.map((entry) => quote(entry.value)).join(",")}]`;
|
|
743
|
+
if (result.type === "AGG_REF") return aggregateSyntheticName(result.func, result.distinct, result.arg);
|
|
744
|
+
if (result.type === "AGG_ARITH") return aggregateOperandLabel(result);
|
|
739
745
|
if (result.type === "FIELD_REF" || result.type === "ARITH") return arithLabel(result);
|
|
740
746
|
return scalarValueLabel(result);
|
|
741
747
|
}
|
|
@@ -1315,6 +1321,11 @@ var Parser = class {
|
|
|
1315
1321
|
}
|
|
1316
1322
|
throw new ParseError(msg, tok);
|
|
1317
1323
|
}
|
|
1324
|
+
consumeSoftKeyword(word) {
|
|
1325
|
+
if (!this.isSoftKeyword(word)) return false;
|
|
1326
|
+
this.advance();
|
|
1327
|
+
return true;
|
|
1328
|
+
}
|
|
1318
1329
|
parseTempTableName() {
|
|
1319
1330
|
const tok = this.peek();
|
|
1320
1331
|
if (tok.kind === "IDENT" /* IDENT */ && tok.value.startsWith("#")) {
|
|
@@ -1954,6 +1965,12 @@ var Parser = class {
|
|
|
1954
1965
|
const parsedAlias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
|
|
1955
1966
|
return this.withAliasDisplay({ type: "GROUPING_COL", ref, alias: parsedAlias2?.alias ?? null }, parsedAlias2);
|
|
1956
1967
|
}
|
|
1968
|
+
if (this.tryAggregateFunc() === null && this.hasNestedAggregateWindowInSelectColumn()) {
|
|
1969
|
+
throw new ParseError(
|
|
1970
|
+
"\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",
|
|
1971
|
+
this.peek()
|
|
1972
|
+
);
|
|
1973
|
+
}
|
|
1957
1974
|
if (this.tryAggregateFunc() === null && this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
|
|
1958
1975
|
const expr = this.parseScalarValueExpr({ allowAggregateArgs: true });
|
|
1959
1976
|
const parsedAlias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
|
|
@@ -1998,6 +2015,9 @@ var Parser = class {
|
|
|
1998
2015
|
const aggFunc = this.tryAggregateFunc();
|
|
1999
2016
|
if (aggFunc !== null) {
|
|
2000
2017
|
const ref = this.parseAggregateRef(aggFunc);
|
|
2018
|
+
if (this.isSoftKeyword("OVER")) {
|
|
2019
|
+
return this.parseAggregateWindowColumn(ref);
|
|
2020
|
+
}
|
|
2001
2021
|
if (this.isArithOp(this.peek().kind)) {
|
|
2002
2022
|
const expr = this.continueAggArith(ref);
|
|
2003
2023
|
const parsedAlias3 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
|
|
@@ -2049,6 +2069,28 @@ var Parser = class {
|
|
|
2049
2069
|
tryWindowFunc() {
|
|
2050
2070
|
return PARSER_WINDOW_FUNCTION_TOKEN_MAP[this.peek().kind] ?? null;
|
|
2051
2071
|
}
|
|
2072
|
+
hasNestedAggregateWindowInSelectColumn() {
|
|
2073
|
+
let depth = 0;
|
|
2074
|
+
for (let index = this.pos; index < this.tokens.length; index++) {
|
|
2075
|
+
const token = this.tokens[index];
|
|
2076
|
+
if (depth === 0 && (token.kind === "," /* COMMA */ || token.kind === "FROM" /* FROM */ || token.kind === ";" /* SEMICOLON */ || token.kind === "EOF" /* EOF */)) return false;
|
|
2077
|
+
if (PARSER_AGGREGATE_FUNCTION_TOKEN_MAP[token.kind] !== void 0 && this.tokens[index + 1]?.kind === "(" /* LPAREN */) {
|
|
2078
|
+
let aggregateDepth = 0;
|
|
2079
|
+
for (let cursor = index + 1; cursor < this.tokens.length; cursor++) {
|
|
2080
|
+
const candidate = this.tokens[cursor];
|
|
2081
|
+
if (candidate.kind === "(" /* LPAREN */) aggregateDepth++;
|
|
2082
|
+
else if (candidate.kind === ")" /* RPAREN */ && --aggregateDepth === 0) {
|
|
2083
|
+
const next = this.tokens[cursor + 1];
|
|
2084
|
+
if (next?.kind === "IDENT" /* IDENT */ && next.value.toUpperCase() === "OVER") return true;
|
|
2085
|
+
break;
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
if (token.kind === "(" /* LPAREN */) depth++;
|
|
2090
|
+
else if (token.kind === ")" /* RPAREN */) depth--;
|
|
2091
|
+
}
|
|
2092
|
+
return false;
|
|
2093
|
+
}
|
|
2052
2094
|
parseWindowColumn(func) {
|
|
2053
2095
|
this.advance();
|
|
2054
2096
|
this.expect("(" /* LPAREN */);
|
|
@@ -2075,12 +2117,81 @@ var Parser = class {
|
|
|
2075
2117
|
const parsedAlias = this.parseAliasName();
|
|
2076
2118
|
return this.withAliasDisplay({ type: "WINDOW_COL", func, partitionBy, orderBy, alias: parsedAlias.alias }, parsedAlias);
|
|
2077
2119
|
}
|
|
2120
|
+
parseAggregateWindowColumn(ref) {
|
|
2121
|
+
const supported = /* @__PURE__ */ new Set(["SUM", "COUNT", "AVG", "MIN", "MAX"]);
|
|
2122
|
+
if (!supported.has(ref.func)) {
|
|
2123
|
+
throw new ParseError(
|
|
2124
|
+
`${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`,
|
|
2125
|
+
this.peek()
|
|
2126
|
+
);
|
|
2127
|
+
}
|
|
2128
|
+
if (ref.distinct) {
|
|
2129
|
+
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());
|
|
2130
|
+
}
|
|
2131
|
+
this.advance();
|
|
2132
|
+
this.expect("(" /* LPAREN */);
|
|
2133
|
+
const partitionBy = [];
|
|
2134
|
+
if (this.isSoftKeyword("PARTITION")) {
|
|
2135
|
+
this.advance();
|
|
2136
|
+
this.expect("BY" /* BY */, "PARTITION \u306E\u5F8C\u306B\u306F BY \u304C\u5FC5\u8981\u3067\u3059");
|
|
2137
|
+
do {
|
|
2138
|
+
const field = this.parseQualifiedIdent();
|
|
2139
|
+
partitionBy.push({ type: "FIELD", tableAlias: field.tableAlias, field: field.field });
|
|
2140
|
+
} while (this.consume("," /* COMMA */));
|
|
2141
|
+
}
|
|
2142
|
+
const orderBy = this.consume("ORDER" /* ORDER */) ? (this.expect("BY" /* BY */), this.parseOrderBy(false)) : [];
|
|
2143
|
+
let frame = orderBy.length > 0 ? { unit: "RANGE", source: "DEFAULT" } : null;
|
|
2144
|
+
if (this.isSoftKeyword("ROWS") || this.isSoftKeyword("RANGE")) {
|
|
2145
|
+
if (orderBy.length === 0) {
|
|
2146
|
+
throw new ParseError("\u30D5\u30EC\u30FC\u30E0\u53E5\u306B\u306F OVER (ORDER BY ...) \u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
2147
|
+
}
|
|
2148
|
+
const unit = this.advance().value.toUpperCase();
|
|
2149
|
+
const valid = this.consume("BETWEEN" /* BETWEEN */) && this.consumeSoftKeyword("UNBOUNDED") && this.consumeSoftKeyword("PRECEDING") && this.consume("AND" /* AND */) && this.consumeSoftKeyword("CURRENT") && this.consumeSoftKeyword("ROW");
|
|
2150
|
+
if (!valid) {
|
|
2151
|
+
throw new ParseError(
|
|
2152
|
+
"\u5BFE\u5FDC\u3059\u308B\u30D5\u30EC\u30FC\u30E0\u306F BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW \u3060\u3051\u3067\u3059",
|
|
2153
|
+
this.peek()
|
|
2154
|
+
);
|
|
2155
|
+
}
|
|
2156
|
+
frame = { unit, source: "EXPLICIT" };
|
|
2157
|
+
}
|
|
2158
|
+
this.expect(")" /* RPAREN */);
|
|
2159
|
+
if (this.isArithOp(this.peek().kind)) {
|
|
2160
|
+
throw new ParseError(
|
|
2161
|
+
"\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",
|
|
2162
|
+
this.peek()
|
|
2163
|
+
);
|
|
2164
|
+
}
|
|
2165
|
+
if (!this.consume("AS" /* AS */)) {
|
|
2166
|
+
throw new ParseError("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306B\u306F AS alias \u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
2167
|
+
}
|
|
2168
|
+
const parsedAlias = this.parseAliasName();
|
|
2169
|
+
return this.withAliasDisplay({
|
|
2170
|
+
type: "WINDOW_COL",
|
|
2171
|
+
windowKind: "AGGREGATE",
|
|
2172
|
+
aggFunc: ref.func,
|
|
2173
|
+
arg: ref.arg,
|
|
2174
|
+
frame,
|
|
2175
|
+
partitionBy,
|
|
2176
|
+
orderBy,
|
|
2177
|
+
alias: parsedAlias.alias
|
|
2178
|
+
}, parsedAlias);
|
|
2179
|
+
}
|
|
2078
2180
|
selectColumnHasAggregate(column) {
|
|
2079
2181
|
if (column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL") return true;
|
|
2080
2182
|
if (column.type === "STRFUNC_COL") return column.expr.args.some((arg) => this.stringFuncArgHasAggregate(arg));
|
|
2081
2183
|
if (column.type === "SCALAR_VALUE_COL") return this.scalarValueHasAggregate(column.expr);
|
|
2184
|
+
if (column.type === "CASE_COL") return this.nodeHasAggregate(column.expr);
|
|
2082
2185
|
return false;
|
|
2083
2186
|
}
|
|
2187
|
+
nodeHasAggregate(node) {
|
|
2188
|
+
if (node === null || typeof node !== "object") return false;
|
|
2189
|
+
if (Array.isArray(node)) return node.some((value2) => this.nodeHasAggregate(value2));
|
|
2190
|
+
const value = node;
|
|
2191
|
+
if (value["type"] === "AGG_REF" || value["type"] === "AGG_ARITH") return true;
|
|
2192
|
+
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return false;
|
|
2193
|
+
return Object.values(value).some((child) => this.nodeHasAggregate(child));
|
|
2194
|
+
}
|
|
2084
2195
|
stringFuncArgHasAggregate(arg) {
|
|
2085
2196
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
2086
2197
|
return this.scalarValueHasAggregate(arg);
|
|
@@ -2091,11 +2202,7 @@ var Parser = class {
|
|
|
2091
2202
|
return this.scalarValueHasAggregate(expr.left) || this.scalarValueHasAggregate(expr.right);
|
|
2092
2203
|
}
|
|
2093
2204
|
if (expr.type === "CASE_WHEN") {
|
|
2094
|
-
|
|
2095
|
-
return results.some((result) => {
|
|
2096
|
-
if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return false;
|
|
2097
|
-
return this.scalarValueHasAggregate(result);
|
|
2098
|
-
});
|
|
2205
|
+
return this.nodeHasAggregate(expr);
|
|
2099
2206
|
}
|
|
2100
2207
|
return false;
|
|
2101
2208
|
}
|
|
@@ -2148,7 +2255,9 @@ var Parser = class {
|
|
|
2148
2255
|
}
|
|
2149
2256
|
const aggFunc = this.tryAggregateFunc();
|
|
2150
2257
|
if (aggFunc !== null) {
|
|
2151
|
-
|
|
2258
|
+
const ref = this.parseAggregateRef(aggFunc);
|
|
2259
|
+
this.rejectAggregateWindowOutsideSelect();
|
|
2260
|
+
return ref;
|
|
2152
2261
|
}
|
|
2153
2262
|
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());
|
|
2154
2263
|
}
|
|
@@ -2352,9 +2461,9 @@ var Parser = class {
|
|
|
2352
2461
|
this.expect("(" /* LPAREN */);
|
|
2353
2462
|
const condition = this.parseCaseCondition(allowGroupingCondition);
|
|
2354
2463
|
this.expect("," /* COMMA */);
|
|
2355
|
-
const thenResult = this.parseCaseResult();
|
|
2464
|
+
const thenResult = this.parseCaseResult(allowGroupingCondition);
|
|
2356
2465
|
this.expect("," /* COMMA */);
|
|
2357
|
-
const elseResult = this.parseCaseResult();
|
|
2466
|
+
const elseResult = this.parseCaseResult(allowGroupingCondition);
|
|
2358
2467
|
this.expect(")" /* RPAREN */);
|
|
2359
2468
|
return {
|
|
2360
2469
|
type: "CASE_WHEN",
|
|
@@ -2369,7 +2478,7 @@ var Parser = class {
|
|
|
2369
2478
|
this.advance();
|
|
2370
2479
|
const condition = this.parseCaseCondition(allowGroupingCondition);
|
|
2371
2480
|
this.expect("THEN" /* THEN */);
|
|
2372
|
-
const result = this.parseCaseResult();
|
|
2481
|
+
const result = this.parseCaseResult(allowGroupingCondition);
|
|
2373
2482
|
branches.push({ condition, result });
|
|
2374
2483
|
}
|
|
2375
2484
|
if (branches.length === 0) {
|
|
@@ -2377,7 +2486,7 @@ var Parser = class {
|
|
|
2377
2486
|
}
|
|
2378
2487
|
let elseResult = null;
|
|
2379
2488
|
if (this.consume("ELSE" /* ELSE */)) {
|
|
2380
|
-
elseResult = this.parseCaseResult();
|
|
2489
|
+
elseResult = this.parseCaseResult(allowGroupingCondition);
|
|
2381
2490
|
}
|
|
2382
2491
|
this.expect("END" /* END */);
|
|
2383
2492
|
return { type: "CASE_WHEN", branches, elseResult };
|
|
@@ -2387,7 +2496,7 @@ var Parser = class {
|
|
|
2387
2496
|
return this.parseWhereExpr("SELECT_CASE");
|
|
2388
2497
|
}
|
|
2389
2498
|
/** THEN / ELSE の結果値。`||` を含む場合だけ新スカラー文法へ渡す。 */
|
|
2390
|
-
parseCaseResult() {
|
|
2499
|
+
parseCaseResult(allowAggregateResult = false) {
|
|
2391
2500
|
const tok = this.peek();
|
|
2392
2501
|
if (this.insideAggregateArg > 0 && this.tryAggregateFunc() !== null) {
|
|
2393
2502
|
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);
|
|
@@ -2395,6 +2504,12 @@ var Parser = class {
|
|
|
2395
2504
|
if (tok.kind === "[" /* LBRACKET */) {
|
|
2396
2505
|
return this.parseArrayLiteral();
|
|
2397
2506
|
}
|
|
2507
|
+
const aggregateFunc = this.tryAggregateFunc();
|
|
2508
|
+
if (aggregateFunc !== null && allowAggregateResult) {
|
|
2509
|
+
const ref = this.parseAggregateRef(aggregateFunc);
|
|
2510
|
+
this.rejectAggregateWindowOutsideSelect();
|
|
2511
|
+
return this.continueAggArith(ref);
|
|
2512
|
+
}
|
|
2398
2513
|
if (this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
|
|
2399
2514
|
return this.parseScalarValueExpr({ allowAggregateArgs: true });
|
|
2400
2515
|
}
|
|
@@ -2918,8 +3033,20 @@ var Parser = class {
|
|
|
2918
3033
|
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());
|
|
2919
3034
|
}
|
|
2920
3035
|
const ref = this.parseAggregateRef(aggFunc);
|
|
3036
|
+
this.rejectAggregateWindowOutsideSelect();
|
|
3037
|
+
if (this.isArithOp(this.peek().kind)) {
|
|
3038
|
+
return {
|
|
3039
|
+
type: "AGG_FIELD",
|
|
3040
|
+
expr: this.continueAggArith(ref)
|
|
3041
|
+
};
|
|
3042
|
+
}
|
|
2921
3043
|
const syntheticName = aggregateSyntheticName(ref.func, ref.distinct, ref.arg);
|
|
2922
|
-
return {
|
|
3044
|
+
return {
|
|
3045
|
+
type: "FIELD",
|
|
3046
|
+
tableAlias: null,
|
|
3047
|
+
field: syntheticName,
|
|
3048
|
+
...this.groupingFieldContext === "SELECT_CASE" || this.groupingFieldContext === "HAVING" ? { aggregateRef: ref } : {}
|
|
3049
|
+
};
|
|
2923
3050
|
}
|
|
2924
3051
|
if (this.peek().kind === "CASE" /* CASE */) {
|
|
2925
3052
|
const expr = this.parseCaseWhenExpr();
|
|
@@ -3365,6 +3492,16 @@ var Parser = class {
|
|
|
3365
3492
|
* フィールド名/alias: 名前 / total
|
|
3366
3493
|
*/
|
|
3367
3494
|
parseOrderByKey(allowGrouping = true) {
|
|
3495
|
+
const aggregateStart = this.tryAggregateFunc();
|
|
3496
|
+
if (aggregateStart !== null) {
|
|
3497
|
+
const start = this.pos;
|
|
3498
|
+
const ref = this.parseAggregateRef(aggregateStart);
|
|
3499
|
+
if (this.isSoftKeyword("OVER")) {
|
|
3500
|
+
throw new ParseError("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306F SELECT \u5217\u306B\u306E\u307F\u8A18\u8FF0\u3067\u304D\u307E\u3059", this.peek());
|
|
3501
|
+
}
|
|
3502
|
+
this.pos = start;
|
|
3503
|
+
void ref;
|
|
3504
|
+
}
|
|
3368
3505
|
if (this.isUnsupportedGroupingIdStart()) {
|
|
3369
3506
|
throw new ParseError("B65: GROUPING_ID is not supported in Phase1.", this.peek());
|
|
3370
3507
|
}
|
|
@@ -3888,6 +4025,11 @@ var Parser = class {
|
|
|
3888
4025
|
isSoftKeyword(value) {
|
|
3889
4026
|
return this.peek().kind === "IDENT" /* IDENT */ && this.peek().value.toUpperCase() === value;
|
|
3890
4027
|
}
|
|
4028
|
+
rejectAggregateWindowOutsideSelect() {
|
|
4029
|
+
if (this.isSoftKeyword("OVER")) {
|
|
4030
|
+
throw new ParseError("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306F SELECT \u5217\u306B\u306E\u307F\u8A18\u8FF0\u3067\u304D\u307E\u3059", this.peek());
|
|
4031
|
+
}
|
|
4032
|
+
}
|
|
3891
4033
|
validateUpdateFromAssignments(assignments, sourceAlias, tok) {
|
|
3892
4034
|
for (const assignment of assignments) {
|
|
3893
4035
|
if (assignment.value.type === "STRING_FUNC") {
|
|
@@ -4403,7 +4545,11 @@ function selectCompleteInputReasons(stmt) {
|
|
|
4403
4545
|
if (stmt.distinct) reasons.add("DISTINCT");
|
|
4404
4546
|
if (stmt.orderBy.length > 0) reasons.add("LOCAL_ORDER");
|
|
4405
4547
|
for (const column of stmt.columns) {
|
|
4406
|
-
if (column.type === "WINDOW_COL" && column.
|
|
4548
|
+
if (column.type === "WINDOW_COL" && column.windowKind === "AGGREGATE") {
|
|
4549
|
+
reasons.add("AGGREGATE_WINDOW");
|
|
4550
|
+
} else if (column.type === "WINDOW_COL" && column.orderBy.length > 0) {
|
|
4551
|
+
reasons.add("WINDOW_ORDER");
|
|
4552
|
+
}
|
|
4407
4553
|
if (column.type === "SCALAR_SUBQUERY_COL") addReasons(reasons, selectCompleteInputReasons(column.query));
|
|
4408
4554
|
if (column.type === "CASE_COL") {
|
|
4409
4555
|
for (const branch of column.expr.branches) addReasons(reasons, whereCompleteInputReasons(branch.condition));
|
|
@@ -5118,6 +5264,9 @@ function convertField(field) {
|
|
|
5118
5264
|
`WHERE \u53E5\u306E\u95A2\u6570\uFF08${field.expr.func}\uFF09\u306F kintone \u30AF\u30A8\u30EA\u306B\u5909\u63DB\u3067\u304D\u307E\u305B\u3093`
|
|
5119
5265
|
);
|
|
5120
5266
|
}
|
|
5267
|
+
if (field.type === "AGG_FIELD") {
|
|
5268
|
+
throw new KintoneQueryError("HAVING \u53E5\u306E\u96C6\u8A08\u7B97\u8853\u5F0F\u306F kintone \u30AF\u30A8\u30EA\u306B\u5909\u63DB\u3067\u304D\u307E\u305B\u3093");
|
|
5269
|
+
}
|
|
5121
5270
|
if (field.type === "ARITH_FIELD") {
|
|
5122
5271
|
throw new KintoneQueryError("WHERE \u53E5\u306E\u7B97\u8853\u5F0F\u306F kintone \u30AF\u30A8\u30EA\u306B\u5909\u63DB\u3067\u304D\u307E\u305B\u3093");
|
|
5123
5272
|
}
|
|
@@ -5256,292 +5405,564 @@ var KintoneQueryError = class extends Error {
|
|
|
5256
5405
|
}
|
|
5257
5406
|
};
|
|
5258
5407
|
|
|
5259
|
-
// src/
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
if (stmt.columns.some(
|
|
5271
|
-
(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)
|
|
5272
|
-
)) return "FULL_SCAN";
|
|
5273
|
-
if (whereRequiresJsEval(stmt.where)) return "FULL_SCAN";
|
|
5274
|
-
if (stmt.orderBy.some((o) => o.key.type !== "FIELD_NAME")) return "FULL_SCAN";
|
|
5275
|
-
return "SIMPLE";
|
|
5408
|
+
// src/engine/groupingRowMeta.ts
|
|
5409
|
+
var groupingRowMetaKey = /* @__PURE__ */ Symbol("ksql.groupingRowMeta");
|
|
5410
|
+
var groupingRefCanonicalIds = /* @__PURE__ */ new WeakMap();
|
|
5411
|
+
function attachGroupingRowMeta(row, includedCanonicalIds) {
|
|
5412
|
+
Object.defineProperty(row, groupingRowMetaKey, {
|
|
5413
|
+
value: { includedCanonicalIds },
|
|
5414
|
+
enumerable: false,
|
|
5415
|
+
configurable: false,
|
|
5416
|
+
writable: false
|
|
5417
|
+
});
|
|
5418
|
+
return row;
|
|
5276
5419
|
}
|
|
5277
|
-
function
|
|
5278
|
-
|
|
5279
|
-
switch (where.type) {
|
|
5280
|
-
case "BOOLEAN":
|
|
5281
|
-
return true;
|
|
5282
|
-
case "BINARY":
|
|
5283
|
-
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);
|
|
5284
|
-
case "NULL_CHECK":
|
|
5285
|
-
return isFunc(where.field);
|
|
5286
|
-
case "LOGICAL":
|
|
5287
|
-
return whereRequiresJsEval(where.left) || whereRequiresJsEval(where.right);
|
|
5288
|
-
case "NOT":
|
|
5289
|
-
case "GROUP":
|
|
5290
|
-
return whereRequiresJsEval(where.expr);
|
|
5291
|
-
case "EXISTS":
|
|
5292
|
-
return true;
|
|
5293
|
-
}
|
|
5420
|
+
function getGroupingRowMeta(row) {
|
|
5421
|
+
return row[groupingRowMetaKey];
|
|
5294
5422
|
}
|
|
5295
|
-
function
|
|
5296
|
-
return
|
|
5423
|
+
function readGroupingMembership(row) {
|
|
5424
|
+
return getGroupingRowMeta(row)?.includedCanonicalIds;
|
|
5297
5425
|
}
|
|
5298
|
-
function
|
|
5299
|
-
|
|
5300
|
-
const hasPagination = stmt.limit !== null || stmt.offset !== null;
|
|
5301
|
-
const shouldInjectDefaultOrder = hasPagination && stmt.orderBy.length === 0;
|
|
5302
|
-
if (stmt.where !== null) {
|
|
5303
|
-
queryParts.push(whereToKintone(stmt.where));
|
|
5304
|
-
}
|
|
5305
|
-
if (stmt.orderBy.length > 0) {
|
|
5306
|
-
const orderStr = stmt.orderBy.map(convertOrderBy).join(", ");
|
|
5307
|
-
queryParts.push(`order by ${orderStr}`);
|
|
5308
|
-
} else if (shouldInjectDefaultOrder) {
|
|
5309
|
-
queryParts.push("order by $id asc");
|
|
5310
|
-
}
|
|
5311
|
-
if (stmt.limit !== null) {
|
|
5312
|
-
queryParts.push(`limit ${stmt.limit}`);
|
|
5313
|
-
}
|
|
5314
|
-
if (stmt.offset !== null) {
|
|
5315
|
-
queryParts.push(`offset ${stmt.offset}`);
|
|
5316
|
-
}
|
|
5317
|
-
return {
|
|
5318
|
-
app: stmt.from.appId,
|
|
5319
|
-
query: queryParts.join(" "),
|
|
5320
|
-
fields: extractFields(stmt.columns),
|
|
5321
|
-
totalCount: false
|
|
5322
|
-
};
|
|
5426
|
+
function bindGroupingRefCanonicalId(ref, canonicalId) {
|
|
5427
|
+
groupingRefCanonicalIds.set(ref, canonicalId);
|
|
5323
5428
|
}
|
|
5324
|
-
function
|
|
5325
|
-
const
|
|
5326
|
-
if (
|
|
5327
|
-
|
|
5429
|
+
function evalGroupingRef(ref, row) {
|
|
5430
|
+
const membership = readGroupingMembership(row);
|
|
5431
|
+
if (!membership) {
|
|
5432
|
+
throw new Error("internal error: GROUPING() evaluation requires B65 grouping row membership.");
|
|
5328
5433
|
}
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
fields: []
|
|
5333
|
-
// 全件取得なので全フィールドを取得する
|
|
5334
|
-
};
|
|
5335
|
-
}
|
|
5336
|
-
function selectToFetchAllFields(stmt, targetTable, plainGroupByPlan) {
|
|
5337
|
-
const plan = collectRequiredFieldsByTable(stmt, plainGroupByPlan);
|
|
5338
|
-
const target = plan.get(targetTable);
|
|
5339
|
-
if (!target) return [];
|
|
5340
|
-
if (target.allFields) return [];
|
|
5341
|
-
const fields = new Set(target.fields);
|
|
5342
|
-
if (target.table.subtableCode) {
|
|
5343
|
-
fields.add(target.table.subtableCode);
|
|
5434
|
+
const canonicalId = groupingRefCanonicalIds.get(ref);
|
|
5435
|
+
if (!canonicalId) {
|
|
5436
|
+
throw new Error("internal error: GROUPING() reference was not resolved during B65 planning.");
|
|
5344
5437
|
}
|
|
5345
|
-
|
|
5346
|
-
return [...fields];
|
|
5438
|
+
return membership.has(canonicalId) ? "0" : "1";
|
|
5347
5439
|
}
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5440
|
+
|
|
5441
|
+
// src/core/groupingValidation.ts
|
|
5442
|
+
var enforceGroupingPlanningCandidateLimits = (facts) => {
|
|
5443
|
+
if (facts.expandedSetCount > B65_MAX_GROUPING_SETS) {
|
|
5444
|
+
throw new Error(
|
|
5445
|
+
`ArgumentError: B65 expanded grouping set count ${facts.expandedSetCount} exceeds limit ${B65_MAX_GROUPING_SETS} (reason=GROUPING_SET_LIMIT_EXCEEDED).`
|
|
5446
|
+
);
|
|
5352
5447
|
}
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
(c) => c.type === "WILDCARD" || c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "CASE_COL" || c.type === "SCALAR_SUBQUERY_COL"
|
|
5358
|
-
);
|
|
5359
|
-
if (hasWildcard) return [];
|
|
5360
|
-
const fields = [];
|
|
5361
|
-
for (const col of columns) {
|
|
5362
|
-
if (col.type === "FIELD") {
|
|
5363
|
-
fields.push(normalizeSimpleFieldRef(col.field));
|
|
5364
|
-
} else if (col.type === "ARITH_COL") {
|
|
5365
|
-
collectArithNode(col.expr, fields);
|
|
5366
|
-
} else if (col.type === "STRFUNC_COL") {
|
|
5367
|
-
collectStringFuncFields(col.expr, fields);
|
|
5368
|
-
} else if (col.type === "SCALAR_VALUE_COL") {
|
|
5369
|
-
collectScalarValueFields(col.expr, fields);
|
|
5370
|
-
}
|
|
5448
|
+
if (facts.canonicalItemCount > B65_MAX_GROUPING_ITEMS) {
|
|
5449
|
+
throw new Error(
|
|
5450
|
+
`ArgumentError: B65 canonical grouping item count ${facts.canonicalItemCount} exceeds limit ${B65_MAX_GROUPING_ITEMS} (reason=GROUPING_ITEM_LIMIT_EXCEEDED).`
|
|
5451
|
+
);
|
|
5371
5452
|
}
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
collectArithNode(expr.left, out);
|
|
5376
|
-
collectArithNode(expr.right, out);
|
|
5377
|
-
}
|
|
5378
|
-
function collectArithNode(node, out) {
|
|
5379
|
-
if (node.type === "VARIABLE") throw new Error(
|
|
5380
|
-
`InternalError: unresolved arithmetic variable @${node.name} reached SELECT field collection.`
|
|
5381
|
-
);
|
|
5382
|
-
if (node.type === "FIELD_REF") out.push(normalizeSimpleFieldRef(node.field));
|
|
5383
|
-
else if (node.type === "ARITH") collectArithFields(node, out);
|
|
5384
|
-
else if (node.type === "STRING_FUNC") collectStringFuncFields(node, out);
|
|
5453
|
+
};
|
|
5454
|
+
function displayField(field) {
|
|
5455
|
+
return field.tableAlias ? `${field.tableAlias}.${field.field}` : field.field;
|
|
5385
5456
|
}
|
|
5386
|
-
function
|
|
5387
|
-
const dot =
|
|
5388
|
-
|
|
5389
|
-
const unqualified = field.slice(dot + 1);
|
|
5390
|
-
return unqualified || field;
|
|
5457
|
+
function refFromName(name) {
|
|
5458
|
+
const dot = name.indexOf(".");
|
|
5459
|
+
return dot > 0 ? { type: "FIELD", tableAlias: name.slice(0, dot), field: name.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field: name };
|
|
5391
5460
|
}
|
|
5392
|
-
function
|
|
5393
|
-
|
|
5394
|
-
|
|
5461
|
+
function collectGroupingRefs(node, out) {
|
|
5462
|
+
if (node === null || typeof node !== "object") return;
|
|
5463
|
+
if (Array.isArray(node)) {
|
|
5464
|
+
node.forEach((item) => collectGroupingRefs(item, out));
|
|
5465
|
+
return;
|
|
5395
5466
|
}
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
if (
|
|
5399
|
-
|
|
5467
|
+
const value = node;
|
|
5468
|
+
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
|
|
5469
|
+
if (value["type"] === "GROUPING_REF") {
|
|
5470
|
+
out.push(value);
|
|
5400
5471
|
return;
|
|
5401
5472
|
}
|
|
5402
|
-
|
|
5473
|
+
Object.values(value).forEach((item) => collectGroupingRefs(item, out));
|
|
5403
5474
|
}
|
|
5404
|
-
function
|
|
5405
|
-
if (
|
|
5406
|
-
|
|
5475
|
+
function collectAggregateArgumentGroupingRefs(node, out) {
|
|
5476
|
+
if (node === null || typeof node !== "object") return;
|
|
5477
|
+
if (Array.isArray(node)) {
|
|
5478
|
+
node.forEach((item) => collectAggregateArgumentGroupingRefs(item, out));
|
|
5407
5479
|
return;
|
|
5408
5480
|
}
|
|
5409
|
-
|
|
5410
|
-
|
|
5481
|
+
const value = node;
|
|
5482
|
+
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
|
|
5483
|
+
if (value["type"] === "AGGREGATE" || value["type"] === "AGG_REF") {
|
|
5484
|
+
collectGroupingRefs(value["arg"], out);
|
|
5411
5485
|
return;
|
|
5412
5486
|
}
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5487
|
+
Object.values(value).forEach((item) => collectAggregateArgumentGroupingRefs(item, out));
|
|
5488
|
+
}
|
|
5489
|
+
function collectNonAggregateFieldRefs(node, out) {
|
|
5490
|
+
if (node === null || typeof node !== "object") return;
|
|
5491
|
+
if (Array.isArray(node)) {
|
|
5492
|
+
node.forEach((item) => collectNonAggregateFieldRefs(item, out));
|
|
5416
5493
|
return;
|
|
5417
5494
|
}
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5495
|
+
const value = node;
|
|
5496
|
+
const type = value["type"];
|
|
5497
|
+
if (type === "SELECT" || type === "SCALAR_SUBQUERY" || type === "GROUPING_REF" || type === "AGG_REF" || type === "AGG_ARITH") return;
|
|
5498
|
+
if (type === "FIELD" && value["aggregateRef"] !== void 0) return;
|
|
5499
|
+
if (type === "FIELD" && typeof value["field"] === "string") {
|
|
5500
|
+
out.push({
|
|
5501
|
+
type: "FIELD",
|
|
5502
|
+
tableAlias: typeof value["tableAlias"] === "string" ? value["tableAlias"] : null,
|
|
5503
|
+
field: value["field"]
|
|
5504
|
+
});
|
|
5427
5505
|
return;
|
|
5428
5506
|
}
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
function collectAggOperandFields(node, out) {
|
|
5432
|
-
if (node.type === "AGG_REF") {
|
|
5433
|
-
if (node.arg.type !== "WILDCARD") collectAggregateArgFields(node.arg, out);
|
|
5507
|
+
if (type === "FIELD_REF" && typeof value["field"] === "string") {
|
|
5508
|
+
out.push(refFromName(value["field"]));
|
|
5434
5509
|
return;
|
|
5435
5510
|
}
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5511
|
+
Object.values(value).forEach((item) => collectNonAggregateFieldRefs(item, out));
|
|
5512
|
+
}
|
|
5513
|
+
function containsAggregate2(node) {
|
|
5514
|
+
if (node === null || typeof node !== "object") return false;
|
|
5515
|
+
if (Array.isArray(node)) return node.some(containsAggregate2);
|
|
5516
|
+
const value = node;
|
|
5517
|
+
if (value["type"] === "AGG_REF" || value["type"] === "AGG_ARITH") return true;
|
|
5518
|
+
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return false;
|
|
5519
|
+
return Object.values(value).some(containsAggregate2);
|
|
5520
|
+
}
|
|
5521
|
+
function isAggregateMaterializedAlias(column) {
|
|
5522
|
+
if (!("alias" in column) || column.alias === null) return false;
|
|
5523
|
+
if (column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL") return true;
|
|
5524
|
+
if (column.type === "STRFUNC_COL" || column.type === "SCALAR_VALUE_COL" || column.type === "CASE_COL") {
|
|
5525
|
+
return containsAggregate2(column);
|
|
5439
5526
|
}
|
|
5527
|
+
return false;
|
|
5440
5528
|
}
|
|
5441
|
-
function
|
|
5442
|
-
|
|
5443
|
-
|
|
5529
|
+
function outputAliases(columns) {
|
|
5530
|
+
return new Set(columns.flatMap(
|
|
5531
|
+
(column) => "alias" in column && typeof column.alias === "string" ? [column.alias] : []
|
|
5532
|
+
));
|
|
5444
5533
|
}
|
|
5445
|
-
function
|
|
5446
|
-
return
|
|
5447
|
-
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
5448
|
-
return scalarValueHasAggregate(arg);
|
|
5449
|
-
});
|
|
5534
|
+
function isAggregateSyntheticReference(ref) {
|
|
5535
|
+
return ref.tableAlias === null && /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/.test(ref.field);
|
|
5450
5536
|
}
|
|
5451
|
-
function
|
|
5452
|
-
|
|
5453
|
-
if (
|
|
5454
|
-
|
|
5537
|
+
function validateGroupingRefMembership(ref, resolve2, canonicalItems) {
|
|
5538
|
+
const resolved = resolve2(ref.field);
|
|
5539
|
+
if (!resolved.physical) {
|
|
5540
|
+
throw new Error(`ArgumentError: B65 grouping reference ${displayField(ref.field)} must resolve to a physical APP field.`);
|
|
5455
5541
|
}
|
|
5456
|
-
if (
|
|
5457
|
-
|
|
5542
|
+
if (!canonicalItems.has(resolved.canonicalId)) {
|
|
5543
|
+
throw new Error(
|
|
5544
|
+
`ArgumentError: B65 GROUPING argument ${displayField(ref.field)} is not present in grouping allItems (reason=B65_GROUPING_ARG_NOT_ITEM).`
|
|
5545
|
+
);
|
|
5458
5546
|
}
|
|
5459
|
-
|
|
5547
|
+
bindGroupingRefCanonicalId(ref, resolved.canonicalId);
|
|
5460
5548
|
}
|
|
5461
|
-
function
|
|
5462
|
-
|
|
5463
|
-
|
|
5549
|
+
function validateDependency(ref, resolve2, canonicalItems, context) {
|
|
5550
|
+
const resolved = resolve2(ref);
|
|
5551
|
+
if (!resolved.physical || !canonicalItems.has(resolved.canonicalId)) {
|
|
5552
|
+
throw new Error(
|
|
5553
|
+
`ArgumentError: B65 non-aggregate field ${displayField(ref)} in ${context} is not a grouping item (reason=B65_NON_GROUPED_DEPENDENCY).`
|
|
5554
|
+
);
|
|
5555
|
+
}
|
|
5464
5556
|
}
|
|
5465
|
-
function
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
return {
|
|
5472
|
-
bySource: new Map(
|
|
5473
|
-
[...states.entries()].map(([table, state]) => [table, new Set(state.fields)])
|
|
5474
|
-
),
|
|
5475
|
-
unqualified
|
|
5476
|
-
};
|
|
5557
|
+
function keyDependencies(key) {
|
|
5558
|
+
if (key.type === "GROUPING_KEY") return [];
|
|
5559
|
+
if (key.type === "FIELD_NAME") return [refFromName(key.name)];
|
|
5560
|
+
const refs = [];
|
|
5561
|
+
collectNonAggregateFieldRefs(key, refs);
|
|
5562
|
+
return refs;
|
|
5477
5563
|
}
|
|
5478
|
-
function
|
|
5479
|
-
const
|
|
5480
|
-
const
|
|
5481
|
-
const
|
|
5482
|
-
|
|
5483
|
-
for (const table of targetTables) {
|
|
5484
|
-
states.set(table, { table, allFields: false, fields: /* @__PURE__ */ new Set() });
|
|
5564
|
+
function validateGroupingStatic(stmt) {
|
|
5565
|
+
const normalized = normalizeGroupingSpec(stmt);
|
|
5566
|
+
const groupingRefs = [];
|
|
5567
|
+
for (const column of stmt.columns) {
|
|
5568
|
+
if (column.type !== "WINDOW_COL") collectGroupingRefs(column, groupingRefs);
|
|
5485
5569
|
}
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
const
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5570
|
+
collectGroupingRefs(stmt.having, groupingRefs);
|
|
5571
|
+
collectGroupingRefs(stmt.orderBy, groupingRefs);
|
|
5572
|
+
const forbiddenGroupingRefs = [];
|
|
5573
|
+
collectGroupingRefs(stmt.where, forbiddenGroupingRefs);
|
|
5574
|
+
collectGroupingRefs(stmt.joins, forbiddenGroupingRefs);
|
|
5575
|
+
collectAggregateArgumentGroupingRefs(stmt.columns, forbiddenGroupingRefs);
|
|
5576
|
+
collectAggregateArgumentGroupingRefs(stmt.having, forbiddenGroupingRefs);
|
|
5577
|
+
for (const column of stmt.columns) {
|
|
5578
|
+
if (column.type === "WINDOW_COL") collectGroupingRefs(column, forbiddenGroupingRefs);
|
|
5579
|
+
}
|
|
5580
|
+
if (forbiddenGroupingRefs.length > 0) {
|
|
5581
|
+
throw new Error(
|
|
5582
|
+
"ArgumentError: B65 GROUPING() is not allowed in WHERE, JOIN, window, aggregate arguments, or DML expressions."
|
|
5583
|
+
);
|
|
5584
|
+
}
|
|
5585
|
+
if (normalized.type !== "GROUPING_SETS") {
|
|
5586
|
+
if (groupingRefs.length > 0) {
|
|
5587
|
+
throw new Error("ArgumentError: B65 GROUPING() requires GROUP BY ROLLUP or GROUPING SETS.");
|
|
5497
5588
|
}
|
|
5589
|
+
return;
|
|
5498
5590
|
}
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5591
|
+
if (stmt.orderMode === "KINTONE_NATIVE") {
|
|
5592
|
+
throw new Error("ArgumentError: B65 KORDER BY is not supported in Phase1.");
|
|
5593
|
+
}
|
|
5594
|
+
if (stmt.columns.some((column) => column.type === "WINDOW_COL")) {
|
|
5595
|
+
throw new Error("ArgumentError: B65 window functions are not supported in Phase1.");
|
|
5596
|
+
}
|
|
5597
|
+
if (stmt.columns.some(
|
|
5598
|
+
(column) => column.type === "WILDCARD" || column.type === "PARENT_WILDCARD"
|
|
5599
|
+
)) {
|
|
5600
|
+
throw new Error("ArgumentError: B65 wildcard projection is not supported in Phase1.");
|
|
5601
|
+
}
|
|
5602
|
+
}
|
|
5603
|
+
function validateGroupingPlanning(stmt, resolve2, planningGuardHook = () => void 0) {
|
|
5604
|
+
validateGroupingStatic(stmt);
|
|
5605
|
+
const normalized = normalizeGroupingSpec(stmt);
|
|
5606
|
+
const groupingRefs = [];
|
|
5607
|
+
for (const column of stmt.columns) {
|
|
5608
|
+
if (column.type !== "WINDOW_COL") collectGroupingRefs(column, groupingRefs);
|
|
5609
|
+
}
|
|
5610
|
+
collectGroupingRefs(stmt.having, groupingRefs);
|
|
5611
|
+
collectGroupingRefs(stmt.orderBy, groupingRefs);
|
|
5612
|
+
if (normalized.type !== "GROUPING_SETS") {
|
|
5613
|
+
return null;
|
|
5614
|
+
}
|
|
5615
|
+
const resolvedSpec = resolveGroupingSpec(stmt, resolve2);
|
|
5616
|
+
const canonicalItems = /* @__PURE__ */ new Set();
|
|
5617
|
+
const resolvedItems = [];
|
|
5618
|
+
for (const item of resolvedSpec.allItems) {
|
|
5619
|
+
const resolved = item;
|
|
5620
|
+
if (!resolved.physical) {
|
|
5621
|
+
throw new Error(`ArgumentError: B65 grouping item ${displayField(item.field)} must resolve to a physical APP field.`);
|
|
5512
5622
|
}
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
if (!st || st.allFields) return;
|
|
5517
|
-
if (table.subtableCode) {
|
|
5518
|
-
if (fieldName.startsWith("_p.")) {
|
|
5519
|
-
const parentField = fieldName.slice(3);
|
|
5520
|
-
if (parentField && parentField !== "*") st.fields.add(parentField);
|
|
5521
|
-
return;
|
|
5522
|
-
}
|
|
5523
|
-
if (fieldName === "_pid" || fieldName === "_rid" || fieldName === "_idx" || fieldName === "$id") {
|
|
5524
|
-
return;
|
|
5525
|
-
}
|
|
5526
|
-
return;
|
|
5623
|
+
if (!canonicalItems.has(resolved.canonicalId)) {
|
|
5624
|
+
canonicalItems.add(resolved.canonicalId);
|
|
5625
|
+
resolvedItems.push(resolved);
|
|
5527
5626
|
}
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5627
|
+
}
|
|
5628
|
+
planningGuardHook({
|
|
5629
|
+
expandedSetCount: normalized.sets.length,
|
|
5630
|
+
canonicalItemCount: canonicalItems.size
|
|
5631
|
+
});
|
|
5632
|
+
for (const ref of groupingRefs) {
|
|
5633
|
+
validateGroupingRefMembership(ref, resolve2, canonicalItems);
|
|
5634
|
+
}
|
|
5635
|
+
const aliases = outputAliases(stmt.columns);
|
|
5636
|
+
for (const column of stmt.columns) {
|
|
5637
|
+
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;
|
|
5638
|
+
const refs = [];
|
|
5639
|
+
if (column.type === "FIELD") refs.push(refFromName(column.field));
|
|
5640
|
+
else collectNonAggregateFieldRefs(column, refs);
|
|
5641
|
+
for (const ref of refs) validateDependency(ref, resolve2, canonicalItems, "SELECT");
|
|
5642
|
+
}
|
|
5643
|
+
if (stmt.having) {
|
|
5644
|
+
const refs = [];
|
|
5645
|
+
collectNonAggregateFieldRefs(stmt.having, refs);
|
|
5646
|
+
for (const ref of refs) {
|
|
5647
|
+
if (ref.tableAlias === null && aliases.has(ref.field) || isAggregateSyntheticReference(ref)) continue;
|
|
5648
|
+
validateDependency(ref, resolve2, canonicalItems, "HAVING");
|
|
5536
5649
|
}
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5650
|
+
}
|
|
5651
|
+
for (const order of stmt.orderBy) {
|
|
5652
|
+
for (const ref of keyDependencies(order.key)) {
|
|
5653
|
+
if (ref.tableAlias === null && aliases.has(ref.field) || isAggregateSyntheticReference(ref)) continue;
|
|
5654
|
+
validateDependency(ref, resolve2, canonicalItems, "ORDER BY");
|
|
5655
|
+
}
|
|
5656
|
+
}
|
|
5657
|
+
const collisionKeys = /* @__PURE__ */ new Set();
|
|
5658
|
+
for (const item of resolvedItems) {
|
|
5659
|
+
collisionKeys.add(item.directKey);
|
|
5660
|
+
if (item.unqualifiedBridgeKey !== null) collisionKeys.add(item.unqualifiedBridgeKey);
|
|
5661
|
+
}
|
|
5662
|
+
for (const column of stmt.columns) {
|
|
5663
|
+
if (!isAggregateMaterializedAlias(column)) continue;
|
|
5664
|
+
const alias = "alias" in column ? column.alias : null;
|
|
5665
|
+
if (alias === null) continue;
|
|
5666
|
+
if (collisionKeys.has(alias)) {
|
|
5667
|
+
throw new Error(
|
|
5668
|
+
`ArgumentError: B65 aggregate alias ${alias} collides with a grouping runtime key (reason=B65_AGGREGATE_ALIAS_COLLISION).`
|
|
5669
|
+
);
|
|
5670
|
+
}
|
|
5671
|
+
}
|
|
5672
|
+
return resolvedSpec;
|
|
5673
|
+
}
|
|
5674
|
+
|
|
5675
|
+
// src/converter/selectToKintone.ts
|
|
5676
|
+
function hasWindowColumns(columns) {
|
|
5677
|
+
return columns.some((column) => column.type === "WINDOW_COL");
|
|
5678
|
+
}
|
|
5679
|
+
function resolveSelectMode(stmt) {
|
|
5680
|
+
if (stmt.from.subtableCode) return "FULL_SCAN";
|
|
5681
|
+
if (stmt.joins.some((j) => j.table.subtableCode)) return "FULL_SCAN";
|
|
5682
|
+
if (stmt.joins.length > 0) return "FULL_SCAN";
|
|
5683
|
+
if (normalizeGroupingSpec(stmt).type !== "NONE") return "FULL_SCAN";
|
|
5684
|
+
if (stmt.distinct) return "FULL_SCAN";
|
|
5685
|
+
if (hasWindowColumns(stmt.columns)) return "FULL_SCAN";
|
|
5686
|
+
if (stmt.columns.some(
|
|
5687
|
+
(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)
|
|
5688
|
+
)) return "FULL_SCAN";
|
|
5689
|
+
if (whereRequiresJsEval(stmt.where)) return "FULL_SCAN";
|
|
5690
|
+
if (stmt.orderBy.some((o) => o.key.type !== "FIELD_NAME")) return "FULL_SCAN";
|
|
5691
|
+
return "SIMPLE";
|
|
5692
|
+
}
|
|
5693
|
+
function whereRequiresJsEval(where) {
|
|
5694
|
+
if (where === null) return false;
|
|
5695
|
+
switch (where.type) {
|
|
5696
|
+
case "BOOLEAN":
|
|
5697
|
+
return true;
|
|
5698
|
+
case "BINARY":
|
|
5699
|
+
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);
|
|
5700
|
+
case "NULL_CHECK":
|
|
5701
|
+
return isFunc(where.field);
|
|
5702
|
+
case "LOGICAL":
|
|
5703
|
+
return whereRequiresJsEval(where.left) || whereRequiresJsEval(where.right);
|
|
5704
|
+
case "NOT":
|
|
5705
|
+
case "GROUP":
|
|
5706
|
+
return whereRequiresJsEval(where.expr);
|
|
5707
|
+
case "EXISTS":
|
|
5708
|
+
return true;
|
|
5709
|
+
}
|
|
5710
|
+
}
|
|
5711
|
+
function isFunc(fv) {
|
|
5712
|
+
return fv.type === "FUNC_FIELD" || fv.type === "ARITH_FIELD" || fv.type === "CASE_FIELD";
|
|
5713
|
+
}
|
|
5714
|
+
function selectToKintoneParams(stmt) {
|
|
5715
|
+
const queryParts = [];
|
|
5716
|
+
const hasPagination = stmt.limit !== null || stmt.offset !== null;
|
|
5717
|
+
const shouldInjectDefaultOrder = hasPagination && stmt.orderBy.length === 0;
|
|
5718
|
+
if (stmt.where !== null) {
|
|
5719
|
+
queryParts.push(whereToKintone(stmt.where));
|
|
5720
|
+
}
|
|
5721
|
+
if (stmt.orderBy.length > 0) {
|
|
5722
|
+
const orderStr = stmt.orderBy.map(convertOrderBy).join(", ");
|
|
5723
|
+
queryParts.push(`order by ${orderStr}`);
|
|
5724
|
+
} else if (shouldInjectDefaultOrder) {
|
|
5725
|
+
queryParts.push("order by $id asc");
|
|
5726
|
+
}
|
|
5727
|
+
if (stmt.limit !== null) {
|
|
5728
|
+
queryParts.push(`limit ${stmt.limit}`);
|
|
5729
|
+
}
|
|
5730
|
+
if (stmt.offset !== null) {
|
|
5731
|
+
queryParts.push(`offset ${stmt.offset}`);
|
|
5732
|
+
}
|
|
5733
|
+
return {
|
|
5734
|
+
app: stmt.from.appId,
|
|
5735
|
+
query: queryParts.join(" "),
|
|
5736
|
+
fields: extractFields(stmt.columns),
|
|
5737
|
+
totalCount: false
|
|
5738
|
+
};
|
|
5739
|
+
}
|
|
5740
|
+
function selectToFetchAllParams(stmt, appId) {
|
|
5741
|
+
const queryParts = [];
|
|
5742
|
+
if (stmt.where !== null && stmt.joins.length === 0 && !whereRequiresJsEval(stmt.where)) {
|
|
5743
|
+
queryParts.push(whereToKintone(stmt.where));
|
|
5744
|
+
}
|
|
5745
|
+
return {
|
|
5746
|
+
app: appId,
|
|
5747
|
+
query: queryParts.join(" "),
|
|
5748
|
+
fields: []
|
|
5749
|
+
// 全件取得なので全フィールドを取得する
|
|
5750
|
+
};
|
|
5751
|
+
}
|
|
5752
|
+
function selectToFetchAllFields(stmt, targetTable, plainGroupByPlan) {
|
|
5753
|
+
const plan = collectRequiredFieldsByTable(stmt, plainGroupByPlan);
|
|
5754
|
+
const target = plan.get(targetTable);
|
|
5755
|
+
if (!target) return [];
|
|
5756
|
+
if (target.allFields) return [];
|
|
5757
|
+
const fields = new Set(target.fields);
|
|
5758
|
+
if (target.table.subtableCode) {
|
|
5759
|
+
fields.add(target.table.subtableCode);
|
|
5760
|
+
}
|
|
5761
|
+
if (fields.size === 0) fields.add("$id");
|
|
5762
|
+
return [...fields];
|
|
5763
|
+
}
|
|
5764
|
+
function convertOrderBy(item) {
|
|
5765
|
+
const dir = item.direction === "ASC" ? "asc" : "desc";
|
|
5766
|
+
if (item.key.type !== "FIELD_NAME") {
|
|
5767
|
+
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");
|
|
5768
|
+
}
|
|
5769
|
+
return `${item.key.name} ${dir}`;
|
|
5770
|
+
}
|
|
5771
|
+
function extractFields(columns) {
|
|
5772
|
+
const hasWildcard = columns.some(
|
|
5773
|
+
(c) => c.type === "WILDCARD" || c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "CASE_COL" || c.type === "SCALAR_SUBQUERY_COL"
|
|
5774
|
+
);
|
|
5775
|
+
if (hasWildcard) return [];
|
|
5776
|
+
const fields = [];
|
|
5777
|
+
for (const col of columns) {
|
|
5778
|
+
if (col.type === "FIELD") {
|
|
5779
|
+
fields.push(normalizeSimpleFieldRef(col.field));
|
|
5780
|
+
} else if (col.type === "ARITH_COL") {
|
|
5781
|
+
collectArithNode(col.expr, fields);
|
|
5782
|
+
} else if (col.type === "STRFUNC_COL") {
|
|
5783
|
+
collectStringFuncFields(col.expr, fields);
|
|
5784
|
+
} else if (col.type === "SCALAR_VALUE_COL") {
|
|
5785
|
+
collectScalarValueFields(col.expr, fields);
|
|
5786
|
+
}
|
|
5787
|
+
}
|
|
5788
|
+
return [...new Set(fields)];
|
|
5789
|
+
}
|
|
5790
|
+
function collectArithFields(expr, out) {
|
|
5791
|
+
collectArithNode(expr.left, out);
|
|
5792
|
+
collectArithNode(expr.right, out);
|
|
5793
|
+
}
|
|
5794
|
+
function collectArithNode(node, out) {
|
|
5795
|
+
if (node.type === "VARIABLE") throw new Error(
|
|
5796
|
+
`InternalError: unresolved arithmetic variable @${node.name} reached SELECT field collection.`
|
|
5797
|
+
);
|
|
5798
|
+
if (node.type === "FIELD_REF") out.push(normalizeSimpleFieldRef(node.field));
|
|
5799
|
+
else if (node.type === "ARITH") collectArithFields(node, out);
|
|
5800
|
+
else if (node.type === "STRING_FUNC") collectStringFuncFields(node, out);
|
|
5801
|
+
}
|
|
5802
|
+
function normalizeSimpleFieldRef(field) {
|
|
5803
|
+
const dot = field.indexOf(".");
|
|
5804
|
+
if (dot <= 0) return field;
|
|
5805
|
+
const unqualified = field.slice(dot + 1);
|
|
5806
|
+
return unqualified || field;
|
|
5807
|
+
}
|
|
5808
|
+
function collectStringFuncFields(expr, out) {
|
|
5809
|
+
for (const arg of expr.args) {
|
|
5810
|
+
collectStringFuncArgFields(arg, out);
|
|
5811
|
+
}
|
|
5812
|
+
}
|
|
5813
|
+
function collectStringFuncArgFields(arg, out) {
|
|
5814
|
+
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
5815
|
+
collectAggOperandFields(arg, out);
|
|
5816
|
+
return;
|
|
5817
|
+
}
|
|
5818
|
+
collectScalarValueFields(arg, out);
|
|
5819
|
+
}
|
|
5820
|
+
function collectScalarValueFields(expr, out) {
|
|
5821
|
+
if (expr.type === "FIELD") {
|
|
5822
|
+
out.push(normalizeSimpleFieldRef(expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field));
|
|
5823
|
+
return;
|
|
5824
|
+
}
|
|
5825
|
+
if (expr.type === "STRING_FUNC") {
|
|
5826
|
+
collectStringFuncFields(expr, out);
|
|
5827
|
+
return;
|
|
5828
|
+
}
|
|
5829
|
+
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
5830
|
+
collectScalarValueFields(expr.left, out);
|
|
5831
|
+
collectScalarValueFields(expr.right, out);
|
|
5832
|
+
return;
|
|
5833
|
+
}
|
|
5834
|
+
if (expr.type === "CASE_WHEN") {
|
|
5835
|
+
for (const branch of expr.branches) collectCaseResultScalarFields(branch.result, out);
|
|
5836
|
+
if (expr.elseResult) collectCaseResultScalarFields(expr.elseResult, out);
|
|
5837
|
+
}
|
|
5838
|
+
}
|
|
5839
|
+
function collectCaseResultScalarFields(result, out) {
|
|
5840
|
+
if (result.type === "ARRAY") return;
|
|
5841
|
+
if (result.type === "AGG_REF" || result.type === "AGG_ARITH") {
|
|
5842
|
+
collectAggOperandFields(result, out);
|
|
5843
|
+
return;
|
|
5844
|
+
}
|
|
5845
|
+
if (result.type === "FIELD_REF" || result.type === "ARITH") {
|
|
5846
|
+
collectArithNode(result, out);
|
|
5847
|
+
return;
|
|
5848
|
+
}
|
|
5849
|
+
collectScalarValueFields(result, out);
|
|
5850
|
+
}
|
|
5851
|
+
function collectAggOperandFields(node, out) {
|
|
5852
|
+
if (node.type === "AGG_REF") {
|
|
5853
|
+
if (node.arg.type !== "WILDCARD") collectAggregateArgFields(node.arg, out);
|
|
5854
|
+
return;
|
|
5855
|
+
}
|
|
5856
|
+
if (node.type === "AGG_ARITH") {
|
|
5857
|
+
collectAggOperandFields(node.left, out);
|
|
5858
|
+
collectAggOperandFields(node.right, out);
|
|
5859
|
+
}
|
|
5860
|
+
}
|
|
5861
|
+
function collectAggregateArgFields(node, out) {
|
|
5862
|
+
if (node.type === "FIELD_REF" || node.type === "ARITH") collectArithNode(node, out);
|
|
5863
|
+
else collectScalarValueFields(node, out);
|
|
5864
|
+
}
|
|
5865
|
+
function hasAggregateInStringFuncExpr(expr) {
|
|
5866
|
+
return expr.args.some((arg) => {
|
|
5867
|
+
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
5868
|
+
return scalarValueHasAggregate(arg);
|
|
5869
|
+
});
|
|
5870
|
+
}
|
|
5871
|
+
function scalarValueHasAggregate(expr) {
|
|
5872
|
+
if (expr.type === "STRING_FUNC") return hasAggregateInStringFuncExpr(expr);
|
|
5873
|
+
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
5874
|
+
return scalarValueHasAggregate(expr.left) || scalarValueHasAggregate(expr.right);
|
|
5875
|
+
}
|
|
5876
|
+
if (expr.type === "CASE_WHEN") {
|
|
5877
|
+
return expr.branches.some((b) => caseResultHasAggregate(b.result)) || expr.elseResult !== null && caseResultHasAggregate(expr.elseResult);
|
|
5878
|
+
}
|
|
5879
|
+
return false;
|
|
5880
|
+
}
|
|
5881
|
+
function caseResultHasAggregate(result) {
|
|
5882
|
+
if (result.type === "AGG_REF" || result.type === "AGG_ARITH") return true;
|
|
5883
|
+
if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return false;
|
|
5884
|
+
return scalarValueHasAggregate(result);
|
|
5885
|
+
}
|
|
5886
|
+
function collectSelectFieldReferencesBySource(stmt, plainGroupByPlan) {
|
|
5887
|
+
const unqualified = /* @__PURE__ */ new Set();
|
|
5888
|
+
const states = collectRequiredFieldsByTable(stmt, plainGroupByPlan, {
|
|
5889
|
+
includeMaterialized: true,
|
|
5890
|
+
unqualified
|
|
5891
|
+
});
|
|
5892
|
+
return {
|
|
5893
|
+
bySource: new Map(
|
|
5894
|
+
[...states.entries()].map(([table, state]) => [table, new Set(state.fields)])
|
|
5895
|
+
),
|
|
5896
|
+
unqualified
|
|
5897
|
+
};
|
|
5898
|
+
}
|
|
5899
|
+
function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
|
|
5900
|
+
const allTables = [stmt.from, ...stmt.joins.map((j) => j.table)];
|
|
5901
|
+
const physicalTables = [stmt.from, ...stmt.joins.map((j) => j.table)].filter((t) => t.cteName === null);
|
|
5902
|
+
const targetTables = sourceAware ? allTables : physicalTables;
|
|
5903
|
+
const states = /* @__PURE__ */ new Map();
|
|
5904
|
+
for (const table of targetTables) {
|
|
5905
|
+
states.set(table, { table, allFields: false, fields: /* @__PURE__ */ new Set() });
|
|
5906
|
+
}
|
|
5907
|
+
if (states.size === 0) return states;
|
|
5908
|
+
const firstTargetTable = targetTables[0] ?? null;
|
|
5909
|
+
const subtableTable = targetTables.find((t) => !!t.subtableCode) ?? null;
|
|
5910
|
+
const aliasToTable = /* @__PURE__ */ new Map();
|
|
5911
|
+
for (const table of targetTables) {
|
|
5912
|
+
if (table.alias) aliasToTable.set(table.alias, table);
|
|
5913
|
+
if (table.cteName !== null) {
|
|
5914
|
+
aliasToTable.set(table.cteName, table);
|
|
5915
|
+
} else if (!table.subtableCode) {
|
|
5916
|
+
aliasToTable.set(`APP${table.appId}`, table);
|
|
5917
|
+
aliasToTable.set(`app${table.appId}`, table);
|
|
5918
|
+
}
|
|
5919
|
+
}
|
|
5920
|
+
const selectAliases = collectSelectOutputNames(stmt.columns);
|
|
5921
|
+
const markAll = (table) => {
|
|
5922
|
+
const st = states.get(table);
|
|
5923
|
+
if (!st) return;
|
|
5924
|
+
st.allFields = true;
|
|
5925
|
+
st.fields.clear();
|
|
5926
|
+
};
|
|
5927
|
+
const markAllTargetTables = () => {
|
|
5928
|
+
for (const t of targetTables) markAll(t);
|
|
5929
|
+
};
|
|
5930
|
+
const markAllSubtableTables = () => {
|
|
5931
|
+
for (const t of targetTables) {
|
|
5932
|
+
if (t.subtableCode) markAll(t);
|
|
5933
|
+
}
|
|
5934
|
+
};
|
|
5935
|
+
const addFieldToTable = (table, fieldName) => {
|
|
5936
|
+
const st = states.get(table);
|
|
5937
|
+
if (!st || st.allFields) return;
|
|
5938
|
+
if (table.subtableCode) {
|
|
5939
|
+
if (fieldName.startsWith("_p.")) {
|
|
5940
|
+
const parentField = fieldName.slice(3);
|
|
5941
|
+
if (parentField && parentField !== "*") st.fields.add(parentField);
|
|
5942
|
+
return;
|
|
5943
|
+
}
|
|
5944
|
+
if (fieldName === "_pid" || fieldName === "_rid" || fieldName === "_idx" || fieldName === "$id") {
|
|
5945
|
+
return;
|
|
5946
|
+
}
|
|
5947
|
+
return;
|
|
5948
|
+
}
|
|
5949
|
+
if (!fieldName) return;
|
|
5950
|
+
st.fields.add(fieldName);
|
|
5951
|
+
};
|
|
5952
|
+
const addFieldName = (rawName, phase = "select", groupResolution) => {
|
|
5953
|
+
if (!rawName || rawName === "*") return;
|
|
5954
|
+
if (rawName === "_p.*") {
|
|
5955
|
+
markAllSubtableTables();
|
|
5956
|
+
return;
|
|
5957
|
+
}
|
|
5958
|
+
if (rawName.endsWith(".*")) {
|
|
5959
|
+
const qualifier = rawName.slice(0, -2);
|
|
5960
|
+
if (!qualifier) {
|
|
5961
|
+
markAllTargetTables();
|
|
5962
|
+
return;
|
|
5963
|
+
}
|
|
5964
|
+
if (qualifier === "_p") {
|
|
5965
|
+
markAllSubtableTables();
|
|
5545
5966
|
return;
|
|
5546
5967
|
}
|
|
5547
5968
|
const target = aliasToTable.get(qualifier);
|
|
@@ -5667,6 +6088,10 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
|
|
|
5667
6088
|
};
|
|
5668
6089
|
const walkCaseResult = (result, phase = "select") => {
|
|
5669
6090
|
if (result.type === "ARRAY") return;
|
|
6091
|
+
if (result.type === "AGG_REF" || result.type === "AGG_ARITH") {
|
|
6092
|
+
walkAgg(result, phase);
|
|
6093
|
+
return;
|
|
6094
|
+
}
|
|
5670
6095
|
if (result.type === "FIELD_REF" || result.type === "ARITH") {
|
|
5671
6096
|
walkArith(result, phase);
|
|
5672
6097
|
return;
|
|
@@ -5682,6 +6107,10 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
|
|
|
5682
6107
|
};
|
|
5683
6108
|
const walkFieldValue = (fv, phase = "select") => {
|
|
5684
6109
|
if (fv.type === "FIELD") {
|
|
6110
|
+
if (fv.aggregateRef) {
|
|
6111
|
+
walkAgg(fv.aggregateRef, phase);
|
|
6112
|
+
return;
|
|
6113
|
+
}
|
|
5685
6114
|
addFieldRef(fv.field, fv.tableAlias, phase);
|
|
5686
6115
|
return;
|
|
5687
6116
|
}
|
|
@@ -5689,6 +6118,10 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
|
|
|
5689
6118
|
walkStringFunc(fv.expr, phase);
|
|
5690
6119
|
return;
|
|
5691
6120
|
}
|
|
6121
|
+
if (fv.type === "AGG_FIELD") {
|
|
6122
|
+
walkAgg(fv.expr, phase);
|
|
6123
|
+
return;
|
|
6124
|
+
}
|
|
5692
6125
|
if (fv.type === "ARITH_FIELD") {
|
|
5693
6126
|
walkArith(fv.expr, phase);
|
|
5694
6127
|
return;
|
|
@@ -5794,6 +6227,9 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
|
|
|
5794
6227
|
case "SCALAR_SUBQUERY_COL":
|
|
5795
6228
|
break;
|
|
5796
6229
|
case "WINDOW_COL":
|
|
6230
|
+
if (col.windowKind === "AGGREGATE" && col.arg.type !== "WILDCARD") {
|
|
6231
|
+
walkAggregateArg(col.arg, "select");
|
|
6232
|
+
}
|
|
5797
6233
|
for (const ref of col.partitionBy) addFieldRef(ref.field, ref.tableAlias, "select");
|
|
5798
6234
|
for (const item of col.orderBy) walkOrderByKey(item.key, "select");
|
|
5799
6235
|
break;
|
|
@@ -6449,464 +6885,198 @@ function containsKlikeOutsideWhereAndNestedSelects(node, allowedWhere) {
|
|
|
6449
6885
|
if (obj.type === "SELECT") return;
|
|
6450
6886
|
if (obj.type === "BINARY" && (obj.op === "KLIKE" || obj.op === "NOT_KLIKE")) {
|
|
6451
6887
|
found = true;
|
|
6452
|
-
return;
|
|
6453
|
-
}
|
|
6454
|
-
for (const child of Object.values(obj)) visit(child);
|
|
6455
|
-
};
|
|
6456
|
-
visit(node);
|
|
6457
|
-
return found;
|
|
6458
|
-
}
|
|
6459
|
-
function isDescendantOf(root, target) {
|
|
6460
|
-
if (root === null) return false;
|
|
6461
|
-
if (root === target) return true;
|
|
6462
|
-
switch (root.type) {
|
|
6463
|
-
case "LOGICAL":
|
|
6464
|
-
return isDescendantOf(root.left, target) || isDescendantOf(root.right, target);
|
|
6465
|
-
case "NOT":
|
|
6466
|
-
case "GROUP":
|
|
6467
|
-
return isDescendantOf(root.expr, target);
|
|
6468
|
-
case "BINARY":
|
|
6469
|
-
case "NULL_CHECK":
|
|
6470
|
-
case "EXISTS":
|
|
6471
|
-
return false;
|
|
6472
|
-
case "BOOLEAN":
|
|
6473
|
-
return false;
|
|
6474
|
-
}
|
|
6475
|
-
}
|
|
6476
|
-
function walkWithoutNestedSelects(node, visitWhere) {
|
|
6477
|
-
if (Array.isArray(node)) {
|
|
6478
|
-
for (const value of node) walkWithoutNestedSelects(value, visitWhere);
|
|
6479
|
-
return;
|
|
6480
|
-
}
|
|
6481
|
-
if (node === null || typeof node !== "object") return;
|
|
6482
|
-
const obj = node;
|
|
6483
|
-
if (obj.type === "BINARY" || obj.type === "NULL_CHECK" || obj.type === "LOGICAL" || obj.type === "NOT" || obj.type === "GROUP" || obj.type === "EXISTS") {
|
|
6484
|
-
visitWhere(obj);
|
|
6485
|
-
}
|
|
6486
|
-
for (const value of Object.values(obj)) {
|
|
6487
|
-
if (value !== node && isSelectObject(value)) continue;
|
|
6488
|
-
walkWithoutNestedSelects(value, visitWhere);
|
|
6489
|
-
}
|
|
6490
|
-
}
|
|
6491
|
-
function walkObjects(node, visit, skipRoot = false) {
|
|
6492
|
-
if (Array.isArray(node)) {
|
|
6493
|
-
for (const value of node) walkObjects(value, visit);
|
|
6494
|
-
return;
|
|
6495
|
-
}
|
|
6496
|
-
if (node === null || typeof node !== "object") return;
|
|
6497
|
-
const obj = node;
|
|
6498
|
-
if (!skipRoot) visit(obj);
|
|
6499
|
-
for (const value of Object.values(obj)) walkObjects(value, visit);
|
|
6500
|
-
}
|
|
6501
|
-
function isSelectObject(value) {
|
|
6502
|
-
return value !== null && typeof value === "object" && value.type === "SELECT";
|
|
6503
|
-
}
|
|
6504
|
-
|
|
6505
|
-
// src/core/primaryOrganizationDmlValidation.ts
|
|
6506
|
-
var PrimaryOrganizationDmlValidationError = class extends Error {
|
|
6507
|
-
constructor() {
|
|
6508
|
-
super(
|
|
6509
|
-
"ArgumentError: PRIMARY_ORGANIZATION() \u306F DML \u306E WHERE \u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093"
|
|
6510
|
-
);
|
|
6511
|
-
this.name = "ArgumentError";
|
|
6512
|
-
}
|
|
6513
|
-
};
|
|
6514
|
-
function validatePrimaryOrganizationDmlStatement(stmt) {
|
|
6515
|
-
const target = stmt.type === "EXPLAIN" ? stmt.query : stmt;
|
|
6516
|
-
switch (target.type) {
|
|
6517
|
-
case "UPDATE":
|
|
6518
|
-
case "DELETE":
|
|
6519
|
-
case "UPSERT":
|
|
6520
|
-
case "UPSERT_SELECT":
|
|
6521
|
-
case "INSERT_SELECT":
|
|
6522
|
-
if (hasPrimaryOrganizationInWhere(target)) {
|
|
6523
|
-
throw new PrimaryOrganizationDmlValidationError();
|
|
6524
|
-
}
|
|
6525
|
-
return;
|
|
6526
|
-
default:
|
|
6527
|
-
return;
|
|
6528
|
-
}
|
|
6529
|
-
}
|
|
6530
|
-
function hasPrimaryOrganizationInWhere(node) {
|
|
6531
|
-
let found = false;
|
|
6532
|
-
walkObjects2(node, (obj) => {
|
|
6533
|
-
if (found || !Object.prototype.hasOwnProperty.call(obj, "where")) return;
|
|
6534
|
-
if (containsPrimaryOrganization(obj.where)) found = true;
|
|
6535
|
-
});
|
|
6536
|
-
return found;
|
|
6537
|
-
}
|
|
6538
|
-
function containsPrimaryOrganization(node) {
|
|
6539
|
-
let found = false;
|
|
6540
|
-
walkObjects2(node, (obj) => {
|
|
6541
|
-
if (obj.type === "KINTONE_FUNC" && obj.name === "PRIMARY_ORGANIZATION") {
|
|
6542
|
-
found = true;
|
|
6543
|
-
}
|
|
6544
|
-
});
|
|
6545
|
-
return found;
|
|
6546
|
-
}
|
|
6547
|
-
function walkObjects2(node, visit) {
|
|
6548
|
-
if (Array.isArray(node)) {
|
|
6549
|
-
for (const value of node) walkObjects2(value, visit);
|
|
6550
|
-
return;
|
|
6551
|
-
}
|
|
6552
|
-
if (node === null || typeof node !== "object") return;
|
|
6553
|
-
const obj = node;
|
|
6554
|
-
visit(obj);
|
|
6555
|
-
for (const value of Object.values(obj)) walkObjects2(value, visit);
|
|
6556
|
-
}
|
|
6557
|
-
|
|
6558
|
-
// src/core/functionArity.ts
|
|
6559
|
-
function assertArity(func, args, min, max = Number.POSITIVE_INFINITY) {
|
|
6560
|
-
if (args.length >= min && args.length <= max) return;
|
|
6561
|
-
const expected = min === max ? String(min) : max === Number.POSITIVE_INFINITY ? `${min} or more` : `${min} to ${max}`;
|
|
6562
|
-
throw new Error(`ArgumentError: ${func} expects ${expected} argument(s).`);
|
|
6563
|
-
}
|
|
6564
|
-
function assertStringFunctionArity(func, args) {
|
|
6565
|
-
switch (func) {
|
|
6566
|
-
case "UPPER":
|
|
6567
|
-
case "LOWER":
|
|
6568
|
-
case "TRIM":
|
|
6569
|
-
case "LTRIM":
|
|
6570
|
-
case "RTRIM":
|
|
6571
|
-
case "LENGTH":
|
|
6572
|
-
case "LENGTH_CHAR":
|
|
6573
|
-
case "YEAR":
|
|
6574
|
-
case "MONTH":
|
|
6575
|
-
case "DAY":
|
|
6576
|
-
case "DAYOFWEEK":
|
|
6577
|
-
case "QUARTER":
|
|
6578
|
-
case "WEEK":
|
|
6579
|
-
case "LAST_DAY":
|
|
6580
|
-
case "ABS":
|
|
6581
|
-
case "SQRT":
|
|
6582
|
-
return assertArity(func, args, 1, 1);
|
|
6583
|
-
case "SUBSTRING":
|
|
6584
|
-
case "LPAD":
|
|
6585
|
-
case "RPAD":
|
|
6586
|
-
case "REGEXP_LIKE":
|
|
6587
|
-
case "REGEXP_SUBSTR":
|
|
6588
|
-
return assertArity(func, args, 2, 3);
|
|
6589
|
-
case "LEFT":
|
|
6590
|
-
case "RIGHT":
|
|
6591
|
-
case "INSTR":
|
|
6592
|
-
case "ISNULL":
|
|
6593
|
-
case "NULLIF":
|
|
6594
|
-
case "MOD":
|
|
6595
|
-
case "POWER":
|
|
6596
|
-
case "FORMAT":
|
|
6597
|
-
case "CAST":
|
|
6598
|
-
case "DATE_FORMAT":
|
|
6599
|
-
case "DATEDIFF":
|
|
6600
|
-
return assertArity(func, args, 2, 2);
|
|
6601
|
-
case "CONCAT":
|
|
6602
|
-
case "COALESCE":
|
|
6603
|
-
case "GREATEST":
|
|
6604
|
-
case "LEAST":
|
|
6605
|
-
return assertArity(func, args, 2);
|
|
6606
|
-
case "REPLACE":
|
|
6607
|
-
case "TRANSLATE":
|
|
6608
|
-
case "DATE_ADD":
|
|
6609
|
-
return assertArity(func, args, 3, 3);
|
|
6610
|
-
case "REGEXP_REPLACE":
|
|
6611
|
-
return assertArity(func, args, 3, 5);
|
|
6612
|
-
case "ROUND":
|
|
6613
|
-
case "FLOOR":
|
|
6614
|
-
case "CEIL":
|
|
6615
|
-
case "TRUNCATE":
|
|
6616
|
-
return assertArity(func, args, 1, 2);
|
|
6617
|
-
case "CURRENT_DATE":
|
|
6618
|
-
case "CURRENT_TIMESTAMP":
|
|
6619
|
-
return assertArity(func, args, 0, 0);
|
|
6620
|
-
}
|
|
6621
|
-
}
|
|
6622
|
-
|
|
6623
|
-
// src/core/statementValidation.ts
|
|
6624
|
-
function validateStatementStatic(stmt) {
|
|
6625
|
-
validateStringFunctionArities(stmt);
|
|
6626
|
-
validatePrimaryOrganizationDmlStatement(stmt);
|
|
6627
|
-
validateKlikeStatement(stmt);
|
|
6628
|
-
}
|
|
6629
|
-
function validateStringFunctionArities(stmt) {
|
|
6630
|
-
const visit = (value) => {
|
|
6631
|
-
if (value === null || typeof value !== "object") return;
|
|
6632
|
-
if (Array.isArray(value)) {
|
|
6633
|
-
value.forEach(visit);
|
|
6634
|
-
return;
|
|
6635
|
-
}
|
|
6636
|
-
const node = value;
|
|
6637
|
-
if (node.type === "STRING_FUNC") {
|
|
6638
|
-
const expr = node;
|
|
6639
|
-
assertStringFunctionArity(expr.func, expr.args);
|
|
6640
|
-
}
|
|
6641
|
-
Object.values(node).forEach(visit);
|
|
6642
|
-
};
|
|
6643
|
-
visit(stmt);
|
|
6644
|
-
}
|
|
6645
|
-
|
|
6646
|
-
// src/engine/groupingRowMeta.ts
|
|
6647
|
-
var groupingRowMetaKey = /* @__PURE__ */ Symbol("ksql.groupingRowMeta");
|
|
6648
|
-
var groupingRefCanonicalIds = /* @__PURE__ */ new WeakMap();
|
|
6649
|
-
function attachGroupingRowMeta(row, includedCanonicalIds) {
|
|
6650
|
-
Object.defineProperty(row, groupingRowMetaKey, {
|
|
6651
|
-
value: { includedCanonicalIds },
|
|
6652
|
-
enumerable: false,
|
|
6653
|
-
configurable: false,
|
|
6654
|
-
writable: false
|
|
6655
|
-
});
|
|
6656
|
-
return row;
|
|
6657
|
-
}
|
|
6658
|
-
function getGroupingRowMeta(row) {
|
|
6659
|
-
return row[groupingRowMetaKey];
|
|
6660
|
-
}
|
|
6661
|
-
function readGroupingMembership(row) {
|
|
6662
|
-
return getGroupingRowMeta(row)?.includedCanonicalIds;
|
|
6663
|
-
}
|
|
6664
|
-
function bindGroupingRefCanonicalId(ref, canonicalId) {
|
|
6665
|
-
groupingRefCanonicalIds.set(ref, canonicalId);
|
|
6666
|
-
}
|
|
6667
|
-
function evalGroupingRef(ref, row) {
|
|
6668
|
-
const membership = readGroupingMembership(row);
|
|
6669
|
-
if (!membership) {
|
|
6670
|
-
throw new Error("internal error: GROUPING() evaluation requires B65 grouping row membership.");
|
|
6671
|
-
}
|
|
6672
|
-
const canonicalId = groupingRefCanonicalIds.get(ref);
|
|
6673
|
-
if (!canonicalId) {
|
|
6674
|
-
throw new Error("internal error: GROUPING() reference was not resolved during B65 planning.");
|
|
6675
|
-
}
|
|
6676
|
-
return membership.has(canonicalId) ? "0" : "1";
|
|
6888
|
+
return;
|
|
6889
|
+
}
|
|
6890
|
+
for (const child of Object.values(obj)) visit(child);
|
|
6891
|
+
};
|
|
6892
|
+
visit(node);
|
|
6893
|
+
return found;
|
|
6677
6894
|
}
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6895
|
+
function isDescendantOf(root, target) {
|
|
6896
|
+
if (root === null) return false;
|
|
6897
|
+
if (root === target) return true;
|
|
6898
|
+
switch (root.type) {
|
|
6899
|
+
case "LOGICAL":
|
|
6900
|
+
return isDescendantOf(root.left, target) || isDescendantOf(root.right, target);
|
|
6901
|
+
case "NOT":
|
|
6902
|
+
case "GROUP":
|
|
6903
|
+
return isDescendantOf(root.expr, target);
|
|
6904
|
+
case "BINARY":
|
|
6905
|
+
case "NULL_CHECK":
|
|
6906
|
+
case "EXISTS":
|
|
6907
|
+
return false;
|
|
6908
|
+
case "BOOLEAN":
|
|
6909
|
+
return false;
|
|
6690
6910
|
}
|
|
6691
|
-
};
|
|
6692
|
-
function displayField(field) {
|
|
6693
|
-
return field.tableAlias ? `${field.tableAlias}.${field.field}` : field.field;
|
|
6694
|
-
}
|
|
6695
|
-
function refFromName(name) {
|
|
6696
|
-
const dot = name.indexOf(".");
|
|
6697
|
-
return dot > 0 ? { type: "FIELD", tableAlias: name.slice(0, dot), field: name.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field: name };
|
|
6698
6911
|
}
|
|
6699
|
-
function
|
|
6700
|
-
if (node === null || typeof node !== "object") return;
|
|
6912
|
+
function walkWithoutNestedSelects(node, visitWhere) {
|
|
6701
6913
|
if (Array.isArray(node)) {
|
|
6702
|
-
node
|
|
6703
|
-
return;
|
|
6704
|
-
}
|
|
6705
|
-
const value = node;
|
|
6706
|
-
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
|
|
6707
|
-
if (value["type"] === "GROUPING_REF") {
|
|
6708
|
-
out.push(value);
|
|
6914
|
+
for (const value of node) walkWithoutNestedSelects(value, visitWhere);
|
|
6709
6915
|
return;
|
|
6710
6916
|
}
|
|
6711
|
-
Object.values(value).forEach((item) => collectGroupingRefs(item, out));
|
|
6712
|
-
}
|
|
6713
|
-
function collectAggregateArgumentGroupingRefs(node, out) {
|
|
6714
6917
|
if (node === null || typeof node !== "object") return;
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6918
|
+
const obj = node;
|
|
6919
|
+
if (obj.type === "BINARY" || obj.type === "NULL_CHECK" || obj.type === "LOGICAL" || obj.type === "NOT" || obj.type === "GROUP" || obj.type === "EXISTS") {
|
|
6920
|
+
visitWhere(obj);
|
|
6718
6921
|
}
|
|
6719
|
-
const value
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
collectGroupingRefs(value["arg"], out);
|
|
6723
|
-
return;
|
|
6922
|
+
for (const value of Object.values(obj)) {
|
|
6923
|
+
if (value !== node && isSelectObject(value)) continue;
|
|
6924
|
+
walkWithoutNestedSelects(value, visitWhere);
|
|
6724
6925
|
}
|
|
6725
|
-
Object.values(value).forEach((item) => collectAggregateArgumentGroupingRefs(item, out));
|
|
6726
6926
|
}
|
|
6727
|
-
function
|
|
6728
|
-
if (node === null || typeof node !== "object") return;
|
|
6927
|
+
function walkObjects(node, visit, skipRoot = false) {
|
|
6729
6928
|
if (Array.isArray(node)) {
|
|
6730
|
-
node
|
|
6731
|
-
return;
|
|
6732
|
-
}
|
|
6733
|
-
const value = node;
|
|
6734
|
-
const type = value["type"];
|
|
6735
|
-
if (type === "SELECT" || type === "SCALAR_SUBQUERY" || type === "GROUPING_REF" || type === "AGG_REF" || type === "AGG_ARITH") return;
|
|
6736
|
-
if (type === "FIELD" && typeof value["field"] === "string") {
|
|
6737
|
-
out.push({
|
|
6738
|
-
type: "FIELD",
|
|
6739
|
-
tableAlias: typeof value["tableAlias"] === "string" ? value["tableAlias"] : null,
|
|
6740
|
-
field: value["field"]
|
|
6741
|
-
});
|
|
6742
|
-
return;
|
|
6743
|
-
}
|
|
6744
|
-
if (type === "FIELD_REF" && typeof value["field"] === "string") {
|
|
6745
|
-
out.push(refFromName(value["field"]));
|
|
6929
|
+
for (const value of node) walkObjects(value, visit);
|
|
6746
6930
|
return;
|
|
6747
6931
|
}
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
if (Array.isArray(node)) return node.some(containsAggregate2);
|
|
6753
|
-
const value = node;
|
|
6754
|
-
if (value["type"] === "AGG_REF" || value["type"] === "AGG_ARITH") return true;
|
|
6755
|
-
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return false;
|
|
6756
|
-
return Object.values(value).some(containsAggregate2);
|
|
6757
|
-
}
|
|
6758
|
-
function isAggregateMaterializedAlias(column) {
|
|
6759
|
-
if (!("alias" in column) || column.alias === null) return false;
|
|
6760
|
-
if (column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL") return true;
|
|
6761
|
-
if (column.type === "STRFUNC_COL" || column.type === "SCALAR_VALUE_COL") {
|
|
6762
|
-
return containsAggregate2(column);
|
|
6763
|
-
}
|
|
6764
|
-
return false;
|
|
6765
|
-
}
|
|
6766
|
-
function outputAliases(columns) {
|
|
6767
|
-
return new Set(columns.flatMap(
|
|
6768
|
-
(column) => "alias" in column && typeof column.alias === "string" ? [column.alias] : []
|
|
6769
|
-
));
|
|
6770
|
-
}
|
|
6771
|
-
function isAggregateSyntheticReference(ref) {
|
|
6772
|
-
return ref.tableAlias === null && /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/.test(ref.field);
|
|
6773
|
-
}
|
|
6774
|
-
function validateGroupingRefMembership(ref, resolve2, canonicalItems) {
|
|
6775
|
-
const resolved = resolve2(ref.field);
|
|
6776
|
-
if (!resolved.physical) {
|
|
6777
|
-
throw new Error(`ArgumentError: B65 grouping reference ${displayField(ref.field)} must resolve to a physical APP field.`);
|
|
6778
|
-
}
|
|
6779
|
-
if (!canonicalItems.has(resolved.canonicalId)) {
|
|
6780
|
-
throw new Error(
|
|
6781
|
-
`ArgumentError: B65 GROUPING argument ${displayField(ref.field)} is not present in grouping allItems (reason=B65_GROUPING_ARG_NOT_ITEM).`
|
|
6782
|
-
);
|
|
6783
|
-
}
|
|
6784
|
-
bindGroupingRefCanonicalId(ref, resolved.canonicalId);
|
|
6785
|
-
}
|
|
6786
|
-
function validateDependency(ref, resolve2, canonicalItems, context) {
|
|
6787
|
-
const resolved = resolve2(ref);
|
|
6788
|
-
if (!resolved.physical || !canonicalItems.has(resolved.canonicalId)) {
|
|
6789
|
-
throw new Error(
|
|
6790
|
-
`ArgumentError: B65 non-aggregate field ${displayField(ref)} in ${context} is not a grouping item (reason=B65_NON_GROUPED_DEPENDENCY).`
|
|
6791
|
-
);
|
|
6792
|
-
}
|
|
6932
|
+
if (node === null || typeof node !== "object") return;
|
|
6933
|
+
const obj = node;
|
|
6934
|
+
if (!skipRoot) visit(obj);
|
|
6935
|
+
for (const value of Object.values(obj)) walkObjects(value, visit);
|
|
6793
6936
|
}
|
|
6794
|
-
function
|
|
6795
|
-
|
|
6796
|
-
if (key.type === "FIELD_NAME") return [refFromName(key.name)];
|
|
6797
|
-
const refs = [];
|
|
6798
|
-
collectNonAggregateFieldRefs(key, refs);
|
|
6799
|
-
return refs;
|
|
6937
|
+
function isSelectObject(value) {
|
|
6938
|
+
return value !== null && typeof value === "object" && value.type === "SELECT";
|
|
6800
6939
|
}
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
collectGroupingRefs(stmt.having, groupingRefs);
|
|
6808
|
-
collectGroupingRefs(stmt.orderBy, groupingRefs);
|
|
6809
|
-
const forbiddenGroupingRefs = [];
|
|
6810
|
-
collectGroupingRefs(stmt.where, forbiddenGroupingRefs);
|
|
6811
|
-
collectGroupingRefs(stmt.joins, forbiddenGroupingRefs);
|
|
6812
|
-
collectAggregateArgumentGroupingRefs(stmt.columns, forbiddenGroupingRefs);
|
|
6813
|
-
collectAggregateArgumentGroupingRefs(stmt.having, forbiddenGroupingRefs);
|
|
6814
|
-
for (const column of stmt.columns) {
|
|
6815
|
-
if (column.type === "WINDOW_COL") collectGroupingRefs(column, forbiddenGroupingRefs);
|
|
6816
|
-
}
|
|
6817
|
-
if (forbiddenGroupingRefs.length > 0) {
|
|
6818
|
-
throw new Error(
|
|
6819
|
-
"ArgumentError: B65 GROUPING() is not allowed in WHERE, JOIN, window, aggregate arguments, or DML expressions."
|
|
6940
|
+
|
|
6941
|
+
// src/core/primaryOrganizationDmlValidation.ts
|
|
6942
|
+
var PrimaryOrganizationDmlValidationError = class extends Error {
|
|
6943
|
+
constructor() {
|
|
6944
|
+
super(
|
|
6945
|
+
"ArgumentError: PRIMARY_ORGANIZATION() \u306F DML \u306E WHERE \u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093"
|
|
6820
6946
|
);
|
|
6947
|
+
this.name = "ArgumentError";
|
|
6821
6948
|
}
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
const resolvedSpec = resolveGroupingSpec(stmt, resolve2);
|
|
6853
|
-
const canonicalItems = /* @__PURE__ */ new Set();
|
|
6854
|
-
const resolvedItems = [];
|
|
6855
|
-
for (const item of resolvedSpec.allItems) {
|
|
6856
|
-
const resolved = item;
|
|
6857
|
-
if (!resolved.physical) {
|
|
6858
|
-
throw new Error(`ArgumentError: B65 grouping item ${displayField(item.field)} must resolve to a physical APP field.`);
|
|
6859
|
-
}
|
|
6860
|
-
if (!canonicalItems.has(resolved.canonicalId)) {
|
|
6861
|
-
canonicalItems.add(resolved.canonicalId);
|
|
6862
|
-
resolvedItems.push(resolved);
|
|
6863
|
-
}
|
|
6864
|
-
}
|
|
6865
|
-
planningGuardHook({
|
|
6866
|
-
expandedSetCount: normalized.sets.length,
|
|
6867
|
-
canonicalItemCount: canonicalItems.size
|
|
6868
|
-
});
|
|
6869
|
-
for (const ref of groupingRefs) {
|
|
6870
|
-
validateGroupingRefMembership(ref, resolve2, canonicalItems);
|
|
6871
|
-
}
|
|
6872
|
-
const aliases = outputAliases(stmt.columns);
|
|
6873
|
-
for (const column of stmt.columns) {
|
|
6874
|
-
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;
|
|
6875
|
-
const refs = [];
|
|
6876
|
-
if (column.type === "FIELD") refs.push(refFromName(column.field));
|
|
6877
|
-
else collectNonAggregateFieldRefs(column, refs);
|
|
6878
|
-
for (const ref of refs) validateDependency(ref, resolve2, canonicalItems, "SELECT");
|
|
6879
|
-
}
|
|
6880
|
-
if (stmt.having) {
|
|
6881
|
-
const refs = [];
|
|
6882
|
-
collectNonAggregateFieldRefs(stmt.having, refs);
|
|
6883
|
-
for (const ref of refs) {
|
|
6884
|
-
if (ref.tableAlias === null && aliases.has(ref.field) || isAggregateSyntheticReference(ref)) continue;
|
|
6885
|
-
validateDependency(ref, resolve2, canonicalItems, "HAVING");
|
|
6886
|
-
}
|
|
6887
|
-
}
|
|
6888
|
-
for (const order of stmt.orderBy) {
|
|
6889
|
-
for (const ref of keyDependencies(order.key)) {
|
|
6890
|
-
if (ref.tableAlias === null && aliases.has(ref.field) || isAggregateSyntheticReference(ref)) continue;
|
|
6891
|
-
validateDependency(ref, resolve2, canonicalItems, "ORDER BY");
|
|
6949
|
+
};
|
|
6950
|
+
function validatePrimaryOrganizationDmlStatement(stmt) {
|
|
6951
|
+
const target = stmt.type === "EXPLAIN" ? stmt.query : stmt;
|
|
6952
|
+
switch (target.type) {
|
|
6953
|
+
case "UPDATE":
|
|
6954
|
+
case "DELETE":
|
|
6955
|
+
case "UPSERT":
|
|
6956
|
+
case "UPSERT_SELECT":
|
|
6957
|
+
case "INSERT_SELECT":
|
|
6958
|
+
if (hasPrimaryOrganizationInWhere(target)) {
|
|
6959
|
+
throw new PrimaryOrganizationDmlValidationError();
|
|
6960
|
+
}
|
|
6961
|
+
return;
|
|
6962
|
+
default:
|
|
6963
|
+
return;
|
|
6964
|
+
}
|
|
6965
|
+
}
|
|
6966
|
+
function hasPrimaryOrganizationInWhere(node) {
|
|
6967
|
+
let found = false;
|
|
6968
|
+
walkObjects2(node, (obj) => {
|
|
6969
|
+
if (found || !Object.prototype.hasOwnProperty.call(obj, "where")) return;
|
|
6970
|
+
if (containsPrimaryOrganization(obj.where)) found = true;
|
|
6971
|
+
});
|
|
6972
|
+
return found;
|
|
6973
|
+
}
|
|
6974
|
+
function containsPrimaryOrganization(node) {
|
|
6975
|
+
let found = false;
|
|
6976
|
+
walkObjects2(node, (obj) => {
|
|
6977
|
+
if (obj.type === "KINTONE_FUNC" && obj.name === "PRIMARY_ORGANIZATION") {
|
|
6978
|
+
found = true;
|
|
6892
6979
|
}
|
|
6980
|
+
});
|
|
6981
|
+
return found;
|
|
6982
|
+
}
|
|
6983
|
+
function walkObjects2(node, visit) {
|
|
6984
|
+
if (Array.isArray(node)) {
|
|
6985
|
+
for (const value of node) walkObjects2(value, visit);
|
|
6986
|
+
return;
|
|
6893
6987
|
}
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6988
|
+
if (node === null || typeof node !== "object") return;
|
|
6989
|
+
const obj = node;
|
|
6990
|
+
visit(obj);
|
|
6991
|
+
for (const value of Object.values(obj)) walkObjects2(value, visit);
|
|
6992
|
+
}
|
|
6993
|
+
|
|
6994
|
+
// src/core/functionArity.ts
|
|
6995
|
+
function assertArity(func, args, min, max = Number.POSITIVE_INFINITY) {
|
|
6996
|
+
if (args.length >= min && args.length <= max) return;
|
|
6997
|
+
const expected = min === max ? String(min) : max === Number.POSITIVE_INFINITY ? `${min} or more` : `${min} to ${max}`;
|
|
6998
|
+
throw new Error(`ArgumentError: ${func} expects ${expected} argument(s).`);
|
|
6999
|
+
}
|
|
7000
|
+
function assertStringFunctionArity(func, args) {
|
|
7001
|
+
switch (func) {
|
|
7002
|
+
case "UPPER":
|
|
7003
|
+
case "LOWER":
|
|
7004
|
+
case "TRIM":
|
|
7005
|
+
case "LTRIM":
|
|
7006
|
+
case "RTRIM":
|
|
7007
|
+
case "LENGTH":
|
|
7008
|
+
case "LENGTH_CHAR":
|
|
7009
|
+
case "YEAR":
|
|
7010
|
+
case "MONTH":
|
|
7011
|
+
case "DAY":
|
|
7012
|
+
case "DAYOFWEEK":
|
|
7013
|
+
case "QUARTER":
|
|
7014
|
+
case "WEEK":
|
|
7015
|
+
case "LAST_DAY":
|
|
7016
|
+
case "ABS":
|
|
7017
|
+
case "SQRT":
|
|
7018
|
+
return assertArity(func, args, 1, 1);
|
|
7019
|
+
case "SUBSTRING":
|
|
7020
|
+
case "LPAD":
|
|
7021
|
+
case "RPAD":
|
|
7022
|
+
case "REGEXP_LIKE":
|
|
7023
|
+
case "REGEXP_SUBSTR":
|
|
7024
|
+
return assertArity(func, args, 2, 3);
|
|
7025
|
+
case "LEFT":
|
|
7026
|
+
case "RIGHT":
|
|
7027
|
+
case "INSTR":
|
|
7028
|
+
case "ISNULL":
|
|
7029
|
+
case "NULLIF":
|
|
7030
|
+
case "MOD":
|
|
7031
|
+
case "POWER":
|
|
7032
|
+
case "FORMAT":
|
|
7033
|
+
case "CAST":
|
|
7034
|
+
case "DATE_FORMAT":
|
|
7035
|
+
case "DATEDIFF":
|
|
7036
|
+
return assertArity(func, args, 2, 2);
|
|
7037
|
+
case "CONCAT":
|
|
7038
|
+
case "COALESCE":
|
|
7039
|
+
case "GREATEST":
|
|
7040
|
+
case "LEAST":
|
|
7041
|
+
return assertArity(func, args, 2);
|
|
7042
|
+
case "REPLACE":
|
|
7043
|
+
case "TRANSLATE":
|
|
7044
|
+
case "DATE_ADD":
|
|
7045
|
+
return assertArity(func, args, 3, 3);
|
|
7046
|
+
case "REGEXP_REPLACE":
|
|
7047
|
+
return assertArity(func, args, 3, 5);
|
|
7048
|
+
case "ROUND":
|
|
7049
|
+
case "FLOOR":
|
|
7050
|
+
case "CEIL":
|
|
7051
|
+
case "TRUNCATE":
|
|
7052
|
+
return assertArity(func, args, 1, 2);
|
|
7053
|
+
case "CURRENT_DATE":
|
|
7054
|
+
case "CURRENT_TIMESTAMP":
|
|
7055
|
+
return assertArity(func, args, 0, 0);
|
|
6898
7056
|
}
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
7057
|
+
}
|
|
7058
|
+
|
|
7059
|
+
// src/core/statementValidation.ts
|
|
7060
|
+
function validateStatementStatic(stmt) {
|
|
7061
|
+
validateStringFunctionArities(stmt);
|
|
7062
|
+
validatePrimaryOrganizationDmlStatement(stmt);
|
|
7063
|
+
validateKlikeStatement(stmt);
|
|
7064
|
+
}
|
|
7065
|
+
function validateStringFunctionArities(stmt) {
|
|
7066
|
+
const visit = (value) => {
|
|
7067
|
+
if (value === null || typeof value !== "object") return;
|
|
7068
|
+
if (Array.isArray(value)) {
|
|
7069
|
+
value.forEach(visit);
|
|
7070
|
+
return;
|
|
6907
7071
|
}
|
|
6908
|
-
|
|
6909
|
-
|
|
7072
|
+
const node = value;
|
|
7073
|
+
if (node.type === "STRING_FUNC") {
|
|
7074
|
+
const expr = node;
|
|
7075
|
+
assertStringFunctionArity(expr.func, expr.args);
|
|
7076
|
+
}
|
|
7077
|
+
Object.values(node).forEach(visit);
|
|
7078
|
+
};
|
|
7079
|
+
visit(stmt);
|
|
6910
7080
|
}
|
|
6911
7081
|
|
|
6912
7082
|
// src/core/batch.ts
|
|
@@ -7985,10 +8155,32 @@ function formatWithComma(num, digits) {
|
|
|
7985
8155
|
return decStr ? `${intFmt}.${decStr}` : intFmt;
|
|
7986
8156
|
}
|
|
7987
8157
|
function evalStringFuncArg(arg, row, resolveFieldType, resolveFieldSemantics2) {
|
|
7988
|
-
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH")
|
|
8158
|
+
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
8159
|
+
return String(evalMaterializedAggregateOperand(arg, row));
|
|
8160
|
+
}
|
|
7989
8161
|
if (arg.type === "NUMBER") return numberLiteralText(arg);
|
|
7990
8162
|
return String(evalScalarValueExpr(arg, row, resolveFieldType, resolveFieldSemantics2));
|
|
7991
8163
|
}
|
|
8164
|
+
function evalMaterializedAggregateOperand(node, row) {
|
|
8165
|
+
if (node.type === "NUMBER") return node.value;
|
|
8166
|
+
if (node.type === "AGG_REF") {
|
|
8167
|
+
return row[aggregateSyntheticName(node.func, node.distinct, node.arg)] ?? "";
|
|
8168
|
+
}
|
|
8169
|
+
const left = Number(evalMaterializedAggregateOperand(node.left, row));
|
|
8170
|
+
const right = Number(evalMaterializedAggregateOperand(node.right, row));
|
|
8171
|
+
switch (node.op) {
|
|
8172
|
+
case "+":
|
|
8173
|
+
return left + right;
|
|
8174
|
+
case "-":
|
|
8175
|
+
return left - right;
|
|
8176
|
+
case "*":
|
|
8177
|
+
return left * right;
|
|
8178
|
+
case "/":
|
|
8179
|
+
return right !== 0 ? left / right : NaN;
|
|
8180
|
+
case "%":
|
|
8181
|
+
return right !== 0 ? left % right : NaN;
|
|
8182
|
+
}
|
|
8183
|
+
}
|
|
7992
8184
|
function resolveFieldRef(row, field) {
|
|
7993
8185
|
const direct = row[field];
|
|
7994
8186
|
if (direct !== void 0) return direct;
|
|
@@ -8083,7 +8275,7 @@ function semanticsForLeft(left, fieldType, resolveSemantics) {
|
|
|
8083
8275
|
if (left.type === "FIELD") {
|
|
8084
8276
|
return resolveSemantics?.(left) ?? (fieldType ? resolveFieldSemantics({ fieldType }) : syntheticSemantics("string"));
|
|
8085
8277
|
}
|
|
8086
|
-
if (left.type === "ARITH_FIELD") return syntheticSemantics("number");
|
|
8278
|
+
if (left.type === "ARITH_FIELD" || left.type === "AGG_FIELD") return syntheticSemantics("number");
|
|
8087
8279
|
if (left.type === "FUNC_FIELD") {
|
|
8088
8280
|
return syntheticSemantics(NUMERIC_STRING_FUNCTIONS.has(left.expr.func) ? "number" : "string");
|
|
8089
8281
|
}
|
|
@@ -8176,6 +8368,7 @@ function evalLogical(expr, row, resolveFieldType, appliedKlikes, resolveFieldSem
|
|
|
8176
8368
|
}
|
|
8177
8369
|
function resolveField(field, row, resolveFieldType, resolveFieldSemantics2) {
|
|
8178
8370
|
if (field.type === "FUNC_FIELD") return evalStringFunc(field.expr, row);
|
|
8371
|
+
if (field.type === "AGG_FIELD") return String(evalMaterializedAggregateOperand(field.expr, row));
|
|
8179
8372
|
if (field.type === "ARITH_FIELD") return String(evalArithExpr(field.expr, row));
|
|
8180
8373
|
if (field.type === "CASE_FIELD") return evalCaseWhen(field.expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
8181
8374
|
if (field.type === "GROUPING_FIELD") return evalGroupingRef(field.ref, row);
|
|
@@ -8233,12 +8426,20 @@ function evalCaseWhenNullable(expr, row, resolveFieldType, resolveFieldSemantics
|
|
|
8233
8426
|
}
|
|
8234
8427
|
function evalCaseResultNullable(result, row, resolveFieldType, resolveFieldSemantics2) {
|
|
8235
8428
|
if (result.type === "ARRAY") return result.elements.map((entry) => entry.value).join(",");
|
|
8429
|
+
if (result.type === "AGG_REF") {
|
|
8430
|
+
return row[aggregateSyntheticName(result.func, result.distinct, result.arg)] ?? "";
|
|
8431
|
+
}
|
|
8432
|
+
if (result.type === "AGG_ARITH") return row[aggregateOperandLabel(result)] ?? "";
|
|
8236
8433
|
if (result.type === "FIELD_REF") return row[result.field] ?? "";
|
|
8237
8434
|
if (result.type === "ARITH") return evalArithExpr(result, row);
|
|
8238
8435
|
return evalScalarValueExprNullable(result, row, resolveFieldType, resolveFieldSemantics2);
|
|
8239
8436
|
}
|
|
8240
8437
|
function evalCaseResult(result, row, resolveFieldType, resolveFieldSemantics2) {
|
|
8241
8438
|
if (result.type === "ARRAY") return result.elements.map((e) => e.value).join(",");
|
|
8439
|
+
if (result.type === "AGG_REF") {
|
|
8440
|
+
return row[aggregateSyntheticName(result.func, result.distinct, result.arg)] ?? "";
|
|
8441
|
+
}
|
|
8442
|
+
if (result.type === "AGG_ARITH") return row[aggregateOperandLabel(result)] ?? "";
|
|
8242
8443
|
if (result.type === "FIELD_REF") {
|
|
8243
8444
|
return row[result.field] ?? "";
|
|
8244
8445
|
}
|
|
@@ -8504,6 +8705,10 @@ function collectAggregateArgFields2(node, out) {
|
|
|
8504
8705
|
}
|
|
8505
8706
|
function collectCaseResultFields(result, out) {
|
|
8506
8707
|
if (result.type === "ARRAY") return;
|
|
8708
|
+
if (result.type === "AGG_REF" || result.type === "AGG_ARITH") {
|
|
8709
|
+
collectAggOperandFields2(result, out);
|
|
8710
|
+
return;
|
|
8711
|
+
}
|
|
8507
8712
|
if (result.type === "FIELD_REF" || result.type === "ARITH") {
|
|
8508
8713
|
collectArithNode2(result, out);
|
|
8509
8714
|
return;
|
|
@@ -8725,6 +8930,9 @@ function evalCaseResultValue(result, row, fieldType) {
|
|
|
8725
8930
|
if (result.type === "ARRAY") {
|
|
8726
8931
|
return convertArray(result.elements.map((e) => e.value), fieldType);
|
|
8727
8932
|
}
|
|
8933
|
+
if (result.type === "AGG_REF" || result.type === "AGG_ARITH") {
|
|
8934
|
+
throw new Error("InternalError: aggregate CASE result reached DML evaluation.");
|
|
8935
|
+
}
|
|
8728
8936
|
if (result.type === "STRING") {
|
|
8729
8937
|
return convertString2(result.value, fieldType);
|
|
8730
8938
|
}
|
|
@@ -10994,7 +11202,7 @@ function valueNeedsFieldMetadata(value) {
|
|
|
10994
11202
|
return Object.values(item).some(valueNeedsFieldMetadata);
|
|
10995
11203
|
}
|
|
10996
11204
|
function selectNeedsOwnMetadata(statement) {
|
|
10997
|
-
return whereNeedsFieldMetadata(statement.where) || normalizeGroupingSpec(statement).type === "GROUPING_SETS" || statement.orderBy.length > 0 || statement.columns.some(
|
|
11205
|
+
return whereNeedsFieldMetadata(statement.where) || statement.groupBy.length > 0 || normalizeGroupingSpec(statement).type === "GROUPING_SETS" || statement.orderBy.length > 0 || statement.columns.some(
|
|
10998
11206
|
(column) => column.type === "WINDOW_COL" && column.orderBy.length > 0
|
|
10999
11207
|
);
|
|
11000
11208
|
}
|
|
@@ -12913,7 +13121,7 @@ function applyFilter(rows, where, resolveFieldType, appliedKlikes, resolveFieldS
|
|
|
12913
13121
|
}
|
|
12914
13122
|
function hasAggregateColumns(columns) {
|
|
12915
13123
|
return columns.some(
|
|
12916
|
-
(c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(c.expr) || c.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate2(c.expr)
|
|
13124
|
+
(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)
|
|
12917
13125
|
);
|
|
12918
13126
|
}
|
|
12919
13127
|
function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind, resolutionPlan, aliasEvaluationContext = {}) {
|
|
@@ -13018,26 +13226,72 @@ function groupingItemValue(item, row) {
|
|
|
13018
13226
|
return row[item.directKey] ?? (item.unqualifiedBridgeKey === null ? void 0 : row[item.unqualifiedBridgeKey]) ?? "";
|
|
13019
13227
|
}
|
|
13020
13228
|
function materializeAggregateColumns(outRow, groupRows, columns, resolveAggSortKind) {
|
|
13021
|
-
for (const col of columns) {
|
|
13229
|
+
for (const [columnIndex, col] of columns.entries()) {
|
|
13022
13230
|
if (col.type === "AGGREGATE") {
|
|
13023
13231
|
const syntheticKey = aggregateSyntheticName(col.func, col.distinct, col.arg);
|
|
13024
13232
|
const value = String(evalAggregate(col.func, col.distinct, col.arg, col.separator, groupRows, resolveAggSortKind));
|
|
13025
13233
|
outRow[col.alias ?? syntheticKey] = value;
|
|
13026
13234
|
if (col.alias) outRow[syntheticKey] = value;
|
|
13027
13235
|
} else if (col.type === "ARITH_AGG_COL") {
|
|
13236
|
+
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
13028
13237
|
const outputKey = col.alias ?? aggArithDefaultKey(col.expr);
|
|
13029
13238
|
outRow[outputKey] = String(evalAggArithExpr(col.expr, groupRows, resolveAggSortKind));
|
|
13030
13239
|
} else if (col.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(col.expr)) {
|
|
13240
|
+
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
13031
13241
|
const outputKey = col.alias ?? stringFuncDefaultKey(col.expr);
|
|
13032
13242
|
const resolvedExpr = resolveAggInStringFuncExpr(col.expr, groupRows, resolveAggSortKind);
|
|
13033
13243
|
outRow[outputKey] = evalStringFunc(resolvedExpr, outRow);
|
|
13034
13244
|
} else if (col.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate2(col.expr)) {
|
|
13245
|
+
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
13035
13246
|
const outputKey = col.alias ?? scalarValueDefaultKey(col.expr);
|
|
13036
13247
|
const resolvedExpr = resolveAggInScalarValue(col.expr, groupRows, resolveAggSortKind);
|
|
13037
13248
|
outRow[outputKey] = String(evalScalarValueExpr(resolvedExpr, outRow));
|
|
13249
|
+
} else if (col.type === "CASE_COL" && containsAggregate2(col.expr)) {
|
|
13250
|
+
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
13251
|
+
const resolvedExpr = resolveAggInCaseExpr(col.expr, groupRows, resolveAggSortKind);
|
|
13252
|
+
const resolveAggregateSemantics = (field) => field.aggregateRef ? aggregateResultSemantics(field.aggregateRef, resolveAggSortKind) : void 0;
|
|
13253
|
+
outRow[caseMaterializedKey(col.alias, columnIndex)] = evalCaseWhen(
|
|
13254
|
+
resolvedExpr,
|
|
13255
|
+
outRow,
|
|
13256
|
+
void 0,
|
|
13257
|
+
resolveAggregateSemantics
|
|
13258
|
+
);
|
|
13038
13259
|
}
|
|
13039
13260
|
}
|
|
13040
13261
|
}
|
|
13262
|
+
function caseMaterializedKey(alias, columnIndex) {
|
|
13263
|
+
return alias ?? `__ksql_case_column_${columnIndex}`;
|
|
13264
|
+
}
|
|
13265
|
+
function collectAggregateRefs(node, out) {
|
|
13266
|
+
if (node === null || typeof node !== "object") return;
|
|
13267
|
+
if (Array.isArray(node)) {
|
|
13268
|
+
node.forEach((value2) => collectAggregateRefs(value2, out));
|
|
13269
|
+
return;
|
|
13270
|
+
}
|
|
13271
|
+
const value = node;
|
|
13272
|
+
if (value["type"] === "AGG_REF") {
|
|
13273
|
+
out.push(value);
|
|
13274
|
+
return;
|
|
13275
|
+
}
|
|
13276
|
+
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
|
|
13277
|
+
Object.values(value).forEach((child) => collectAggregateRefs(child, out));
|
|
13278
|
+
}
|
|
13279
|
+
function materializeAggregateDependencies(outRow, rows, node, resolveAggSortKind) {
|
|
13280
|
+
const refs = [];
|
|
13281
|
+
collectAggregateRefs(node, refs);
|
|
13282
|
+
for (const ref of refs) {
|
|
13283
|
+
const key = aggregateSyntheticName(ref.func, ref.distinct, ref.arg);
|
|
13284
|
+
if (outRow[key] !== void 0) continue;
|
|
13285
|
+
outRow[key] = String(evalAggregate(
|
|
13286
|
+
ref.func,
|
|
13287
|
+
ref.distinct,
|
|
13288
|
+
ref.arg,
|
|
13289
|
+
ref.separator,
|
|
13290
|
+
rows,
|
|
13291
|
+
resolveAggSortKind
|
|
13292
|
+
));
|
|
13293
|
+
}
|
|
13294
|
+
}
|
|
13041
13295
|
function evalGroupByKey(key, row, resolution, columns, aliasEvaluationContext) {
|
|
13042
13296
|
if (key.type === "FIELD_NAME") {
|
|
13043
13297
|
if (!resolution) return row[key.name] ?? "";
|
|
@@ -13071,26 +13325,7 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
|
|
|
13071
13325
|
if (arg.type === "WILDCARD") {
|
|
13072
13326
|
return func === "COUNT" ? rows.length : 0;
|
|
13073
13327
|
}
|
|
13074
|
-
const strValues =
|
|
13075
|
-
for (const row of rows) {
|
|
13076
|
-
let strVal;
|
|
13077
|
-
if (arg.type === "FIELD_REF") {
|
|
13078
|
-
const raw = row[arg.field];
|
|
13079
|
-
if (raw === void 0 || raw === "" && func !== "MIN" && func !== "MAX") continue;
|
|
13080
|
-
strVal = raw;
|
|
13081
|
-
} else if (arg.type === "ARITH" || arg.type === "NUMBER" || arg.type === "STRING_FUNC") {
|
|
13082
|
-
const n = evalArithExpr(arg, row);
|
|
13083
|
-
if (isNaN(n)) continue;
|
|
13084
|
-
strVal = String(n);
|
|
13085
|
-
} else {
|
|
13086
|
-
const value = evalScalarValueExprNullable(arg, row);
|
|
13087
|
-
if (value === null) continue;
|
|
13088
|
-
if (value === "" && func !== "MIN" && func !== "MAX") continue;
|
|
13089
|
-
if (typeof value === "number" && Number.isNaN(value)) continue;
|
|
13090
|
-
strVal = String(value);
|
|
13091
|
-
}
|
|
13092
|
-
strValues.push(strVal);
|
|
13093
|
-
}
|
|
13328
|
+
const strValues = aggregateRowValues(func, arg, rows).filter((value) => value !== null);
|
|
13094
13329
|
const statistical = func === "STDDEV_POP" || func === "STDDEV_SAMP" || func === "VAR_POP" || func === "VAR_SAMP" || func === "MEDIAN";
|
|
13095
13330
|
const numericValues = statistical ? strValues.map((value) => {
|
|
13096
13331
|
const numeric = Number(value);
|
|
@@ -13168,6 +13403,27 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
|
|
|
13168
13403
|
}
|
|
13169
13404
|
}
|
|
13170
13405
|
}
|
|
13406
|
+
function aggregateRowValues(func, arg, rows) {
|
|
13407
|
+
return rows.map((row) => {
|
|
13408
|
+
let strVal;
|
|
13409
|
+
if (arg.type === "FIELD_REF") {
|
|
13410
|
+
const raw = row[arg.field];
|
|
13411
|
+
if (raw === void 0 || raw === "" && func !== "MIN" && func !== "MAX") return null;
|
|
13412
|
+
strVal = raw;
|
|
13413
|
+
} else if (arg.type === "ARITH" || arg.type === "NUMBER") {
|
|
13414
|
+
const n = evalArithExpr(arg, row);
|
|
13415
|
+
if (isNaN(n)) return null;
|
|
13416
|
+
strVal = String(n);
|
|
13417
|
+
} else {
|
|
13418
|
+
const value = evalScalarValueExprNullable(arg, row);
|
|
13419
|
+
if (value === null) return null;
|
|
13420
|
+
if (value === "" && func !== "MIN" && func !== "MAX") return null;
|
|
13421
|
+
if (typeof value === "number" && Number.isNaN(value)) return null;
|
|
13422
|
+
strVal = String(value);
|
|
13423
|
+
}
|
|
13424
|
+
return strVal;
|
|
13425
|
+
});
|
|
13426
|
+
}
|
|
13171
13427
|
function toAggregateFieldRef(field) {
|
|
13172
13428
|
const dot = field.indexOf(".");
|
|
13173
13429
|
return dot > 0 ? { type: "FIELD", tableAlias: field.slice(0, dot), field: field.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field };
|
|
@@ -13210,6 +13466,16 @@ function resolveAggregateArgSemantics(arg, resolver) {
|
|
|
13210
13466
|
const first = results[0];
|
|
13211
13467
|
return results.every((result) => JSON.stringify(result) === JSON.stringify(first)) ? first : kinds[0];
|
|
13212
13468
|
}
|
|
13469
|
+
function aggregateResultSemantics(ref, resolver) {
|
|
13470
|
+
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") {
|
|
13471
|
+
return syntheticSemantics("number");
|
|
13472
|
+
}
|
|
13473
|
+
if (ref.func === "GROUP_CONCAT" || ref.func === "MODE") {
|
|
13474
|
+
return syntheticSemantics("string");
|
|
13475
|
+
}
|
|
13476
|
+
const semantics = ref.arg.type === "WILDCARD" ? "string" : resolveAggregateArgSemantics(ref.arg, resolver) ?? "string";
|
|
13477
|
+
return typeof semantics === "string" ? syntheticSemantics(semantics) : semantics;
|
|
13478
|
+
}
|
|
13213
13479
|
function applyHaving(rows, having, resolveFieldType, resolveFieldSemantics2) {
|
|
13214
13480
|
if (having === null) return rows;
|
|
13215
13481
|
return rows.filter((row) => evalWhere(having, row, resolveFieldType, void 0, resolveFieldSemantics2));
|
|
@@ -13369,7 +13635,7 @@ function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, reso
|
|
|
13369
13635
|
break;
|
|
13370
13636
|
}
|
|
13371
13637
|
case "CASE_COL":
|
|
13372
|
-
evaluators.set(alias, (row) => evalCaseWhen(column.expr, row, resolveFieldType, resolveFieldSemantics2));
|
|
13638
|
+
evaluators.set(alias, (row) => containsAggregate2(column.expr) ? row[alias] ?? "" : evalCaseWhen(column.expr, row, resolveFieldType, resolveFieldSemantics2));
|
|
13373
13639
|
break;
|
|
13374
13640
|
case "SCALAR_VALUE_COL": {
|
|
13375
13641
|
const source = scalarValueDefaultKey(column.expr);
|
|
@@ -13388,7 +13654,7 @@ function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, reso
|
|
|
13388
13654
|
}
|
|
13389
13655
|
return (name, row) => evaluators.get(name)?.(row);
|
|
13390
13656
|
}
|
|
13391
|
-
function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2) {
|
|
13657
|
+
function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2, resolveAggSortKind) {
|
|
13392
13658
|
const windows = columns.filter((column) => column.type === "WINDOW_COL");
|
|
13393
13659
|
if (rows.length === 0 || windows.length === 0) return rows;
|
|
13394
13660
|
for (const window of windows) {
|
|
@@ -13402,6 +13668,10 @@ function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2) {
|
|
|
13402
13668
|
for (const partition of partitions.values()) {
|
|
13403
13669
|
const sortedResult = sortDecoratedRows(partition, window.orderBy, optionOrders, sortKinds, fieldSemantics2);
|
|
13404
13670
|
const sorted = sortedResult.rows;
|
|
13671
|
+
if (!isRankingWindow(window)) {
|
|
13672
|
+
applyAggregateWindow(window, sortedResult, resolveAggSortKind);
|
|
13673
|
+
continue;
|
|
13674
|
+
}
|
|
13405
13675
|
let rank = 1;
|
|
13406
13676
|
let denseRank = 1;
|
|
13407
13677
|
for (let index = 0; index < sorted.length; index++) {
|
|
@@ -13416,6 +13686,53 @@ function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2) {
|
|
|
13416
13686
|
}
|
|
13417
13687
|
return rows;
|
|
13418
13688
|
}
|
|
13689
|
+
function applyAggregateWindow(window, sortedResult, resolveAggSortKind) {
|
|
13690
|
+
const sorted = sortedResult.rows;
|
|
13691
|
+
const values = window.arg.type === "WILDCARD" ? null : aggregateRowValues(window.aggFunc, window.arg, sorted.map((item) => item.row));
|
|
13692
|
+
const comparison = window.arg.type === "WILDCARD" ? void 0 : resolveAggregateArgSemantics(window.arg, resolveAggSortKind);
|
|
13693
|
+
const semantics = typeof comparison === "string" ? syntheticSemantics(comparison) : comparison ?? syntheticSemantics("string");
|
|
13694
|
+
const output = [];
|
|
13695
|
+
let count = 0;
|
|
13696
|
+
let sum = 0;
|
|
13697
|
+
let best;
|
|
13698
|
+
for (let index = 0; index < sorted.length; index++) {
|
|
13699
|
+
const value = values?.[index] ?? null;
|
|
13700
|
+
if (window.arg.type === "WILDCARD") {
|
|
13701
|
+
count++;
|
|
13702
|
+
} else if (value !== null) {
|
|
13703
|
+
if (window.aggFunc === "COUNT") {
|
|
13704
|
+
count++;
|
|
13705
|
+
} else if (window.aggFunc === "SUM" || window.aggFunc === "AVG") {
|
|
13706
|
+
sum += Number(value);
|
|
13707
|
+
count++;
|
|
13708
|
+
} else if (best === void 0) {
|
|
13709
|
+
best = value;
|
|
13710
|
+
} else {
|
|
13711
|
+
const cmp = compareCanonicalValues(value, best, semantics);
|
|
13712
|
+
if (window.aggFunc === "MAX" && cmp > 0 || window.aggFunc === "MIN" && cmp < 0) {
|
|
13713
|
+
best = value;
|
|
13714
|
+
}
|
|
13715
|
+
}
|
|
13716
|
+
}
|
|
13717
|
+
const result = window.aggFunc === "COUNT" ? count : window.aggFunc === "SUM" ? sum : window.aggFunc === "AVG" ? count === 0 ? 0 : sum / count : best ?? 0;
|
|
13718
|
+
output.push(String(result));
|
|
13719
|
+
}
|
|
13720
|
+
if (window.frame === null) {
|
|
13721
|
+
const finalValue = output[output.length - 1];
|
|
13722
|
+
for (const item of sorted) item.row[window.alias] = finalValue;
|
|
13723
|
+
return;
|
|
13724
|
+
}
|
|
13725
|
+
if (window.frame.unit === "RANGE") {
|
|
13726
|
+
for (let start = 0; start < sorted.length; ) {
|
|
13727
|
+
let end = start;
|
|
13728
|
+
while (end + 1 < sorted.length && sortedResult.compare(sorted[end], sorted[end + 1]) === 0) end++;
|
|
13729
|
+
for (let index = start; index <= end; index++) sorted[index].row[window.alias] = output[end];
|
|
13730
|
+
start = end + 1;
|
|
13731
|
+
}
|
|
13732
|
+
return;
|
|
13733
|
+
}
|
|
13734
|
+
for (let index = 0; index < sorted.length; index++) sorted[index].row[window.alias] = output[index];
|
|
13735
|
+
}
|
|
13419
13736
|
function resolveWindowField(row, ref) {
|
|
13420
13737
|
const name = ref.tableAlias ? `${ref.tableAlias}.${ref.field}` : ref.field;
|
|
13421
13738
|
return resolveFieldRef(row, name);
|
|
@@ -13458,7 +13775,7 @@ function evaluateSelectColumnValue(column, row, columnIndex, context = {}) {
|
|
|
13458
13775
|
case "ARITH_COL":
|
|
13459
13776
|
return String(evalArithExpr(column.expr, row));
|
|
13460
13777
|
case "CASE_COL":
|
|
13461
|
-
return evalCaseWhen(
|
|
13778
|
+
return containsAggregate2(column.expr) ? row[caseMaterializedKey(column.alias, columnIndex)] ?? "" : evalCaseWhen(
|
|
13462
13779
|
column.expr,
|
|
13463
13780
|
row,
|
|
13464
13781
|
context.resolveFieldType,
|
|
@@ -13523,13 +13840,14 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns2, r
|
|
|
13523
13840
|
return { rows: projected2, columns: cols };
|
|
13524
13841
|
}
|
|
13525
13842
|
const defaultFieldKeys = buildDefaultFieldOutputKeys(columns);
|
|
13843
|
+
const defaultCaseKeys = buildDefaultCaseOutputKeys(columns);
|
|
13526
13844
|
const hasWildcard = columns.some(
|
|
13527
13845
|
(col) => col.type === "WILDCARD" || col.type === "PARENT_WILDCARD"
|
|
13528
13846
|
);
|
|
13529
|
-
const outputKeys = hasWildcard ? null : computeOutputKeys(columns, defaultFieldKeys);
|
|
13847
|
+
const outputKeys = hasWildcard ? null : computeOutputKeys(columns, defaultFieldKeys, defaultCaseKeys);
|
|
13530
13848
|
const orderedKeys = outputKeys ?? [];
|
|
13531
13849
|
if (hasWildcard && rows.length === 0) {
|
|
13532
|
-
return { rows: [], columns: computeExplicitOutputKeys(columns, defaultFieldKeys) };
|
|
13850
|
+
return { rows: [], columns: computeExplicitOutputKeys(columns, defaultFieldKeys, defaultCaseKeys) };
|
|
13533
13851
|
}
|
|
13534
13852
|
const projected = rows.map((row, rowIdx) => {
|
|
13535
13853
|
const out = {};
|
|
@@ -13596,7 +13914,7 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns2, r
|
|
|
13596
13914
|
break;
|
|
13597
13915
|
}
|
|
13598
13916
|
case "CASE_COL": {
|
|
13599
|
-
const key = outputKeys?.[colIdx] ?? col.alias ?? "case";
|
|
13917
|
+
const key = outputKeys?.[colIdx] ?? col.alias ?? defaultCaseKeys.get(colIdx) ?? "case";
|
|
13600
13918
|
out[key] = value;
|
|
13601
13919
|
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
13602
13920
|
break;
|
|
@@ -13637,15 +13955,15 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns2, r
|
|
|
13637
13955
|
});
|
|
13638
13956
|
return { rows: projected, columns: orderedKeys };
|
|
13639
13957
|
}
|
|
13640
|
-
function computeOutputKeys(columns, defaultFieldKeys) {
|
|
13641
|
-
return columns.map((col, colIdx) => computeOutputKey(col, colIdx, defaultFieldKeys));
|
|
13958
|
+
function computeOutputKeys(columns, defaultFieldKeys, defaultCaseKeys) {
|
|
13959
|
+
return columns.map((col, colIdx) => computeOutputKey(col, colIdx, defaultFieldKeys, defaultCaseKeys));
|
|
13642
13960
|
}
|
|
13643
|
-
function computeExplicitOutputKeys(columns, defaultFieldKeys) {
|
|
13961
|
+
function computeExplicitOutputKeys(columns, defaultFieldKeys, defaultCaseKeys) {
|
|
13644
13962
|
const keys = [];
|
|
13645
13963
|
const seen = /* @__PURE__ */ new Set();
|
|
13646
13964
|
for (const [colIdx, col] of columns.entries()) {
|
|
13647
13965
|
if (col.type === "WILDCARD" || col.type === "PARENT_WILDCARD") continue;
|
|
13648
|
-
const key = computeOutputKey(col, colIdx, defaultFieldKeys);
|
|
13966
|
+
const key = computeOutputKey(col, colIdx, defaultFieldKeys, defaultCaseKeys);
|
|
13649
13967
|
if (!seen.has(key)) {
|
|
13650
13968
|
seen.add(key);
|
|
13651
13969
|
keys.push(key);
|
|
@@ -13653,7 +13971,7 @@ function computeExplicitOutputKeys(columns, defaultFieldKeys) {
|
|
|
13653
13971
|
}
|
|
13654
13972
|
return keys;
|
|
13655
13973
|
}
|
|
13656
|
-
function computeOutputKey(col, colIdx, defaultFieldKeys) {
|
|
13974
|
+
function computeOutputKey(col, colIdx, defaultFieldKeys, defaultCaseKeys) {
|
|
13657
13975
|
switch (col.type) {
|
|
13658
13976
|
case "VARIABLE_COL":
|
|
13659
13977
|
throw new Error(`internal error: unresolved SELECT variable @${col.name}`);
|
|
@@ -13668,7 +13986,7 @@ function computeOutputKey(col, colIdx, defaultFieldKeys) {
|
|
|
13668
13986
|
case "ARITH_COL":
|
|
13669
13987
|
return col.alias ?? arithColDefaultKey(col.expr);
|
|
13670
13988
|
case "CASE_COL":
|
|
13671
|
-
return col.alias ?? "case";
|
|
13989
|
+
return col.alias ?? defaultCaseKeys.get(colIdx) ?? "case";
|
|
13672
13990
|
case "STRFUNC_COL":
|
|
13673
13991
|
return col.alias ?? stringFuncDefaultKey(col.expr);
|
|
13674
13992
|
case "SCALAR_VALUE_COL":
|
|
@@ -13684,6 +14002,24 @@ function computeOutputKey(col, colIdx, defaultFieldKeys) {
|
|
|
13684
14002
|
throw new Error("internal: computeOutputKey received a wildcard column");
|
|
13685
14003
|
}
|
|
13686
14004
|
}
|
|
14005
|
+
function buildDefaultCaseOutputKeys(columns) {
|
|
14006
|
+
const used = new Set(columns.flatMap(
|
|
14007
|
+
(column) => "alias" in column && column.alias !== null ? [column.alias] : []
|
|
14008
|
+
));
|
|
14009
|
+
const keys = /* @__PURE__ */ new Map();
|
|
14010
|
+
let suffix = 1;
|
|
14011
|
+
for (const [columnIndex, column] of columns.entries()) {
|
|
14012
|
+
if (column.type !== "CASE_COL" || column.alias !== null) continue;
|
|
14013
|
+
let key;
|
|
14014
|
+
do {
|
|
14015
|
+
key = suffix === 1 ? "case" : `case_${suffix}`;
|
|
14016
|
+
suffix++;
|
|
14017
|
+
} while (used.has(key));
|
|
14018
|
+
used.add(key);
|
|
14019
|
+
keys.set(columnIndex, key);
|
|
14020
|
+
}
|
|
14021
|
+
return keys;
|
|
14022
|
+
}
|
|
13687
14023
|
function buildDefaultFieldOutputKeys(columns) {
|
|
13688
14024
|
const qualifierCollisionCount = /* @__PURE__ */ new Map();
|
|
13689
14025
|
for (const col of columns) {
|
|
@@ -13773,6 +14109,7 @@ function scalarValueHasAggregate2(expr) {
|
|
|
13773
14109
|
return false;
|
|
13774
14110
|
}
|
|
13775
14111
|
function caseResultHasAggregate2(result) {
|
|
14112
|
+
if (result.type === "AGG_REF" || result.type === "AGG_ARITH") return true;
|
|
13776
14113
|
if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return false;
|
|
13777
14114
|
return scalarValueHasAggregate2(result);
|
|
13778
14115
|
}
|
|
@@ -13795,6 +14132,7 @@ function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
|
|
|
13795
14132
|
}
|
|
13796
14133
|
function resolveAggInScalarValue(expr, rows, resolveAggSortKind) {
|
|
13797
14134
|
if (expr.type === "STRING_FUNC") return resolveAggInStringFuncExpr(expr, rows, resolveAggSortKind);
|
|
14135
|
+
if (expr.type === "CASE_WHEN") return resolveAggInCaseExpr(expr, rows, resolveAggSortKind);
|
|
13798
14136
|
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
13799
14137
|
return {
|
|
13800
14138
|
...expr,
|
|
@@ -13804,6 +14142,35 @@ function resolveAggInScalarValue(expr, rows, resolveAggSortKind) {
|
|
|
13804
14142
|
}
|
|
13805
14143
|
return expr;
|
|
13806
14144
|
}
|
|
14145
|
+
function resolveAggInCaseResult(result, rows, resolveAggSortKind) {
|
|
14146
|
+
if (result.type === "AGG_REF") {
|
|
14147
|
+
const value = evalAggregate(
|
|
14148
|
+
result.func,
|
|
14149
|
+
result.distinct,
|
|
14150
|
+
result.arg,
|
|
14151
|
+
result.separator,
|
|
14152
|
+
rows,
|
|
14153
|
+
resolveAggSortKind
|
|
14154
|
+
);
|
|
14155
|
+
return typeof value === "number" ? { type: "NUMBER", value, raw: String(value) } : { type: "STRING", value };
|
|
14156
|
+
}
|
|
14157
|
+
if (result.type === "AGG_ARITH") {
|
|
14158
|
+
const value = evalAggArithExpr(result, rows, resolveAggSortKind);
|
|
14159
|
+
return { type: "NUMBER", value, raw: String(value) };
|
|
14160
|
+
}
|
|
14161
|
+
if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return result;
|
|
14162
|
+
return resolveAggInScalarValue(result, rows, resolveAggSortKind);
|
|
14163
|
+
}
|
|
14164
|
+
function resolveAggInCaseExpr(expr, rows, resolveAggSortKind) {
|
|
14165
|
+
return {
|
|
14166
|
+
...expr,
|
|
14167
|
+
branches: expr.branches.map((branch) => ({
|
|
14168
|
+
...branch,
|
|
14169
|
+
result: resolveAggInCaseResult(branch.result, rows, resolveAggSortKind)
|
|
14170
|
+
})),
|
|
14171
|
+
elseResult: expr.elseResult === null ? null : resolveAggInCaseResult(expr.elseResult, rows, resolveAggSortKind)
|
|
14172
|
+
};
|
|
14173
|
+
}
|
|
13807
14174
|
function resolveAggInStringFuncExpr(expr, rows, resolveAggSortKind) {
|
|
13808
14175
|
return {
|
|
13809
14176
|
type: "STRING_FUNC",
|
|
@@ -13832,12 +14199,19 @@ function mergeKnownColumns(left, right, rows) {
|
|
|
13832
14199
|
...Object.keys(rows[0] ?? {})
|
|
13833
14200
|
])];
|
|
13834
14201
|
}
|
|
13835
|
-
function deriveOutputOrderSemantics(columns) {
|
|
14202
|
+
function deriveOutputOrderSemantics(columns, resolveAggSortKind) {
|
|
13836
14203
|
const result = /* @__PURE__ */ new Map();
|
|
13837
14204
|
for (const column of columns) {
|
|
13838
14205
|
if (!("alias" in column) || !column.alias) continue;
|
|
13839
|
-
if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL"
|
|
14206
|
+
if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL") {
|
|
13840
14207
|
result.set(column.alias, syntheticSemantics("number"));
|
|
14208
|
+
} else if (column.type === "WINDOW_COL") {
|
|
14209
|
+
if (isRankingWindow(column) || column.aggFunc === "COUNT" || column.aggFunc === "SUM" || column.aggFunc === "AVG") {
|
|
14210
|
+
result.set(column.alias, syntheticSemantics("number"));
|
|
14211
|
+
} else if (column.arg.type !== "WILDCARD") {
|
|
14212
|
+
const semantics = resolveAggregateArgSemantics(column.arg, resolveAggSortKind) ?? "string";
|
|
14213
|
+
result.set(column.alias, typeof semantics === "string" ? syntheticSemantics(semantics) : semantics);
|
|
14214
|
+
}
|
|
13841
14215
|
} else if (column.type === "AGGREGATE") {
|
|
13842
14216
|
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") {
|
|
13843
14217
|
result.set(column.alias, syntheticSemantics("number"));
|
|
@@ -13872,7 +14246,7 @@ function runFullScan(input) {
|
|
|
13872
14246
|
resolvedGroupingSpec,
|
|
13873
14247
|
plainGroupByPlan
|
|
13874
14248
|
} = input;
|
|
13875
|
-
const effectiveOrderSemantics = deriveOutputOrderSemantics(stmt.columns);
|
|
14249
|
+
const effectiveOrderSemantics = deriveOutputOrderSemantics(stmt.columns, aggregateSortKindResolver);
|
|
13876
14250
|
for (const [key, value] of orderSemantics ?? []) effectiveOrderSemantics.set(key, value);
|
|
13877
14251
|
let rows = [];
|
|
13878
14252
|
const mainAlias = stmt.from.alias;
|
|
@@ -13926,8 +14300,16 @@ function runFullScan(input) {
|
|
|
13926
14300
|
}
|
|
13927
14301
|
);
|
|
13928
14302
|
}
|
|
13929
|
-
|
|
13930
|
-
rows =
|
|
14303
|
+
const resolveHavingSemantics = (field) => field.aggregateRef ? aggregateResultSemantics(field.aggregateRef, aggregateSortKindResolver) : havingFieldSemanticsResolver?.(field);
|
|
14304
|
+
rows = applyHaving(rows, stmt.having, havingFieldTypeResolver, resolveHavingSemantics);
|
|
14305
|
+
rows = applyWindow(
|
|
14306
|
+
rows,
|
|
14307
|
+
stmt.columns,
|
|
14308
|
+
optionOrders,
|
|
14309
|
+
sortKinds,
|
|
14310
|
+
effectiveOrderSemantics,
|
|
14311
|
+
aggregateSortKindResolver
|
|
14312
|
+
);
|
|
13931
14313
|
if (stmt.distinct) {
|
|
13932
14314
|
rows = applyDistinct(
|
|
13933
14315
|
rows,
|
|
@@ -16412,8 +16794,8 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
16412
16794
|
tempTables
|
|
16413
16795
|
);
|
|
16414
16796
|
const first = resolvedStmt2.expr.query.columns[0];
|
|
16415
|
-
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");
|
|
16416
|
-
if (first?.type === "AGGREGATE" && first.func === "MODE") {
|
|
16797
|
+
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");
|
|
16798
|
+
if (first?.type === "AGGREGATE" && first.func === "MODE" || first?.type === "WINDOW_COL" && first.windowKind === "AGGREGATE" && (first.aggFunc === "MIN" || first.aggFunc === "MAX")) {
|
|
16417
16799
|
const meta = (await inferSelectColumnMeta(
|
|
16418
16800
|
resolvedStmt2.expr.query,
|
|
16419
16801
|
["__scalar__"],
|
|
@@ -17039,8 +17421,21 @@ function buildHavingFieldSemanticsResolver(stmt, rowResolver) {
|
|
|
17039
17421
|
if (!("alias" in column) || !column.alias) continue;
|
|
17040
17422
|
let semantics;
|
|
17041
17423
|
if (column.type === "FIELD") semantics = rowResolver(aggregateFieldRef(column.field));
|
|
17042
|
-
else if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL"
|
|
17424
|
+
else if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL") {
|
|
17043
17425
|
semantics = syntheticSemantics("number");
|
|
17426
|
+
} else if (column.type === "WINDOW_COL") {
|
|
17427
|
+
if (column.windowKind !== "AGGREGATE" || column.aggFunc === "COUNT" || column.aggFunc === "SUM" || column.aggFunc === "AVG") {
|
|
17428
|
+
semantics = syntheticSemantics("number");
|
|
17429
|
+
} else if (column.arg.type !== "WILDCARD") {
|
|
17430
|
+
semantics = inferAggregateArgMeta(column.arg, (ref) => {
|
|
17431
|
+
const resolved = rowResolver(ref);
|
|
17432
|
+
return resolved ? {
|
|
17433
|
+
sortKind: resolved.compareMode === "number" || resolved.compareMode === "recordNumber" ? "number" : "string",
|
|
17434
|
+
fieldType: resolved.fieldType,
|
|
17435
|
+
semantics: resolved
|
|
17436
|
+
} : void 0;
|
|
17437
|
+
}).semantics;
|
|
17438
|
+
}
|
|
17044
17439
|
} else if (column.type === "AGGREGATE") {
|
|
17045
17440
|
if (column.func === "MIN" || column.func === "MAX" || column.func === "MODE") {
|
|
17046
17441
|
if (column.arg.type !== "WILDCARD") {
|
|
@@ -17402,6 +17797,7 @@ async function validateSelectGroupingPlanning(stmt, client, cacheContext, materi
|
|
|
17402
17797
|
function completeInputErrorPrefix(reasons) {
|
|
17403
17798
|
const reasonList = [...reasons].join(", ");
|
|
17404
17799
|
const aggregateSubjects = [
|
|
17800
|
+
["AGGREGATE_WINDOW", "\u96C6\u8A08\u30A6\u30A3\u30F3\u30C9\u30A6\u306E\u6B63\u3057\u3044\u7D50\u679C"],
|
|
17405
17801
|
["GROUPING_SETS", "\u5C0F\u8A08\u30FB\u7DCF\u8A08\u306E\u6B63\u3057\u3044\u7D50\u679C"],
|
|
17406
17802
|
["STATISTICAL_AGGREGATE", "\u7D71\u8A08\u96C6\u7D04\u306E\u6B63\u3057\u3044\u7D50\u679C"],
|
|
17407
17803
|
["AGGREGATE", "\u96C6\u8A08\u306E\u6B63\u3057\u3044\u7D50\u679C"],
|
|
@@ -17468,7 +17864,7 @@ function scalarValueHasFieldRef(expr) {
|
|
|
17468
17864
|
}
|
|
17469
17865
|
if (expr.type === "CASE_WHEN") {
|
|
17470
17866
|
const results = [...expr.branches.map((branch) => branch.result), ...expr.elseResult ? [expr.elseResult] : []];
|
|
17471
|
-
return results.some((result) => result.type !== "ARRAY" && (result.type === "FIELD_REF" || result.type === "ARITH" ? arithHasFieldRef(result) : scalarValueHasFieldRef(result)));
|
|
17867
|
+
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)));
|
|
17472
17868
|
}
|
|
17473
17869
|
return false;
|
|
17474
17870
|
}
|
|
@@ -18020,7 +18416,8 @@ function collectAggregateArgFieldRefs(arg, out) {
|
|
|
18020
18416
|
}
|
|
18021
18417
|
if (arg.type === "CASE_WHEN") {
|
|
18022
18418
|
for (const result of [...arg.branches.map((branch) => branch.result), ...arg.elseResult ? [arg.elseResult] : []]) {
|
|
18023
|
-
if (result.type
|
|
18419
|
+
if (result.type === "AGG_REF" || result.type === "AGG_ARITH") collectAggregateOperandRefs(result, out);
|
|
18420
|
+
else if (result.type !== "ARRAY") collectAggregateArgFieldRefs(result, out);
|
|
18024
18421
|
}
|
|
18025
18422
|
}
|
|
18026
18423
|
}
|
|
@@ -18057,10 +18454,29 @@ function collectScalarAggregateRefs(expr, out) {
|
|
|
18057
18454
|
const results = [...expr.branches.map((branch) => branch.result), ...expr.elseResult ? [expr.elseResult] : []];
|
|
18058
18455
|
for (const result of results) {
|
|
18059
18456
|
if (result.type === "STRING_FUNC") collectStringFuncAggregateRefs(result, out);
|
|
18457
|
+
else if (result.type === "AGG_REF" || result.type === "AGG_ARITH") collectAggregateOperandRefs(result, out);
|
|
18060
18458
|
else if (result.type !== "ARRAY" && result.type !== "FIELD_REF" && result.type !== "ARITH") collectScalarAggregateRefs(result, out);
|
|
18061
18459
|
}
|
|
18062
18460
|
}
|
|
18063
18461
|
}
|
|
18462
|
+
function collectCaseAggregateRefs(expr, out) {
|
|
18463
|
+
const visit = (node) => {
|
|
18464
|
+
if (node === null || typeof node !== "object") return;
|
|
18465
|
+
if (Array.isArray(node)) {
|
|
18466
|
+
node.forEach(visit);
|
|
18467
|
+
return;
|
|
18468
|
+
}
|
|
18469
|
+
const value = node;
|
|
18470
|
+
if (value["type"] === "AGG_REF") {
|
|
18471
|
+
const aggregate = value;
|
|
18472
|
+
collectAggregateRef(aggregate.func, aggregate.arg, out);
|
|
18473
|
+
return;
|
|
18474
|
+
}
|
|
18475
|
+
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
|
|
18476
|
+
Object.values(value).forEach(visit);
|
|
18477
|
+
};
|
|
18478
|
+
visit(expr);
|
|
18479
|
+
}
|
|
18064
18480
|
function collectSelectAggregateSortRefs(columns) {
|
|
18065
18481
|
const refs = [];
|
|
18066
18482
|
for (const column of columns) {
|
|
@@ -18072,6 +18488,8 @@ function collectSelectAggregateSortRefs(columns) {
|
|
|
18072
18488
|
collectStringFuncAggregateRefs(column.expr, refs);
|
|
18073
18489
|
} else if (column.type === "SCALAR_VALUE_COL") {
|
|
18074
18490
|
collectScalarAggregateRefs(column.expr, refs);
|
|
18491
|
+
} else if (column.type === "CASE_COL") {
|
|
18492
|
+
collectCaseAggregateRefs(column.expr, refs);
|
|
18075
18493
|
}
|
|
18076
18494
|
}
|
|
18077
18495
|
return refs;
|
|
@@ -18249,6 +18667,13 @@ function stringFunctionColumnMeta(expr) {
|
|
|
18249
18667
|
function caseResultColumnMeta(result, resolveField2) {
|
|
18250
18668
|
if (result.type === "STRING") return syntheticColumnMeta("string");
|
|
18251
18669
|
if (result.type === "ARRAY") return unsupportedColumnMeta();
|
|
18670
|
+
if (result.type === "AGG_REF") {
|
|
18671
|
+
if (result.func === "MIN" || result.func === "MAX" || result.func === "MODE") {
|
|
18672
|
+
return result.arg.type === "WILDCARD" ? unknownStringColumnMeta() : inferAggregateArgMeta(result.arg, resolveField2);
|
|
18673
|
+
}
|
|
18674
|
+
return result.func === "GROUP_CONCAT" ? syntheticColumnMeta("string") : syntheticColumnMeta("number");
|
|
18675
|
+
}
|
|
18676
|
+
if (result.type === "AGG_ARITH") return syntheticColumnMeta("number");
|
|
18252
18677
|
if (result.type === "NUMBER" || result.type === "ARITH" || result.type === "SCALAR_ARITH") return syntheticColumnMeta("number");
|
|
18253
18678
|
if (result.type === "STRING_FUNC") return stringFunctionColumnMeta(result);
|
|
18254
18679
|
if (result.type === "FIELD_REF") return resolveField2(aggregateFieldRef(result.field)) ?? unknownStringColumnMeta();
|
|
@@ -18286,12 +18711,18 @@ function inferAggregateArgMeta(arg, resolveField2) {
|
|
|
18286
18711
|
if (arg.elseResult) results.push(caseResultColumnMeta(arg.elseResult, resolveField2));
|
|
18287
18712
|
return mergeExpressionColumnMeta(results);
|
|
18288
18713
|
}
|
|
18714
|
+
function inferWindowColumnMeta(column, resolveField2) {
|
|
18715
|
+
if (column.windowKind !== "AGGREGATE" || column.aggFunc === "COUNT" || column.aggFunc === "SUM" || column.aggFunc === "AVG") {
|
|
18716
|
+
return syntheticColumnMeta("number");
|
|
18717
|
+
}
|
|
18718
|
+
return column.arg.type === "WILDCARD" ? unknownStringColumnMeta() : inferAggregateArgMeta(column.arg, resolveField2);
|
|
18719
|
+
}
|
|
18289
18720
|
function withDisplayName(meta, displayName) {
|
|
18290
18721
|
return { ...meta ?? {}, displayName };
|
|
18291
18722
|
}
|
|
18292
18723
|
function selectNeedsSourceColumnMeta(stmt) {
|
|
18293
18724
|
return stmt.columns.some(
|
|
18294
|
-
(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")
|
|
18725
|
+
(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")
|
|
18295
18726
|
);
|
|
18296
18727
|
}
|
|
18297
18728
|
async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext, materializedTables, forLibraryCapture = false) {
|
|
@@ -18397,7 +18828,7 @@ async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext,
|
|
|
18397
18828
|
} else if (column.type === "STRFUNC_COL") {
|
|
18398
18829
|
meta = stringFunctionColumnMeta(column.expr);
|
|
18399
18830
|
} else if (column.type === "WINDOW_COL") {
|
|
18400
|
-
meta =
|
|
18831
|
+
meta = inferWindowColumnMeta(column, resolveField2);
|
|
18401
18832
|
} else if (column.type === "CASE_COL") {
|
|
18402
18833
|
const results = column.expr.branches.map((branch) => caseResultColumnMeta(branch.result, resolveField2));
|
|
18403
18834
|
if (column.expr.elseResult) results.push(caseResultColumnMeta(column.expr.elseResult, resolveField2));
|
|
@@ -19324,8 +19755,10 @@ async function buildOrderSemanticsForSelect(stmt, client, cacheContext, material
|
|
|
19324
19755
|
if (!("alias" in column) || !column.alias) continue;
|
|
19325
19756
|
let meta;
|
|
19326
19757
|
if (column.type === "FIELD") meta = resolveField2(aggregateFieldRef(column.field));
|
|
19327
|
-
else if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL"
|
|
19758
|
+
else if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL") {
|
|
19328
19759
|
meta = syntheticColumnMeta("number");
|
|
19760
|
+
} else if (column.type === "WINDOW_COL") {
|
|
19761
|
+
meta = inferWindowColumnMeta(column, resolveField2);
|
|
19329
19762
|
} else if (column.type === "GROUPING_COL") {
|
|
19330
19763
|
meta = syntheticColumnMeta("number");
|
|
19331
19764
|
} else if (column.type === "LITERAL_COL" || column.type === "SCALAR_VALUE_COL") meta = syntheticColumnMeta("string");
|
|
@@ -23363,6 +23796,20 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlan
|
|
|
23363
23796
|
}
|
|
23364
23797
|
}
|
|
23365
23798
|
}
|
|
23799
|
+
for (const column of stmt.columns) {
|
|
23800
|
+
if (column.type !== "WINDOW_COL" || column.windowKind !== "AGGREGATE") continue;
|
|
23801
|
+
const clauses = [];
|
|
23802
|
+
if (column.partitionBy.length > 0) {
|
|
23803
|
+
clauses.push(`PARTITION BY ${column.partitionBy.map(
|
|
23804
|
+
(ref) => ref.tableAlias ? `${ref.tableAlias}.${ref.field}` : ref.field
|
|
23805
|
+
).join(", ")}`);
|
|
23806
|
+
}
|
|
23807
|
+
if (column.orderBy.length > 0) {
|
|
23808
|
+
clauses.push(`ORDER BY ${column.orderBy.map(formatOrderByItem).join(", ")}`);
|
|
23809
|
+
}
|
|
23810
|
+
lines.push(` window ${column.alias}: ${column.aggFunc} OVER (${clauses.join(" ")})`);
|
|
23811
|
+
lines.push(column.frame === null ? " frame: PARTITION ENTIRE" : ` frame: ${column.frame.unit} UNBOUNDED PRECEDING AND CURRENT ROW${column.frame.source === "DEFAULT" ? " (\u65E2\u5B9A)" : ""}`);
|
|
23812
|
+
}
|
|
23366
23813
|
if (totalCountPlan) {
|
|
23367
23814
|
const baseQuery = stmt.where === null ? "" : whereToKintone(stmt.where);
|
|
23368
23815
|
lines.push(` app: APP${stmt.from.appId} (${stmt.from.appId})`);
|