@rex0220/kintone-sql-tools 3.45.0 → 3.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cli/ksql.js +382 -45
- package/dist-engine/index.cjs +10 -10
- package/dist-engine/index.mjs +10 -10
- package/dist-engine/ksql-engine.umd.js +9 -9
- package/dist-engine/meta/bundle-baseline.json +7 -7
- package/dist-engine/meta/cjs.json +18 -18
- package/dist-engine/meta/esm.json +18 -18
- package/dist-engine/meta/umd.json +18 -18
- package/dist-mcp/ksql-mcp.js +392 -50
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -752,7 +752,7 @@ function caseLabel(expr) {
|
|
|
752
752
|
}
|
|
753
753
|
function stringFuncArgLabel(arg) {
|
|
754
754
|
if (arg.type === "AGG_REF") return aggregateSyntheticName(arg.func, arg.distinct, arg.arg);
|
|
755
|
-
if (arg.type === "AGG_ARITH") return aggregateOperandLabel(arg);
|
|
755
|
+
if (arg.type === "AGG_ARITH" || arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") return aggregateOperandLabel(arg);
|
|
756
756
|
return scalarValueLabel(arg);
|
|
757
757
|
}
|
|
758
758
|
function stringFuncLabel(expr) {
|
|
@@ -790,6 +790,8 @@ function aggregateSyntheticName(func, distinct, arg) {
|
|
|
790
790
|
function aggregateOperandLabel(node) {
|
|
791
791
|
if (node.type === "NUMBER") return numberLiteralText(node);
|
|
792
792
|
if (node.type === "AGG_REF") return aggregateSyntheticName(node.func, node.distinct, node.arg);
|
|
793
|
+
if (node.type === "AGG_GROUP_KEY") return node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field;
|
|
794
|
+
if (node.type === "VARIABLE") return `@${node.name}`;
|
|
793
795
|
return `${aggregateOperandLabel(node.left)}${node.op}${aggregateOperandLabel(node.right)}`;
|
|
794
796
|
}
|
|
795
797
|
|
|
@@ -1068,6 +1070,8 @@ var Parser = class {
|
|
|
1068
1070
|
this.cteNames = /* @__PURE__ */ new Set();
|
|
1069
1071
|
/** パース中に出現した一時テーブル参照(#name)のトークン。単文 API での拒否に使う */
|
|
1070
1072
|
this.tempTableRefs = [];
|
|
1073
|
+
/** GROUP BY を読む前に作る B124 候補 leaf の診断位置。AST 公開型へ位置情報を足さない。 */
|
|
1074
|
+
this.aggregateGroupKeyTokens = /* @__PURE__ */ new WeakMap();
|
|
1071
1075
|
this.allowSelectArithVariable = false;
|
|
1072
1076
|
}
|
|
1073
1077
|
// ----------------------------------------------------------
|
|
@@ -1879,6 +1883,7 @@ var Parser = class {
|
|
|
1879
1883
|
if (grouping && orderMode === "KINTONE_NATIVE") {
|
|
1880
1884
|
throw new ParseError("B65: KORDER BY cannot be combined with grouping sets in Phase1.", this.peek());
|
|
1881
1885
|
}
|
|
1886
|
+
this.validateAggregateGroupKeyRefs(columns, having, groupBy, grouping);
|
|
1882
1887
|
return {
|
|
1883
1888
|
type: "SELECT",
|
|
1884
1889
|
distinct,
|
|
@@ -1971,6 +1976,12 @@ var Parser = class {
|
|
|
1971
1976
|
this.peek()
|
|
1972
1977
|
);
|
|
1973
1978
|
}
|
|
1979
|
+
if (this.isNonAggregateArithmeticStartWithAggregate()) {
|
|
1980
|
+
throw new ParseError(
|
|
1981
|
+
`\u96C6\u8A08\u7B97\u8853\u5F0F\u306F\u96C6\u8A08\u95A2\u6570\u304B\u3089\u59CB\u307E\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08${this.peek().value}\uFF09\u3002`,
|
|
1982
|
+
this.peek()
|
|
1983
|
+
);
|
|
1984
|
+
}
|
|
1974
1985
|
if (this.tryAggregateFunc() === null && this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
|
|
1975
1986
|
const expr = this.parseScalarValueExpr({ allowAggregateArgs: true });
|
|
1976
1987
|
const parsedAlias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
|
|
@@ -2194,6 +2205,7 @@ var Parser = class {
|
|
|
2194
2205
|
}
|
|
2195
2206
|
stringFuncArgHasAggregate(arg) {
|
|
2196
2207
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
2208
|
+
if (arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") return false;
|
|
2197
2209
|
return this.scalarValueHasAggregate(arg);
|
|
2198
2210
|
}
|
|
2199
2211
|
scalarValueHasAggregate(expr) {
|
|
@@ -2236,7 +2248,7 @@ var Parser = class {
|
|
|
2236
2248
|
parseAggArithMulDiv() {
|
|
2237
2249
|
return this.continueAggArithMulDiv(this.parseAggPrimary());
|
|
2238
2250
|
}
|
|
2239
|
-
/** 集計算術式の一次式: 集計関数 /
|
|
2251
|
+
/** 集計算術式の一次式: 集計関数 / 数値 / 変数 / GROUP BY キー候補 / 括弧 */
|
|
2240
2252
|
parseAggPrimary() {
|
|
2241
2253
|
if (this.consume("(" /* LPAREN */)) {
|
|
2242
2254
|
const inner = this.continueAggArith(this.parseAggPrimary());
|
|
@@ -2253,14 +2265,99 @@ var Parser = class {
|
|
|
2253
2265
|
const tok = this.advance();
|
|
2254
2266
|
return makeNumberLiteral(tok.value);
|
|
2255
2267
|
}
|
|
2268
|
+
if (this.peek().kind === "VARIABLE" /* VARIABLE */) {
|
|
2269
|
+
const tok = this.advance();
|
|
2270
|
+
return { type: "VARIABLE", name: tok.value.slice(1).toLowerCase() };
|
|
2271
|
+
}
|
|
2256
2272
|
const aggFunc = this.tryAggregateFunc();
|
|
2257
2273
|
if (aggFunc !== null) {
|
|
2258
2274
|
const ref = this.parseAggregateRef(aggFunc);
|
|
2259
2275
|
this.rejectAggregateWindowOutsideSelect();
|
|
2260
2276
|
return ref;
|
|
2261
2277
|
}
|
|
2278
|
+
if (this.peek().kind === "IDENT" /* IDENT */ || this.peek().kind === "BIDENT" /* BIDENT */) {
|
|
2279
|
+
const tok = this.peek();
|
|
2280
|
+
const parsed = this.parseQualifiedIdent();
|
|
2281
|
+
const ref = {
|
|
2282
|
+
type: "AGG_GROUP_KEY",
|
|
2283
|
+
field: parsed.field,
|
|
2284
|
+
...parsed.tableAlias ? { tableAlias: parsed.tableAlias } : {}
|
|
2285
|
+
};
|
|
2286
|
+
this.aggregateGroupKeyTokens.set(ref, tok);
|
|
2287
|
+
return ref;
|
|
2288
|
+
}
|
|
2262
2289
|
throw new ParseError("\u96C6\u8A08\u7B97\u8853\u5F0F\u306B\u306F\u96C6\u8A08\u95A2\u6570\u307E\u305F\u306F\u6570\u5024\u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
2263
2290
|
}
|
|
2291
|
+
/** B124 Phase 1 はトップレベルの非集計オペランド開始形を明示拒否する。 */
|
|
2292
|
+
isNonAggregateArithmeticStartWithAggregate() {
|
|
2293
|
+
const first = this.peek();
|
|
2294
|
+
if (this.tryAggregateFunc() !== null || first.kind === "CASE" /* CASE */ || first.kind === "IF" /* IF */) return false;
|
|
2295
|
+
if (this.isGroupingFunctionStart()) return false;
|
|
2296
|
+
if (this.tryStringFuncName() !== null) return false;
|
|
2297
|
+
if (!["IDENT" /* IDENT */, "BIDENT" /* BIDENT */, "VARIABLE" /* VARIABLE */, "(" /* LPAREN */].includes(first.kind)) return false;
|
|
2298
|
+
let depth = 0;
|
|
2299
|
+
let sawArithmetic = false;
|
|
2300
|
+
for (let index = this.pos; index < this.tokens.length; index++) {
|
|
2301
|
+
const token = this.tokens[index];
|
|
2302
|
+
if (depth === 0 && index > this.pos && (token.kind === "," /* COMMA */ || token.kind === "AS" /* AS */ || token.kind === "FROM" /* FROM */ || token.kind === ";" /* SEMICOLON */ || token.kind === "EOF" /* EOF */ || token.kind === "=" /* EQ */ || token.kind === "!=" /* NEQ */ || token.kind === "<>" /* LT_GT */ || token.kind === ">" /* GT */ || token.kind === "<" /* LT */ || token.kind === ">=" /* GTE */ || token.kind === "<=" /* LTE */ || token.kind === "AND" /* AND */ || token.kind === "OR" /* OR */)) break;
|
|
2303
|
+
if (this.isArithOp(token.kind)) sawArithmetic = true;
|
|
2304
|
+
if (PARSER_AGGREGATE_FUNCTION_TOKEN_MAP[token.kind] !== void 0 && this.tokens[index + 1]?.kind === "(" /* LPAREN */) return sawArithmetic;
|
|
2305
|
+
if (token.kind === "(" /* LPAREN */) depth++;
|
|
2306
|
+
else if (token.kind === ")" /* RPAREN */) {
|
|
2307
|
+
depth--;
|
|
2308
|
+
if (depth < 0) break;
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
return false;
|
|
2312
|
+
}
|
|
2313
|
+
/** SELECT ローカルの B124 leaf だけを ordinary GROUP BY の表記と照合する。 */
|
|
2314
|
+
validateAggregateGroupKeyRefs(columns, having, groupBy, grouping) {
|
|
2315
|
+
const refs = [];
|
|
2316
|
+
const visit = (node) => {
|
|
2317
|
+
if (Array.isArray(node)) {
|
|
2318
|
+
node.forEach(visit);
|
|
2319
|
+
return;
|
|
2320
|
+
}
|
|
2321
|
+
if (node === null || typeof node !== "object") return;
|
|
2322
|
+
const value = node;
|
|
2323
|
+
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
|
|
2324
|
+
if (value["type"] === "AGG_GROUP_KEY") {
|
|
2325
|
+
refs.push(node);
|
|
2326
|
+
return;
|
|
2327
|
+
}
|
|
2328
|
+
Object.values(value).forEach(visit);
|
|
2329
|
+
};
|
|
2330
|
+
visit(columns);
|
|
2331
|
+
visit(having);
|
|
2332
|
+
if (refs.length === 0) return;
|
|
2333
|
+
const first = refs[0];
|
|
2334
|
+
const firstToken = this.aggregateGroupKeyTokens.get(first) ?? this.peek();
|
|
2335
|
+
if (grouping !== void 0) {
|
|
2336
|
+
throw new ParseError(
|
|
2337
|
+
"ROLLUP / CUBE / GROUPING SETS \u3067\u306F\u96C6\u8A08\u7B97\u8853\u5F0F\u306B\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u66F8\u3051\u307E\u305B\u3093\uFF08\u5C0F\u8A08\u30FB\u7DCF\u8A08\u884C\u3067\u5024\u304C\u5B9A\u307E\u3089\u306A\u3044\u305F\u3081\u3067\u3059\uFF09\u3002",
|
|
2338
|
+
firstToken
|
|
2339
|
+
);
|
|
2340
|
+
}
|
|
2341
|
+
if (groupBy.length === 0) {
|
|
2342
|
+
throw new ParseError(
|
|
2343
|
+
`\u96C6\u8A08\u7B97\u8853\u5F0F\u306B\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u66F8\u304F\u306B\u306F GROUP BY \u304C\u5FC5\u8981\u3067\u3059\uFF08${this.aggregateGroupKeyDisplay(first)}\uFF09\u3002`,
|
|
2344
|
+
firstToken
|
|
2345
|
+
);
|
|
2346
|
+
}
|
|
2347
|
+
const ordinaryNames = new Set(groupBy.filter((key) => key.type === "FIELD_NAME").map((key) => key.name));
|
|
2348
|
+
for (const ref of refs) {
|
|
2349
|
+
const display = this.aggregateGroupKeyDisplay(ref);
|
|
2350
|
+
if (!ordinaryNames.has(display)) {
|
|
2351
|
+
throw new ParseError(
|
|
2352
|
+
`\u96C6\u8A08\u7B97\u8853\u5F0F\u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u53C2\u7167\u306F GROUP BY \u306B\u66F8\u3044\u305F\u8868\u8A18\u3068\u4E00\u81F4\u3059\u308B\u5217\u3060\u3051\u3067\u3059\uFF08${display}\uFF09\u3002\u30B0\u30EB\u30FC\u30D7\u5185\u3067\u5024\u304C\u5B9A\u307E\u3089\u306A\u3044\u305F\u3081\u3067\u3059\u3002`,
|
|
2353
|
+
this.aggregateGroupKeyTokens.get(ref) ?? firstToken
|
|
2354
|
+
);
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
aggregateGroupKeyDisplay(ref) {
|
|
2359
|
+
return ref.tableAlias ? `${ref.tableAlias}.${ref.field}` : ref.field;
|
|
2360
|
+
}
|
|
2264
2361
|
// ──────────────────────────────────────────────────
|
|
2265
2362
|
// 汎用スカラー値式パーサー(B38)
|
|
2266
2363
|
// ──────────────────────────────────────────────────
|
|
@@ -3008,6 +3105,12 @@ var Parser = class {
|
|
|
3008
3105
|
// - 集計関数(HAVING のみ): COUNT(*) / SUM(f) ...
|
|
3009
3106
|
// - 通常フィールド参照: [alias.]field
|
|
3010
3107
|
parseFieldValue() {
|
|
3108
|
+
if (this.groupingFieldContext === "HAVING" && this.isNonAggregateArithmeticStartWithAggregate()) {
|
|
3109
|
+
throw new ParseError(
|
|
3110
|
+
`\u96C6\u8A08\u7B97\u8853\u5F0F\u306F\u96C6\u8A08\u95A2\u6570\u304B\u3089\u59CB\u307E\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08${this.peek().value}\uFF09\u3002`,
|
|
3111
|
+
this.peek()
|
|
3112
|
+
);
|
|
3113
|
+
}
|
|
3011
3114
|
if (this.isUnsupportedGroupingIdStart()) {
|
|
3012
3115
|
throw new ParseError("B65: GROUPING_ID is not supported in Phase1.", this.peek());
|
|
3013
3116
|
}
|
|
@@ -5811,7 +5914,7 @@ function collectStringFuncFields(expr, out) {
|
|
|
5811
5914
|
}
|
|
5812
5915
|
}
|
|
5813
5916
|
function collectStringFuncArgFields(arg, out) {
|
|
5814
|
-
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
5917
|
+
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH" || arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") {
|
|
5815
5918
|
collectAggOperandFields(arg, out);
|
|
5816
5919
|
return;
|
|
5817
5920
|
}
|
|
@@ -5857,6 +5960,9 @@ function collectAggOperandFields(node, out) {
|
|
|
5857
5960
|
collectAggOperandFields(node.left, out);
|
|
5858
5961
|
collectAggOperandFields(node.right, out);
|
|
5859
5962
|
}
|
|
5963
|
+
if (node.type === "AGG_GROUP_KEY") {
|
|
5964
|
+
out.push(normalizeSimpleFieldRef(node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field));
|
|
5965
|
+
}
|
|
5860
5966
|
}
|
|
5861
5967
|
function collectAggregateArgFields(node, out) {
|
|
5862
5968
|
if (node.type === "FIELD_REF" || node.type === "ARITH") collectArithNode(node, out);
|
|
@@ -5865,6 +5971,7 @@ function collectAggregateArgFields(node, out) {
|
|
|
5865
5971
|
function hasAggregateInStringFuncExpr(expr) {
|
|
5866
5972
|
return expr.args.some((arg) => {
|
|
5867
5973
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
5974
|
+
if (arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") return false;
|
|
5868
5975
|
return scalarValueHasAggregate(arg);
|
|
5869
5976
|
});
|
|
5870
5977
|
}
|
|
@@ -6052,9 +6159,12 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
|
|
|
6052
6159
|
walkAgg(node.left, phase);
|
|
6053
6160
|
walkAgg(node.right, phase);
|
|
6054
6161
|
}
|
|
6162
|
+
if (node.type === "AGG_GROUP_KEY") {
|
|
6163
|
+
addFieldRef(node.field, node.tableAlias ?? null, phase);
|
|
6164
|
+
}
|
|
6055
6165
|
};
|
|
6056
6166
|
const walkStringArg = (arg, phase = "select") => {
|
|
6057
|
-
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
6167
|
+
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH" || arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") {
|
|
6058
6168
|
walkAgg(arg, phase);
|
|
6059
6169
|
return;
|
|
6060
6170
|
}
|
|
@@ -8155,7 +8265,7 @@ function formatWithComma(num, digits) {
|
|
|
8155
8265
|
return decStr ? `${intFmt}.${decStr}` : intFmt;
|
|
8156
8266
|
}
|
|
8157
8267
|
function evalStringFuncArg(arg, row, resolveFieldType, resolveFieldSemantics2) {
|
|
8158
|
-
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
8268
|
+
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH" || arg.type === "AGG_GROUP_KEY") {
|
|
8159
8269
|
return String(evalMaterializedAggregateOperand(arg, row));
|
|
8160
8270
|
}
|
|
8161
8271
|
if (arg.type === "NUMBER") return numberLiteralText(arg);
|
|
@@ -8166,6 +8276,13 @@ function evalMaterializedAggregateOperand(node, row) {
|
|
|
8166
8276
|
if (node.type === "AGG_REF") {
|
|
8167
8277
|
return row[aggregateSyntheticName(node.func, node.distinct, node.arg)] ?? "";
|
|
8168
8278
|
}
|
|
8279
|
+
if (node.type === "AGG_GROUP_KEY") {
|
|
8280
|
+
const field = node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field;
|
|
8281
|
+
return Number(resolveFieldRef(row, field));
|
|
8282
|
+
}
|
|
8283
|
+
if (node.type === "VARIABLE") {
|
|
8284
|
+
throw new Error(`InternalError: unresolved aggregate arithmetic variable @${node.name}.`);
|
|
8285
|
+
}
|
|
8169
8286
|
const left = Number(evalMaterializedAggregateOperand(node.left, row));
|
|
8170
8287
|
const right = Number(evalMaterializedAggregateOperand(node.right, row));
|
|
8171
8288
|
switch (node.op) {
|
|
@@ -8667,7 +8784,7 @@ function collectStringFuncFields2(expr, out) {
|
|
|
8667
8784
|
for (const arg of expr.args) collectStringFuncArgFields2(arg, out);
|
|
8668
8785
|
}
|
|
8669
8786
|
function collectStringFuncArgFields2(arg, out) {
|
|
8670
|
-
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
8787
|
+
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH" || arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") {
|
|
8671
8788
|
collectAggOperandFields2(arg, out);
|
|
8672
8789
|
return;
|
|
8673
8790
|
}
|
|
@@ -8698,6 +8815,7 @@ function collectAggOperandFields2(node, out) {
|
|
|
8698
8815
|
collectAggOperandFields2(node.left, out);
|
|
8699
8816
|
collectAggOperandFields2(node.right, out);
|
|
8700
8817
|
}
|
|
8818
|
+
if (node.type === "AGG_GROUP_KEY") out.add(node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field);
|
|
8701
8819
|
}
|
|
8702
8820
|
function collectAggregateArgFields2(node, out) {
|
|
8703
8821
|
if (node.type === "FIELD_REF" || node.type === "ARITH") collectArithNode2(node, out);
|
|
@@ -11501,6 +11619,42 @@ var LOCAL_COLLECTION_TYPES = /* @__PURE__ */ new Set([
|
|
|
11501
11619
|
function nativeWhereOperatorsForType(fieldType) {
|
|
11502
11620
|
return NATIVE_OPERATORS.get(fieldType) ?? /* @__PURE__ */ new Set();
|
|
11503
11621
|
}
|
|
11622
|
+
function normalizeChoiceEquality(where, resolveField2) {
|
|
11623
|
+
const rewrites = [];
|
|
11624
|
+
const visit = (node) => {
|
|
11625
|
+
if (node.type === "BINARY") {
|
|
11626
|
+
if ((node.op === "=" || node.op === "!=" || node.op === "<>") && node.left.type === "FIELD" && node.right.type === "STRING" && node.right.value !== "") {
|
|
11627
|
+
const semantics = resolveField2(node.left);
|
|
11628
|
+
if (semantics !== void 0 && semantics.compareMode === "option" && LOCAL_SCALAR_TYPES.has(semantics.fieldType) && nativeWhereOperatorsForType(semantics.fieldType).has("in") && semantics.optionOrder?.has(node.right.value) === true) {
|
|
11629
|
+
const normalizedOperator = node.op === "=" ? "IN" : "NOT_IN";
|
|
11630
|
+
rewrites.push({
|
|
11631
|
+
field: node.left,
|
|
11632
|
+
originalOperator: node.op,
|
|
11633
|
+
normalizedOperator,
|
|
11634
|
+
value: node.right.value
|
|
11635
|
+
});
|
|
11636
|
+
return {
|
|
11637
|
+
...node,
|
|
11638
|
+
op: normalizedOperator,
|
|
11639
|
+
right: { type: "IN_LIST", values: [node.right] }
|
|
11640
|
+
};
|
|
11641
|
+
}
|
|
11642
|
+
}
|
|
11643
|
+
return node;
|
|
11644
|
+
}
|
|
11645
|
+
if (node.type === "LOGICAL") {
|
|
11646
|
+
const left = visit(node.left);
|
|
11647
|
+
const right = visit(node.right);
|
|
11648
|
+
return left === node.left && right === node.right ? node : { ...node, left, right };
|
|
11649
|
+
}
|
|
11650
|
+
if (node.type === "GROUP" || node.type === "NOT") {
|
|
11651
|
+
const expr = visit(node.expr);
|
|
11652
|
+
return expr === node.expr ? node : { ...node, expr };
|
|
11653
|
+
}
|
|
11654
|
+
return node;
|
|
11655
|
+
};
|
|
11656
|
+
return { normalizedWhere: visit(where), rewrites };
|
|
11657
|
+
}
|
|
11504
11658
|
function classifyWhereCapability(where, resolveField2) {
|
|
11505
11659
|
if (where === null) {
|
|
11506
11660
|
return { capability: "EXACT_PUSHDOWN", reasons: [{ code: "WHERE_EXACT" }] };
|
|
@@ -13431,6 +13585,13 @@ function toAggregateFieldRef(field) {
|
|
|
13431
13585
|
function evalAggArithExpr(node, rows, resolveAggSortKind) {
|
|
13432
13586
|
if (node.type === "NUMBER") return node.value;
|
|
13433
13587
|
if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, node.separator, rows, resolveAggSortKind));
|
|
13588
|
+
if (node.type === "AGG_GROUP_KEY") {
|
|
13589
|
+
const field = node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field;
|
|
13590
|
+
return Number(resolveFieldRef(rows[0] ?? {}, field));
|
|
13591
|
+
}
|
|
13592
|
+
if (node.type === "VARIABLE") {
|
|
13593
|
+
throw new Error(`InternalError: unresolved aggregate arithmetic variable @${node.name}.`);
|
|
13594
|
+
}
|
|
13434
13595
|
const l = evalAggArithExpr(node.left, rows, resolveAggSortKind);
|
|
13435
13596
|
const r = evalAggArithExpr(node.right, rows, resolveAggSortKind);
|
|
13436
13597
|
switch (node.op) {
|
|
@@ -14069,7 +14230,8 @@ function arithColDefaultKey(expr) {
|
|
|
14069
14230
|
}
|
|
14070
14231
|
function stringFuncDefaultKey(expr) {
|
|
14071
14232
|
const argStrs = expr.args.map((a) => {
|
|
14072
|
-
if (a.type === "AGG_REF" || a.type === "AGG_ARITH") return aggArithDefaultKey(a);
|
|
14233
|
+
if (a.type === "AGG_REF" || a.type === "AGG_ARITH" || a.type === "AGG_GROUP_KEY") return aggArithDefaultKey(a);
|
|
14234
|
+
if (a.type === "VARIABLE") return `@${a.name}`;
|
|
14073
14235
|
return scalarValueDefaultKey(a);
|
|
14074
14236
|
});
|
|
14075
14237
|
return `${expr.func}(${argStrs.join(",")})`;
|
|
@@ -14096,6 +14258,7 @@ function scalarValueDefaultKey(expr) {
|
|
|
14096
14258
|
}
|
|
14097
14259
|
function hasAggregateInStringFuncArg(arg) {
|
|
14098
14260
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
14261
|
+
if (arg.type === "AGG_GROUP_KEY" || arg.type === "VARIABLE") return false;
|
|
14099
14262
|
return scalarValueHasAggregate2(arg);
|
|
14100
14263
|
}
|
|
14101
14264
|
function scalarValueHasAggregate2(expr) {
|
|
@@ -14125,6 +14288,13 @@ function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
|
|
|
14125
14288
|
const value = evalAggArithExpr(arg, rows, resolveAggSortKind);
|
|
14126
14289
|
return { type: "NUMBER", value, raw: String(value) };
|
|
14127
14290
|
}
|
|
14291
|
+
if (arg.type === "AGG_GROUP_KEY") {
|
|
14292
|
+
const field = arg.tableAlias ? `${arg.tableAlias}.${arg.field}` : arg.field;
|
|
14293
|
+
return { type: "NUMBER", value: Number(resolveFieldRef(rows[0] ?? {}, field)), raw: resolveFieldRef(rows[0] ?? {}, field) };
|
|
14294
|
+
}
|
|
14295
|
+
if (arg.type === "VARIABLE") {
|
|
14296
|
+
throw new Error(`InternalError: unresolved aggregate arithmetic variable @${arg.name}.`);
|
|
14297
|
+
}
|
|
14128
14298
|
if (arg.type === "STRING_FUNC") {
|
|
14129
14299
|
return resolveAggInStringFuncExpr(arg, rows, resolveAggSortKind);
|
|
14130
14300
|
}
|
|
@@ -16265,18 +16435,18 @@ async function assertRelativeDateExecutionPlan(stmt, client, cacheContext) {
|
|
|
16265
16435
|
}
|
|
16266
16436
|
async function resolveRelativeDateExecutionPlan(stmt, client, cacheContext) {
|
|
16267
16437
|
return buildRelativeDatePushdownPlan(stmt, {
|
|
16268
|
-
select: (select) =>
|
|
16438
|
+
select: async (select) => {
|
|
16439
|
+
const { resolver } = await normalizeSelectChoiceEquality(select, client, cacheContext);
|
|
16440
|
+
return classifyWhereCapability(select.where, resolver);
|
|
16441
|
+
},
|
|
16269
16442
|
dml: (dml) => resolveDmlWhereCapability(dml, client, cacheContext),
|
|
16270
16443
|
prefilterDecomposition: async (select) => {
|
|
16271
16444
|
if (select.where === null) return null;
|
|
16272
|
-
const resolver = await
|
|
16273
|
-
select,
|
|
16274
|
-
client,
|
|
16275
|
-
cacheContext
|
|
16276
|
-
);
|
|
16445
|
+
const { resolver } = await normalizeSelectChoiceEquality(select, client, cacheContext);
|
|
16277
16446
|
return decomposeRelativeDatePrefilter(select, resolver);
|
|
16278
16447
|
},
|
|
16279
16448
|
joinServerFunctionPlan: async (select) => {
|
|
16449
|
+
await normalizeSelectChoiceEquality(select, client, cacheContext);
|
|
16280
16450
|
const metadata = await loadTypedPushdownMeta(select, client, cacheContext);
|
|
16281
16451
|
const runtimePlan = buildRuntimeJoinPushdownPlan(select, metadata);
|
|
16282
16452
|
if (runtimePlan === null) return null;
|
|
@@ -17117,7 +17287,15 @@ function resolveBatchVariableReferencesInternal(node, variables, numericArithmet
|
|
|
17117
17287
|
`ArgumentError: variable @${obj["name"]} is not numeric and cannot be used in arithmetic.`
|
|
17118
17288
|
);
|
|
17119
17289
|
}
|
|
17120
|
-
return numericArithmeticOperand && value.type === "string" && value.placeholder === true ? {
|
|
17290
|
+
return numericArithmeticOperand && value.type === "string" && value.placeholder === true ? {
|
|
17291
|
+
type: "NUMBER",
|
|
17292
|
+
value: 0,
|
|
17293
|
+
raw: numericArithmeticOperand === "AGG_ARITH" ? `@${obj["name"]}` : value.value
|
|
17294
|
+
} : value.type === "number" ? {
|
|
17295
|
+
type: "NUMBER",
|
|
17296
|
+
value: value.value,
|
|
17297
|
+
raw: numericArithmeticOperand === "AGG_ARITH" ? `@${obj["name"]}` : value.raw ?? String(value.value)
|
|
17298
|
+
} : { type: "STRING", value: value.value };
|
|
17121
17299
|
}
|
|
17122
17300
|
if (obj["type"] === "VARIABLE_COL" && typeof obj["name"] === "string" && typeof obj["alias"] === "string") {
|
|
17123
17301
|
const value = variables.get(obj["name"]);
|
|
@@ -17136,7 +17314,7 @@ function resolveBatchVariableReferencesInternal(node, variables, numericArithmet
|
|
|
17136
17314
|
resolveBatchVariableReferencesInternal(
|
|
17137
17315
|
value,
|
|
17138
17316
|
variables,
|
|
17139
|
-
|
|
17317
|
+
key === "left" || key === "right" ? obj["type"] === "AGG_ARITH" ? "AGG_ARITH" : obj["type"] === "ARITH" || obj["type"] === "SCALAR_ARITH" ? "ARITH" : false : false
|
|
17140
17318
|
)
|
|
17141
17319
|
])
|
|
17142
17320
|
);
|
|
@@ -17338,7 +17516,10 @@ async function buildWhereFieldSemanticsResolver(stmt, client, cacheContext, mate
|
|
|
17338
17516
|
if (node === null || typeof node !== "object") return;
|
|
17339
17517
|
const value = node;
|
|
17340
17518
|
if (value["type"] === "SELECT") return;
|
|
17341
|
-
|
|
17519
|
+
const operator = String(value["op"]);
|
|
17520
|
+
const right = value["right"];
|
|
17521
|
+
const needsOptionExistence = ["=", "!=", "<>"].includes(operator) && right?.["type"] === "STRING" && right["value"] !== "";
|
|
17522
|
+
if (value["type"] === "BINARY" && ([">", "<", ">=", "<="].includes(operator) || needsOptionExistence)) {
|
|
17342
17523
|
const left = value["left"];
|
|
17343
17524
|
if (left?.["type"] === "FIELD" && typeof left["field"] === "string") {
|
|
17344
17525
|
orderedFields.add(left["field"]);
|
|
@@ -17405,6 +17586,49 @@ async function buildWhereFieldSemanticsResolver(stmt, client, cacheContext, mate
|
|
|
17405
17586
|
return matches.length > 1 ? syntheticSemantics("string") : void 0;
|
|
17406
17587
|
};
|
|
17407
17588
|
}
|
|
17589
|
+
var choiceEqualityRewritesBySelect = /* @__PURE__ */ new WeakMap();
|
|
17590
|
+
async function normalizeSelectChoiceEquality(stmt, client, cacheContext, materializedTables, forcePhysicalMetadata = false) {
|
|
17591
|
+
const resolver = await buildWhereFieldSemanticsResolver(
|
|
17592
|
+
stmt,
|
|
17593
|
+
client,
|
|
17594
|
+
cacheContext,
|
|
17595
|
+
materializedTables,
|
|
17596
|
+
forcePhysicalMetadata
|
|
17597
|
+
);
|
|
17598
|
+
if (stmt.where === null) return { resolver, rewrites: [] };
|
|
17599
|
+
const normalization = normalizeChoiceEquality(stmt.where, resolver);
|
|
17600
|
+
stmt.where = normalization.normalizedWhere;
|
|
17601
|
+
if (normalization.rewrites.length > 0) {
|
|
17602
|
+
choiceEqualityRewritesBySelect.set(stmt, normalization.rewrites);
|
|
17603
|
+
}
|
|
17604
|
+
return { resolver, rewrites: normalization.rewrites };
|
|
17605
|
+
}
|
|
17606
|
+
function hasDefaultRangeAggregateWindow(stmt) {
|
|
17607
|
+
return stmt.columns.some(
|
|
17608
|
+
(column) => column.type === "WINDOW_COL" && column.windowKind === "AGGREGATE" && column.orderBy.length > 0 && column.frame?.source === "DEFAULT"
|
|
17609
|
+
);
|
|
17610
|
+
}
|
|
17611
|
+
function collectDefaultRangeWindowWarnings(stmt, resolveField2, context) {
|
|
17612
|
+
const canProveSinglePhysicalInput = context === "DIRECT" && stmt.joins.length === 0 && stmt.from.cteName === null && stmt.from.subtableCode == null;
|
|
17613
|
+
const warnings = [];
|
|
17614
|
+
for (const column of stmt.columns) {
|
|
17615
|
+
if (column.type !== "WINDOW_COL" || column.windowKind !== "AGGREGATE" || column.orderBy.length === 0 || column.frame?.source !== "DEFAULT") continue;
|
|
17616
|
+
const hasTotalOrderKey = canProveSinglePhysicalInput && column.orderBy.some((item) => {
|
|
17617
|
+
if (item.key.type !== "FIELD_NAME") return false;
|
|
17618
|
+
const ref = aggregateFieldRef(item.key.name);
|
|
17619
|
+
return ref.field === "$id" || resolveField2(ref)?.fieldType === "RECORD_NUMBER";
|
|
17620
|
+
});
|
|
17621
|
+
if (hasTotalOrderKey) continue;
|
|
17622
|
+
warnings.push(
|
|
17623
|
+
`${column.alias} \u306F\u65E2\u5B9A\u30D5\u30EC\u30FC\u30E0\uFF08RANGE\uFF09\u3067\u8A55\u4FA1\u3055\u308C\u307E\u3059\u3002ORDER BY \u306E\u5024\u304C\u540C\u3058\u884C\u306F\u3059\u3079\u3066\u540C\u3058\u5024\u306B\u306A\u308A\u307E\u3059\u3002\u884C\u3054\u3068\u306E\u5024\u304C\u5FC5\u8981\u306A\u3089 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW \u3092\u660E\u793A\u3059\u308B\u304B\u3001ORDER BY \u306B\u30EC\u30B3\u30FC\u30C9\u756A\u53F7\u306A\u3069\u306E\u30BF\u30A4\u30D6\u30EC\u30FC\u30AF\u30AD\u30FC\u3092\u8DB3\u3057\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
17624
|
+
);
|
|
17625
|
+
}
|
|
17626
|
+
return warnings;
|
|
17627
|
+
}
|
|
17628
|
+
function mergeSelectWarnings(result, additional) {
|
|
17629
|
+
if (additional.length === 0) return result;
|
|
17630
|
+
return { ...result, warnings: [.../* @__PURE__ */ new Set([...result.warnings ?? [], ...additional])] };
|
|
17631
|
+
}
|
|
17408
17632
|
function selectCaseConditionsNeedFieldMetadata(stmt) {
|
|
17409
17633
|
const visit = (value) => {
|
|
17410
17634
|
if (value === null || typeof value !== "object") return false;
|
|
@@ -17461,11 +17685,6 @@ function buildHavingFieldSemanticsResolver(stmt, rowResolver) {
|
|
|
17461
17685
|
}
|
|
17462
17686
|
return (field) => field.tableAlias === null && aliases.has(field.field) ? aliases.get(field.field) : rowResolver(field);
|
|
17463
17687
|
}
|
|
17464
|
-
async function resolveSelectWhereCapability(stmt, client, cacheContext, materializedTables) {
|
|
17465
|
-
if (stmt.where === null) return classifyWhereCapability(null, () => void 0);
|
|
17466
|
-
const resolver = await buildWhereFieldSemanticsResolver(stmt, client, cacheContext, materializedTables);
|
|
17467
|
-
return classifyWhereCapability(stmt.where, resolver);
|
|
17468
|
-
}
|
|
17469
17688
|
function formatWhereCapabilityFailure(result) {
|
|
17470
17689
|
const reason = result.reasons.find(
|
|
17471
17690
|
(candidate) => candidate.code === "WHERE_FIELD_UNRESOLVED" || candidate.code === "WHERE_OPERATOR_UNSUPPORTED" || candidate.code === "WHERE_OPERATOR_INVALID_FOR_FIELD_TYPE"
|
|
@@ -17510,7 +17729,7 @@ async function assertDmlWhereCapability(stmt, client, cacheContext) {
|
|
|
17510
17729
|
);
|
|
17511
17730
|
}
|
|
17512
17731
|
}
|
|
17513
|
-
async function executeSelect(stmt, client, options, cacheContext, cteCache, captureColumnMeta = false, forLibraryCapture = false) {
|
|
17732
|
+
async function executeSelect(stmt, client, options, cacheContext, cteCache, captureColumnMeta = false, forLibraryCapture = false, windowWarningContext = "DIRECT") {
|
|
17514
17733
|
let result;
|
|
17515
17734
|
await validateSelectGroupingPlanning(stmt, client, cacheContext, cteCache);
|
|
17516
17735
|
if (isNoFromSelect(stmt)) {
|
|
@@ -17523,6 +17742,18 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache, capt
|
|
|
17523
17742
|
}
|
|
17524
17743
|
return result;
|
|
17525
17744
|
}
|
|
17745
|
+
const { resolver: fieldSemanticsResolver } = await normalizeSelectChoiceEquality(
|
|
17746
|
+
stmt,
|
|
17747
|
+
client,
|
|
17748
|
+
cacheContext,
|
|
17749
|
+
cteCache,
|
|
17750
|
+
hasDefaultRangeAggregateWindow(stmt)
|
|
17751
|
+
);
|
|
17752
|
+
const defaultRangeWarnings = collectDefaultRangeWindowWarnings(
|
|
17753
|
+
stmt,
|
|
17754
|
+
fieldSemanticsResolver,
|
|
17755
|
+
windowWarningContext
|
|
17756
|
+
);
|
|
17526
17757
|
const plainGroupByPlan = await buildRuntimePlainGroupByPlan(
|
|
17527
17758
|
stmt,
|
|
17528
17759
|
client,
|
|
@@ -17530,7 +17761,10 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache, capt
|
|
|
17530
17761
|
cteCache
|
|
17531
17762
|
);
|
|
17532
17763
|
await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache);
|
|
17533
|
-
const whereCapability = rememberSelectWhereCapability(
|
|
17764
|
+
const whereCapability = rememberSelectWhereCapability(
|
|
17765
|
+
stmt,
|
|
17766
|
+
classifyWhereCapability(stmt.where, fieldSemanticsResolver)
|
|
17767
|
+
);
|
|
17534
17768
|
if (whereCapability.capability === "UNSUPPORTED") {
|
|
17535
17769
|
throw new Error(`ArgumentError: WHERE predicate is unsupported (${formatWhereCapabilityFailure(whereCapability)}).`);
|
|
17536
17770
|
}
|
|
@@ -17617,7 +17851,7 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache, capt
|
|
|
17617
17851
|
await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache, forLibraryCapture)
|
|
17618
17852
|
);
|
|
17619
17853
|
}
|
|
17620
|
-
return result;
|
|
17854
|
+
return mergeSelectWarnings(result, defaultRangeWarnings);
|
|
17621
17855
|
}
|
|
17622
17856
|
async function buildRuntimePlainGroupByPlan(stmt, client, cacheContext, materializedTables) {
|
|
17623
17857
|
if (stmt.groupBy.length === 0) return void 0;
|
|
@@ -17853,6 +18087,8 @@ function arithHasFieldRef(node) {
|
|
|
17853
18087
|
return false;
|
|
17854
18088
|
}
|
|
17855
18089
|
function stringFuncArgHasFieldRef(arg) {
|
|
18090
|
+
if (arg.type === "AGG_GROUP_KEY") return true;
|
|
18091
|
+
if (arg.type === "VARIABLE") return false;
|
|
17856
18092
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
17857
18093
|
return scalarValueHasFieldRef(arg);
|
|
17858
18094
|
}
|
|
@@ -18410,7 +18646,11 @@ function collectAggregateArgFieldRefs(arg, out) {
|
|
|
18410
18646
|
}
|
|
18411
18647
|
if (arg.type === "STRING_FUNC") {
|
|
18412
18648
|
for (const child of arg.args) {
|
|
18413
|
-
if (child.type
|
|
18649
|
+
if (child.type === "AGG_GROUP_KEY") {
|
|
18650
|
+
out.push({ type: "FIELD", tableAlias: child.tableAlias ?? null, field: child.field });
|
|
18651
|
+
} else if (child.type !== "AGG_REF" && child.type !== "AGG_ARITH" && child.type !== "VARIABLE") {
|
|
18652
|
+
collectAggregateArgFieldRefs(child, out);
|
|
18653
|
+
}
|
|
18414
18654
|
}
|
|
18415
18655
|
return;
|
|
18416
18656
|
}
|
|
@@ -18430,11 +18670,16 @@ function collectAggregateOperandRefs(node, out) {
|
|
|
18430
18670
|
collectAggregateOperandRefs(node.left, out);
|
|
18431
18671
|
collectAggregateOperandRefs(node.right, out);
|
|
18432
18672
|
}
|
|
18673
|
+
if (node.type === "AGG_GROUP_KEY") out.push({ type: "FIELD", tableAlias: node.tableAlias ?? null, field: node.field });
|
|
18433
18674
|
}
|
|
18434
18675
|
function collectStringFuncAggregateRefs(expr, out) {
|
|
18435
18676
|
for (const arg of expr.args) {
|
|
18436
18677
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
18437
18678
|
collectAggregateOperandRefs(arg, out);
|
|
18679
|
+
} else if (arg.type === "AGG_GROUP_KEY") {
|
|
18680
|
+
out.push({ type: "FIELD", tableAlias: arg.tableAlias ?? null, field: arg.field });
|
|
18681
|
+
} else if (arg.type === "VARIABLE") {
|
|
18682
|
+
continue;
|
|
18438
18683
|
} else {
|
|
18439
18684
|
collectScalarAggregateRefs(arg, out);
|
|
18440
18685
|
}
|
|
@@ -19117,7 +19362,8 @@ async function executeUnion(stmt, client, options, cacheContext, captureColumnMe
|
|
|
19117
19362
|
cacheContext,
|
|
19118
19363
|
void 0,
|
|
19119
19364
|
captureColumnMeta,
|
|
19120
|
-
forLibraryCapture
|
|
19365
|
+
forLibraryCapture,
|
|
19366
|
+
"DERIVED"
|
|
19121
19367
|
),
|
|
19122
19368
|
executeSelect(
|
|
19123
19369
|
markCountTotalCountRoot(stmt.right),
|
|
@@ -19126,7 +19372,8 @@ async function executeUnion(stmt, client, options, cacheContext, captureColumnMe
|
|
|
19126
19372
|
cacheContext,
|
|
19127
19373
|
void 0,
|
|
19128
19374
|
captureColumnMeta,
|
|
19129
|
-
forLibraryCapture
|
|
19375
|
+
forLibraryCapture,
|
|
19376
|
+
"DERIVED"
|
|
19130
19377
|
)
|
|
19131
19378
|
]);
|
|
19132
19379
|
const leftCols = leftResult.columns;
|
|
@@ -19140,7 +19387,17 @@ async function executeUnion(stmt, client, options, cacheContext, captureColumnMe
|
|
|
19140
19387
|
});
|
|
19141
19388
|
const combined = [...leftResult.rows, ...remappedRight];
|
|
19142
19389
|
const rows = stmt.all ? combined : deduplicateRows(combined, leftCols);
|
|
19143
|
-
const
|
|
19390
|
+
const warnings = [.../* @__PURE__ */ new Set([
|
|
19391
|
+
...leftResult.warnings ?? [],
|
|
19392
|
+
...rightResult.warnings ?? []
|
|
19393
|
+
])];
|
|
19394
|
+
const result = {
|
|
19395
|
+
type: "SELECT",
|
|
19396
|
+
rows,
|
|
19397
|
+
columns: leftCols,
|
|
19398
|
+
rowCount: rows.length,
|
|
19399
|
+
warnings
|
|
19400
|
+
};
|
|
19144
19401
|
if (captureColumnMeta) {
|
|
19145
19402
|
materializedMetaBySelectResult.set(result, mergeUnionColumnMeta(leftResult, rightResult));
|
|
19146
19403
|
}
|
|
@@ -19158,25 +19415,44 @@ function deduplicateRows(rows, columns) {
|
|
|
19158
19415
|
}
|
|
19159
19416
|
async function executeWith(stmt, client, options, cacheContext, seed, captureColumnMeta = false) {
|
|
19160
19417
|
if ((seed == null || seed.size === 0) && canInlineSingleCte(stmt)) {
|
|
19161
|
-
return executeSelect(
|
|
19418
|
+
return executeSelect(
|
|
19419
|
+
buildInlinedQuery(stmt),
|
|
19420
|
+
client,
|
|
19421
|
+
options,
|
|
19422
|
+
cacheContext,
|
|
19423
|
+
void 0,
|
|
19424
|
+
captureColumnMeta,
|
|
19425
|
+
false,
|
|
19426
|
+
"DERIVED"
|
|
19427
|
+
);
|
|
19162
19428
|
}
|
|
19163
19429
|
const cteCache = new Map(seed ?? []);
|
|
19430
|
+
const warnings = /* @__PURE__ */ new Set();
|
|
19164
19431
|
for (const cte of stmt.ctes) {
|
|
19165
|
-
let
|
|
19432
|
+
let result2;
|
|
19166
19433
|
if (cte.query.type === "SHOW_APPS") {
|
|
19167
|
-
|
|
19434
|
+
result2 = await executeShowApps(client);
|
|
19168
19435
|
} else if (cte.query.type === "DESCRIBE") {
|
|
19169
|
-
|
|
19436
|
+
result2 = await executeDescribe(cte.query, client, cacheContext);
|
|
19170
19437
|
} else {
|
|
19171
|
-
|
|
19438
|
+
result2 = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext, true);
|
|
19172
19439
|
}
|
|
19440
|
+
for (const warning of result2.warnings ?? []) warnings.add(warning);
|
|
19173
19441
|
cteCache.set(cte.name, {
|
|
19174
|
-
rows:
|
|
19175
|
-
columns:
|
|
19176
|
-
columnMeta: materializedMetaBySelectResult.get(
|
|
19442
|
+
rows: result2.rows,
|
|
19443
|
+
columns: result2.columns,
|
|
19444
|
+
columnMeta: materializedMetaBySelectResult.get(result2)
|
|
19177
19445
|
});
|
|
19178
19446
|
}
|
|
19179
|
-
|
|
19447
|
+
const result = await executeQueryWithCte(
|
|
19448
|
+
stmt.query,
|
|
19449
|
+
client,
|
|
19450
|
+
options,
|
|
19451
|
+
cteCache,
|
|
19452
|
+
cacheContext,
|
|
19453
|
+
captureColumnMeta
|
|
19454
|
+
);
|
|
19455
|
+
return mergeSelectWarnings(result, [...warnings]);
|
|
19180
19456
|
}
|
|
19181
19457
|
async function executeQueryWithCte(query, client, options, cteCache, cacheContext, captureColumnMeta = false, b86PreflightComplete = false) {
|
|
19182
19458
|
if (!b86PreflightComplete) {
|
|
@@ -19198,7 +19474,17 @@ async function executeQueryWithCte(query, client, options, cteCache, cacheContex
|
|
|
19198
19474
|
});
|
|
19199
19475
|
const combined = [...leftResult.rows, ...remapped];
|
|
19200
19476
|
const rows = query.all ? combined : deduplicateRows(combined, leftCols);
|
|
19201
|
-
const
|
|
19477
|
+
const warnings = [.../* @__PURE__ */ new Set([
|
|
19478
|
+
...leftResult.warnings ?? [],
|
|
19479
|
+
...rightResult.warnings ?? []
|
|
19480
|
+
])];
|
|
19481
|
+
const result2 = {
|
|
19482
|
+
type: "SELECT",
|
|
19483
|
+
rows,
|
|
19484
|
+
columns: leftCols,
|
|
19485
|
+
rowCount: rows.length,
|
|
19486
|
+
warnings
|
|
19487
|
+
};
|
|
19202
19488
|
if (captureColumnMeta) {
|
|
19203
19489
|
materializedMetaBySelectResult.set(result2, mergeUnionColumnMeta(leftResult, rightResult));
|
|
19204
19490
|
}
|
|
@@ -19206,7 +19492,16 @@ async function executeQueryWithCte(query, client, options, cteCache, cacheContex
|
|
|
19206
19492
|
}
|
|
19207
19493
|
const hasCteRef = query.from.cteName != null && query.from.cteName !== NO_FROM_CTE_NAME || query.joins.some((j) => j.table.cteName != null);
|
|
19208
19494
|
if (!hasCteRef) {
|
|
19209
|
-
return executeSelect(
|
|
19495
|
+
return executeSelect(
|
|
19496
|
+
query,
|
|
19497
|
+
client,
|
|
19498
|
+
options,
|
|
19499
|
+
cacheContext,
|
|
19500
|
+
cteCache,
|
|
19501
|
+
captureColumnMeta,
|
|
19502
|
+
false,
|
|
19503
|
+
"DERIVED"
|
|
19504
|
+
);
|
|
19210
19505
|
}
|
|
19211
19506
|
const result = await executeFullScanWithCte(query, client, options, cteCache, cacheContext);
|
|
19212
19507
|
if (captureColumnMeta) {
|
|
@@ -19254,6 +19549,18 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
19254
19549
|
for (const table of [stmt.from, ...stmt.joins.map((join2) => join2.table)]) {
|
|
19255
19550
|
if (table.cteName !== null) requireMaterializedTable(table.cteName);
|
|
19256
19551
|
}
|
|
19552
|
+
const { resolver: choiceAndWindowResolver } = await normalizeSelectChoiceEquality(
|
|
19553
|
+
stmt,
|
|
19554
|
+
client,
|
|
19555
|
+
cacheContext,
|
|
19556
|
+
cteCache,
|
|
19557
|
+
hasDefaultRangeAggregateWindow(stmt)
|
|
19558
|
+
);
|
|
19559
|
+
const defaultRangeWarnings = collectDefaultRangeWindowWarnings(
|
|
19560
|
+
stmt,
|
|
19561
|
+
choiceAndWindowResolver,
|
|
19562
|
+
"DERIVED"
|
|
19563
|
+
);
|
|
19257
19564
|
const maxRecords = options.maxRecords ?? 1e4;
|
|
19258
19565
|
const warnings = /* @__PURE__ */ new Set();
|
|
19259
19566
|
const parallel = options.fetchParallel ?? 1;
|
|
@@ -19262,7 +19569,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
19262
19569
|
resolveSubqueries(stmt.having, client, options, cacheContext, cteCache),
|
|
19263
19570
|
resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache)
|
|
19264
19571
|
]);
|
|
19265
|
-
const whereCapability =
|
|
19572
|
+
const whereCapability = classifyWhereCapability(stmt.where, choiceAndWindowResolver);
|
|
19266
19573
|
if (whereCapability.capability === "UNSUPPORTED") {
|
|
19267
19574
|
throw new Error(`ArgumentError: WHERE predicate is unsupported (${formatWhereCapabilityFailure(whereCapability)}).`);
|
|
19268
19575
|
}
|
|
@@ -19391,7 +19698,10 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
19391
19698
|
client,
|
|
19392
19699
|
cacheContext
|
|
19393
19700
|
);
|
|
19394
|
-
return
|
|
19701
|
+
return mergeSelectWarnings(
|
|
19702
|
+
{ type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] },
|
|
19703
|
+
defaultRangeWarnings
|
|
19704
|
+
);
|
|
19395
19705
|
}
|
|
19396
19706
|
async function restoreEmptyWildcardColumns(stmt, rows, columns, client, cacheContext) {
|
|
19397
19707
|
if (rows.length !== 0 || columns.length !== 0 || stmt.columns.length !== 1 || stmt.columns[0].type !== "WILDCARD" || stmt.joins.length !== 0 || stmt.from.cteName !== null) {
|
|
@@ -22805,6 +23115,7 @@ async function resolveScalarColumns(columns, client, options, cacheContext, cteC
|
|
|
22805
23115
|
return cache;
|
|
22806
23116
|
}
|
|
22807
23117
|
var explainJoinPushdownPlans = /* @__PURE__ */ new WeakMap();
|
|
23118
|
+
var explainChoiceEqualityRewrites = /* @__PURE__ */ new WeakMap();
|
|
22808
23119
|
var validateExplainInfo = /* @__PURE__ */ new WeakMap();
|
|
22809
23120
|
var applyParentExplainPlan = /* @__PURE__ */ new WeakMap();
|
|
22810
23121
|
async function buildExplainWhereAnalysis(query, client, cacheContext, maxRecords = 1e4, relativeDatePlan) {
|
|
@@ -22860,7 +23171,13 @@ async function buildExplainWhereAnalysis(query, client, cacheContext, maxRecords
|
|
|
22860
23171
|
if (needsWhereSchema || select.orderBy.length > 0 || select.columns.some((column) => column.type === "WINDOW_COL" && column.orderBy.length > 0)) {
|
|
22861
23172
|
physicalApps.forEach((appId) => fieldApps.add(appId));
|
|
22862
23173
|
}
|
|
22863
|
-
const
|
|
23174
|
+
const { resolver, rewrites } = await normalizeSelectChoiceEquality(
|
|
23175
|
+
select,
|
|
23176
|
+
tracedClient,
|
|
23177
|
+
cacheContext
|
|
23178
|
+
);
|
|
23179
|
+
if (rewrites.length > 0) explainChoiceEqualityRewrites.set(select, rewrites);
|
|
23180
|
+
const capability = classifyWhereCapability(select.where, resolver);
|
|
22864
23181
|
const relativeNode = relativeNodeFor(select);
|
|
22865
23182
|
if (capability.capability === "UNSUPPORTED" && !relativeNode) {
|
|
22866
23183
|
throw new Error(`ArgumentError: WHERE predicate is unsupported (${formatWhereCapabilityFailure(capability)}).`);
|
|
@@ -22972,7 +23289,13 @@ async function buildExplainWhereAnalysis(query, client, cacheContext, maxRecords
|
|
|
22972
23289
|
await visit(query);
|
|
22973
23290
|
if (typeof query === "object" && query !== null && query.type === "WITH" && canInlineSingleCte(query)) {
|
|
22974
23291
|
const inlined = buildInlinedQuery(query);
|
|
22975
|
-
const
|
|
23292
|
+
const { resolver, rewrites } = await normalizeSelectChoiceEquality(
|
|
23293
|
+
inlined,
|
|
23294
|
+
tracedClient,
|
|
23295
|
+
cacheContext
|
|
23296
|
+
);
|
|
23297
|
+
if (rewrites.length > 0) explainChoiceEqualityRewrites.set(inlined, rewrites);
|
|
23298
|
+
const capability = classifyWhereCapability(inlined.where, resolver);
|
|
22976
23299
|
const relativeNode = relativeNodeFor(inlined);
|
|
22977
23300
|
if (capability.capability === "UNSUPPORTED" && !relativeNode) {
|
|
22978
23301
|
throw new Error(`ArgumentError: WHERE predicate is unsupported (${formatWhereCapabilityFailure(capability)}).`);
|
|
@@ -23744,6 +24067,13 @@ function buildValidatePlan(stmt, label) {
|
|
|
23744
24067
|
lines.push(" records/mutation API during EXPLAIN: none; violation count unavailable");
|
|
23745
24068
|
return lines;
|
|
23746
24069
|
}
|
|
24070
|
+
function formatChoiceEqualityRewrite(rewrite) {
|
|
24071
|
+
const field = rewrite.field.tableAlias ? `${rewrite.field.tableAlias}.${rewrite.field.field}` : rewrite.field.field;
|
|
24072
|
+
const originalValue = rewrite.value.replace(/'/g, "''");
|
|
24073
|
+
const normalizedValue = rewrite.value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
24074
|
+
const normalizedOperator = rewrite.normalizedOperator === "IN" ? "in" : "not in";
|
|
24075
|
+
return ` pushdown normalized: ${field} ${rewrite.originalOperator} '${originalValue}' -> ${field} ${normalizedOperator} ("${normalizedValue}")`;
|
|
24076
|
+
}
|
|
23747
24077
|
function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlans, allowTotalCountPlan = true, emitFetch = true, collector = { sources: [] }, sourceRole = "main") {
|
|
23748
24078
|
const whereCapability = capabilities?.get(stmt) ?? (capabilities ? [...capabilities].find(([candidate]) => JSON.stringify(candidate) === JSON.stringify(stmt))?.[1] : void 0);
|
|
23749
24079
|
const orderPlan = orderPlans?.get(stmt) ?? (orderPlans ? [...orderPlans].find(([candidate]) => JSON.stringify(candidate) === JSON.stringify(stmt))?.[1] : void 0);
|
|
@@ -23761,6 +24091,9 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlan
|
|
|
23761
24091
|
);
|
|
23762
24092
|
if (label) lines.push(label);
|
|
23763
24093
|
lines.push(` mode: ${mode}`);
|
|
24094
|
+
for (const rewrite of explainChoiceEqualityRewrites.get(stmt) ?? choiceEqualityRewritesBySelect.get(stmt) ?? []) {
|
|
24095
|
+
lines.push(formatChoiceEqualityRewrite(rewrite));
|
|
24096
|
+
}
|
|
23764
24097
|
if (groupingMetadata) {
|
|
23765
24098
|
lines.push(` grouping source: ${groupingMetadata.source}`);
|
|
23766
24099
|
lines.push(
|
|
@@ -24416,7 +24749,8 @@ function collectArithNodeRefs(node, out) {
|
|
|
24416
24749
|
}
|
|
24417
24750
|
if (node.type === "STRING_FUNC") {
|
|
24418
24751
|
for (const arg of node.args) {
|
|
24419
|
-
if (arg.type
|
|
24752
|
+
if (arg.type === "AGG_GROUP_KEY") out.add(arg.tableAlias ? `${arg.tableAlias}.${arg.field}` : arg.field);
|
|
24753
|
+
else if (arg.type !== "AGG_REF" && arg.type !== "AGG_ARITH" && arg.type !== "VARIABLE") collectScalarNodeRefs(arg, out);
|
|
24420
24754
|
}
|
|
24421
24755
|
}
|
|
24422
24756
|
}
|
|
@@ -24478,7 +24812,10 @@ function collectScalarNodeRefs(node, out) {
|
|
|
24478
24812
|
return;
|
|
24479
24813
|
}
|
|
24480
24814
|
if (node.type === "STRING_FUNC") {
|
|
24481
|
-
for (const arg of node.args)
|
|
24815
|
+
for (const arg of node.args) {
|
|
24816
|
+
if (arg.type === "AGG_GROUP_KEY") out.add(arg.tableAlias ? `${arg.tableAlias}.${arg.field}` : arg.field);
|
|
24817
|
+
else if (arg.type !== "AGG_REF" && arg.type !== "AGG_ARITH" && arg.type !== "VARIABLE") collectScalarNodeRefs(arg, out);
|
|
24818
|
+
}
|
|
24482
24819
|
return;
|
|
24483
24820
|
}
|
|
24484
24821
|
if (node.type === "SCALAR_ARITH" || node.type === "CONCAT_OP") {
|