@rex0220/kintone-sql-tools 3.15.0 → 3.16.1
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 +345 -97
- package/dist-mcp/ksql-mcp.js +348 -99
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -584,6 +584,120 @@ function numberLiteralText(node) {
|
|
|
584
584
|
return toPlainDecimal(source) ?? source;
|
|
585
585
|
}
|
|
586
586
|
|
|
587
|
+
// src/core/aggregateExpression.ts
|
|
588
|
+
function quote(value) {
|
|
589
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
590
|
+
}
|
|
591
|
+
function arithLabel(node, topLevel = false) {
|
|
592
|
+
if (node.type === "FIELD_REF") return node.field;
|
|
593
|
+
if (node.type === "NUMBER") return numberLiteralText(node);
|
|
594
|
+
if (node.type === "STRING_FUNC") return stringFuncLabel(node);
|
|
595
|
+
const label = `${arithLabel(node.left)}${node.op}${arithLabel(node.right)}`;
|
|
596
|
+
return topLevel ? label : `(${label})`;
|
|
597
|
+
}
|
|
598
|
+
function fieldValueLabel(value) {
|
|
599
|
+
if (value.type === "FIELD") return value.tableAlias ? `${value.tableAlias}.${value.field}` : value.field;
|
|
600
|
+
if (value.type === "FUNC_FIELD") return stringFuncLabel(value.expr);
|
|
601
|
+
if (value.type === "ARITH_FIELD") return arithLabel(value.expr);
|
|
602
|
+
return caseLabel(value.expr);
|
|
603
|
+
}
|
|
604
|
+
function sqlValueLabel(value) {
|
|
605
|
+
switch (value.type) {
|
|
606
|
+
case "STRING":
|
|
607
|
+
return quote(value.value);
|
|
608
|
+
case "NUMBER":
|
|
609
|
+
return numberLiteralText(value);
|
|
610
|
+
case "VARIABLE":
|
|
611
|
+
return `@${value.name}`;
|
|
612
|
+
case "VARIABLE_IN_LIST":
|
|
613
|
+
return `@${value.name}`;
|
|
614
|
+
case "KINTONE_FUNC":
|
|
615
|
+
return `${value.name}()`;
|
|
616
|
+
case "ARRAY":
|
|
617
|
+
return `[${value.elements.map((entry) => quote(entry.value)).join(",")}]`;
|
|
618
|
+
case "IN_LIST":
|
|
619
|
+
return `(${value.values.map(sqlValueLabel).join(",")})`;
|
|
620
|
+
case "ARITH_VALUE":
|
|
621
|
+
return arithLabel(value.expr);
|
|
622
|
+
case "CASE_VALUE":
|
|
623
|
+
return caseLabel(value.expr);
|
|
624
|
+
case "SUBQUERY_IN_LIST":
|
|
625
|
+
return "(SUBQUERY)";
|
|
626
|
+
case "SCALAR_SUBQUERY":
|
|
627
|
+
return "(SUBQUERY)";
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
function whereLabel(expr) {
|
|
631
|
+
switch (expr.type) {
|
|
632
|
+
case "BINARY":
|
|
633
|
+
return `${fieldValueLabel(expr.left)} ${expr.op.replace("_", " ")} ${sqlValueLabel(expr.right)}`;
|
|
634
|
+
case "NULL_CHECK":
|
|
635
|
+
return `${fieldValueLabel(expr.field)} IS ${expr.not ? "NOT " : ""}NULL`;
|
|
636
|
+
case "LOGICAL":
|
|
637
|
+
return `(${whereLabel(expr.left)} ${expr.op} ${whereLabel(expr.right)})`;
|
|
638
|
+
case "NOT":
|
|
639
|
+
return `NOT (${whereLabel(expr.expr)})`;
|
|
640
|
+
case "GROUP":
|
|
641
|
+
return `(${whereLabel(expr.expr)})`;
|
|
642
|
+
case "BOOLEAN":
|
|
643
|
+
return expr.value ? "TRUE" : "FALSE";
|
|
644
|
+
case "EXISTS":
|
|
645
|
+
return `${expr.not ? "NOT " : ""}EXISTS (SUBQUERY)`;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
function caseResultLabel(result) {
|
|
649
|
+
if (result.type === "ARRAY") return `[${result.elements.map((entry) => quote(entry.value)).join(",")}]`;
|
|
650
|
+
if (result.type === "FIELD_REF" || result.type === "ARITH") return arithLabel(result);
|
|
651
|
+
return scalarValueLabel(result);
|
|
652
|
+
}
|
|
653
|
+
function caseLabel(expr) {
|
|
654
|
+
const branches = expr.branches.map((branch) => `WHEN ${whereLabel(branch.condition)} THEN ${caseResultLabel(branch.result)}`).join(" ");
|
|
655
|
+
const otherwise = expr.elseResult === null ? "" : ` ELSE ${caseResultLabel(expr.elseResult)}`;
|
|
656
|
+
return `CASE ${branches}${otherwise} END`;
|
|
657
|
+
}
|
|
658
|
+
function stringFuncArgLabel(arg) {
|
|
659
|
+
if (arg.type === "AGG_REF") return aggregateSyntheticName(arg.func, arg.distinct, arg.arg);
|
|
660
|
+
if (arg.type === "AGG_ARITH") return aggregateOperandLabel(arg);
|
|
661
|
+
return scalarValueLabel(arg);
|
|
662
|
+
}
|
|
663
|
+
function stringFuncLabel(expr) {
|
|
664
|
+
return `${expr.func}(${expr.args.map(stringFuncArgLabel).join(",")})`;
|
|
665
|
+
}
|
|
666
|
+
function scalarValueLabel(expr) {
|
|
667
|
+
switch (expr.type) {
|
|
668
|
+
case "STRING":
|
|
669
|
+
return quote(expr.value);
|
|
670
|
+
case "NUMBER":
|
|
671
|
+
return numberLiteralText(expr);
|
|
672
|
+
case "VARIABLE":
|
|
673
|
+
return `@${expr.name}`;
|
|
674
|
+
case "FIELD":
|
|
675
|
+
return expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field;
|
|
676
|
+
case "STRING_FUNC":
|
|
677
|
+
return stringFuncLabel(expr);
|
|
678
|
+
case "CASE_WHEN":
|
|
679
|
+
return caseLabel(expr);
|
|
680
|
+
case "SCALAR_ARITH":
|
|
681
|
+
return `(${scalarValueLabel(expr.left)}${expr.op}${scalarValueLabel(expr.right)})`;
|
|
682
|
+
case "CONCAT_OP":
|
|
683
|
+
return `(${scalarValueLabel(expr.left)}||${scalarValueLabel(expr.right)})`;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
function aggregateArgLabel(arg) {
|
|
687
|
+
if (arg.type === "WILDCARD") return "*";
|
|
688
|
+
if (arg.type === "FIELD_REF" || arg.type === "ARITH") return arithLabel(arg, true);
|
|
689
|
+
return scalarValueLabel(arg);
|
|
690
|
+
}
|
|
691
|
+
function aggregateSyntheticName(func, distinct, arg) {
|
|
692
|
+
const label = aggregateArgLabel(arg);
|
|
693
|
+
return distinct ? `${func}(DISTINCT ${label})` : `${func}(${label})`;
|
|
694
|
+
}
|
|
695
|
+
function aggregateOperandLabel(node) {
|
|
696
|
+
if (node.type === "NUMBER") return numberLiteralText(node);
|
|
697
|
+
if (node.type === "AGG_REF") return aggregateSyntheticName(node.func, node.distinct, node.arg);
|
|
698
|
+
return `${aggregateOperandLabel(node.left)}${node.op}${aggregateOperandLabel(node.right)}`;
|
|
699
|
+
}
|
|
700
|
+
|
|
587
701
|
// src/parser/parser.ts
|
|
588
702
|
var MAX_BATCH_STATEMENTS = 20;
|
|
589
703
|
var PARSER_SCALAR_FUNCTION_TOKEN_MAP = Object.freeze({
|
|
@@ -787,6 +901,7 @@ var Parser = class {
|
|
|
787
901
|
this.scalarAllowsAggregateArgs = true;
|
|
788
902
|
this.scalarAllowsCase = true;
|
|
789
903
|
this.pos = 0;
|
|
904
|
+
this.insideAggregateArg = 0;
|
|
790
905
|
/** WITH 句で定義された CTE 名のセット(parseTableRef で参照) */
|
|
791
906
|
this.cteNames = /* @__PURE__ */ new Set();
|
|
792
907
|
/** パース中に出現した一時テーブル参照(#name)のトークン。単文 API での拒否に使う */
|
|
@@ -1615,7 +1730,7 @@ var Parser = class {
|
|
|
1615
1730
|
if (this.consume("*" /* STAR */)) {
|
|
1616
1731
|
return { type: "WILDCARD" };
|
|
1617
1732
|
}
|
|
1618
|
-
if (this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
|
|
1733
|
+
if (this.tryAggregateFunc() === null && this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
|
|
1619
1734
|
const expr = this.parseScalarValueExpr({ allowAggregateArgs: true });
|
|
1620
1735
|
const alias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
|
|
1621
1736
|
return { type: "SCALAR_VALUE_COL", expr, alias: alias2 };
|
|
@@ -1887,7 +2002,12 @@ var Parser = class {
|
|
|
1887
2002
|
if (!allowCase) throw new ParseError("\u3053\u306E\u30B9\u30AB\u30E9\u30FC\u5024\u5F0F\u3067\u306F CASE \u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", tok);
|
|
1888
2003
|
return this.parseCaseWhenExpr();
|
|
1889
2004
|
}
|
|
1890
|
-
if (this.tryAggregateFunc() !== null)
|
|
2005
|
+
if (this.tryAggregateFunc() !== null) {
|
|
2006
|
+
throw new ParseError(
|
|
2007
|
+
this.insideAggregateArg > 0 ? "\u96C6\u8A08\u95A2\u6570\u306E\u5F15\u6570\u5185\u306B\u96C6\u8A08\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093" : "\u30B9\u30AB\u30E9\u30FC\u5024\u5F0F\u306B\u96C6\u7D04\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093",
|
|
2008
|
+
tok
|
|
2009
|
+
);
|
|
2010
|
+
}
|
|
1891
2011
|
if (this.tryStringFuncName() !== null) return this.parseStringFuncExpr();
|
|
1892
2012
|
if (tok.kind === "IDENT" /* IDENT */ || tok.kind === "BIDENT" /* BIDENT */) {
|
|
1893
2013
|
this.advance();
|
|
@@ -2036,6 +2156,9 @@ var Parser = class {
|
|
|
2036
2156
|
/** THEN / ELSE の結果値。`||` を含む場合だけ新スカラー文法へ渡す。 */
|
|
2037
2157
|
parseCaseResult() {
|
|
2038
2158
|
const tok = this.peek();
|
|
2159
|
+
if (this.insideAggregateArg > 0 && this.tryAggregateFunc() !== null) {
|
|
2160
|
+
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);
|
|
2161
|
+
}
|
|
2039
2162
|
if (tok.kind === "[" /* LBRACKET */) {
|
|
2040
2163
|
return this.parseArrayLiteral();
|
|
2041
2164
|
}
|
|
@@ -2179,7 +2302,7 @@ var Parser = class {
|
|
|
2179
2302
|
}
|
|
2180
2303
|
arg = { type: "WILDCARD" };
|
|
2181
2304
|
} else {
|
|
2182
|
-
arg = this.
|
|
2305
|
+
arg = this.parseAggregateArgExpr();
|
|
2183
2306
|
}
|
|
2184
2307
|
let separator;
|
|
2185
2308
|
if (this.isSoftKeyword("SEPARATOR")) {
|
|
@@ -2198,6 +2321,60 @@ var Parser = class {
|
|
|
2198
2321
|
...separator !== void 0 ? { separator } : {}
|
|
2199
2322
|
};
|
|
2200
2323
|
}
|
|
2324
|
+
isAggregateArgEnd() {
|
|
2325
|
+
return this.peek().kind === ")" /* RPAREN */ || this.isSoftKeyword("SEPARATOR");
|
|
2326
|
+
}
|
|
2327
|
+
/** 旧算術 AST を優先し、新規形だけ ScalarValueExpr として読む。 */
|
|
2328
|
+
parseAggregateArgExpr() {
|
|
2329
|
+
const start = this.pos;
|
|
2330
|
+
try {
|
|
2331
|
+
const legacy = this.parseArithAddSub();
|
|
2332
|
+
if (this.isAggregateArgEnd()) return legacy;
|
|
2333
|
+
} catch {
|
|
2334
|
+
}
|
|
2335
|
+
this.pos = start;
|
|
2336
|
+
this.insideAggregateArg++;
|
|
2337
|
+
try {
|
|
2338
|
+
let expr;
|
|
2339
|
+
try {
|
|
2340
|
+
expr = this.parseScalarValueExpr({ allowCase: true, allowAggregateArgs: false });
|
|
2341
|
+
} catch (error) {
|
|
2342
|
+
if (error instanceof ParseError) {
|
|
2343
|
+
if (error.message.includes("\u6BD4\u8F03\u30FB\u8FF0\u8A9E")) {
|
|
2344
|
+
throw new ParseError(
|
|
2345
|
+
"\u96C6\u8A08\u95A2\u6570\u306E\u5F15\u6570\u306B\u6BD4\u8F03\u30FB\u8FF0\u8A9E\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002CASE \u3067\u5024\u3092\u660E\u793A\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u4F8B: SUM(CASE WHEN amount > 0 THEN 1 ELSE 0 END)",
|
|
2346
|
+
error.token
|
|
2347
|
+
);
|
|
2348
|
+
}
|
|
2349
|
+
if (error.message.includes("\u96C6\u7D04\u95A2\u6570")) {
|
|
2350
|
+
throw new ParseError("\u96C6\u8A08\u95A2\u6570\u306E\u5F15\u6570\u5185\u306B\u96C6\u8A08\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", error.token);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
throw error;
|
|
2354
|
+
}
|
|
2355
|
+
if (!this.isAggregateArgEnd()) {
|
|
2356
|
+
throw new ParseError(
|
|
2357
|
+
"\u3053\u306E\u96C6\u8A08\u95A2\u6570\u306E\u5F15\u6570\u5F62\u5F0F\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002CASE \u3067\u5024\u3092\u660E\u793A\u3059\u308B\u304B\u3001CTE \u3067\u5F0F\u3092\u5217\u306B\u3057\u3066\u304B\u3089\u96C6\u8A08\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
2358
|
+
this.peek()
|
|
2359
|
+
);
|
|
2360
|
+
}
|
|
2361
|
+
this.assertNoNestedAggregate(expr);
|
|
2362
|
+
return expr;
|
|
2363
|
+
} finally {
|
|
2364
|
+
this.insideAggregateArg--;
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
assertNoNestedAggregate(expr) {
|
|
2368
|
+
const visit = (value) => {
|
|
2369
|
+
if (value === null || typeof value !== "object") return;
|
|
2370
|
+
const node = value;
|
|
2371
|
+
if (node.type === "AGG_REF" || node.type === "AGG_ARITH") {
|
|
2372
|
+
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());
|
|
2373
|
+
}
|
|
2374
|
+
for (const child of Object.values(node)) visit(child);
|
|
2375
|
+
};
|
|
2376
|
+
visit(expr);
|
|
2377
|
+
}
|
|
2201
2378
|
// ----------------------------------------------------------
|
|
2202
2379
|
// FROM / JOIN
|
|
2203
2380
|
// ----------------------------------------------------------
|
|
@@ -2466,31 +2643,11 @@ var Parser = class {
|
|
|
2466
2643
|
}
|
|
2467
2644
|
const aggFunc = this.tryAggregateFunc();
|
|
2468
2645
|
if (aggFunc !== null) {
|
|
2469
|
-
this.
|
|
2470
|
-
|
|
2471
|
-
const distinct = this.consume("DISTINCT" /* DISTINCT */);
|
|
2472
|
-
const distinctToken = distinct ? this.prev() : null;
|
|
2473
|
-
if (aggFunc === "MODE" && distinctToken) {
|
|
2474
|
-
throw new ParseError("MODE \u3067\u306F DISTINCT \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", distinctToken);
|
|
2475
|
-
}
|
|
2476
|
-
let argStr;
|
|
2477
|
-
if (this.consume("*" /* STAR */)) {
|
|
2478
|
-
if (!aggregateAcceptsWildcard(aggFunc)) {
|
|
2479
|
-
throw new ParseError(`${aggFunc}(*) \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u30D5\u30A3\u30FC\u30EB\u30C9\u307E\u305F\u306F\u5F0F\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`, this.prev());
|
|
2480
|
-
}
|
|
2481
|
-
argStr = "*";
|
|
2482
|
-
} else {
|
|
2483
|
-
argStr = this.parseIdentifier();
|
|
2484
|
-
}
|
|
2485
|
-
if (this.isSoftKeyword("SEPARATOR")) {
|
|
2486
|
-
const separatorToken = this.advance();
|
|
2487
|
-
if (aggFunc !== "GROUP_CONCAT") {
|
|
2488
|
-
throw new ParseError("SEPARATOR \u306F GROUP_CONCAT \u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059", separatorToken);
|
|
2489
|
-
}
|
|
2490
|
-
this.expect("STRING" /* STRING */, "SEPARATOR \u306E\u5F8C\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059");
|
|
2646
|
+
if (this.insideAggregateArg > 0) {
|
|
2647
|
+
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());
|
|
2491
2648
|
}
|
|
2492
|
-
this.
|
|
2493
|
-
const syntheticName =
|
|
2649
|
+
const ref = this.parseAggregateRef(aggFunc);
|
|
2650
|
+
const syntheticName = aggregateSyntheticName(ref.func, ref.distinct, ref.arg);
|
|
2494
2651
|
return { type: "FIELD", tableAlias: null, field: syntheticName };
|
|
2495
2652
|
}
|
|
2496
2653
|
if (this.peek().kind === "CASE" /* CASE */) {
|
|
@@ -4631,7 +4788,7 @@ function collectCaseResultScalarFields(result, out) {
|
|
|
4631
4788
|
}
|
|
4632
4789
|
function collectAggOperandFields(node, out) {
|
|
4633
4790
|
if (node.type === "AGG_REF") {
|
|
4634
|
-
if (node.arg.type !== "WILDCARD")
|
|
4791
|
+
if (node.arg.type !== "WILDCARD") collectAggregateArgFields(node.arg, out);
|
|
4635
4792
|
return;
|
|
4636
4793
|
}
|
|
4637
4794
|
if (node.type === "AGG_ARITH") {
|
|
@@ -4639,6 +4796,10 @@ function collectAggOperandFields(node, out) {
|
|
|
4639
4796
|
collectAggOperandFields(node.right, out);
|
|
4640
4797
|
}
|
|
4641
4798
|
}
|
|
4799
|
+
function collectAggregateArgFields(node, out) {
|
|
4800
|
+
if (node.type === "FIELD_REF" || node.type === "ARITH") collectArithNode(node, out);
|
|
4801
|
+
else collectScalarValueFields(node, out);
|
|
4802
|
+
}
|
|
4642
4803
|
function hasAggregateInStringFuncExpr(expr) {
|
|
4643
4804
|
return expr.args.some((arg) => {
|
|
4644
4805
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
@@ -4784,7 +4945,7 @@ function collectRequiredFieldsByTable(stmt) {
|
|
|
4784
4945
|
};
|
|
4785
4946
|
const walkAgg = (node, phase = "select") => {
|
|
4786
4947
|
if (node.type === "AGG_REF") {
|
|
4787
|
-
if (node.arg.type !== "WILDCARD")
|
|
4948
|
+
if (node.arg.type !== "WILDCARD") walkAggregateArg(node.arg, phase);
|
|
4788
4949
|
return;
|
|
4789
4950
|
}
|
|
4790
4951
|
if (node.type === "AGG_ARITH") {
|
|
@@ -4818,6 +4979,13 @@ function collectRequiredFieldsByTable(stmt) {
|
|
|
4818
4979
|
}
|
|
4819
4980
|
if (expr.type === "CASE_WHEN") walkCase(expr, phase);
|
|
4820
4981
|
};
|
|
4982
|
+
const walkAggregateArg = (expr, phase = "select") => {
|
|
4983
|
+
if (expr.type === "FIELD_REF" || expr.type === "ARITH") {
|
|
4984
|
+
walkArith(expr, phase);
|
|
4985
|
+
return;
|
|
4986
|
+
}
|
|
4987
|
+
walkScalar(expr, phase);
|
|
4988
|
+
};
|
|
4821
4989
|
const walkCaseResult = (result, phase = "select") => {
|
|
4822
4990
|
if (result.type === "ARRAY") return;
|
|
4823
4991
|
if (result.type === "FIELD_REF" || result.type === "ARITH") {
|
|
@@ -4919,7 +5087,7 @@ function collectRequiredFieldsByTable(stmt) {
|
|
|
4919
5087
|
case "VARIABLE_COL":
|
|
4920
5088
|
throw new Error(`internal error: unresolved SELECT variable @${col.name}`);
|
|
4921
5089
|
case "AGGREGATE":
|
|
4922
|
-
if (col.arg.type !== "WILDCARD")
|
|
5090
|
+
if (col.arg.type !== "WILDCARD") walkAggregateArg(col.arg, "select");
|
|
4923
5091
|
break;
|
|
4924
5092
|
case "ARITH_AGG_COL":
|
|
4925
5093
|
walkAgg(col.expr, "select");
|
|
@@ -5000,44 +5168,6 @@ function collectSelectOutputNames(columns) {
|
|
|
5000
5168
|
}
|
|
5001
5169
|
return names;
|
|
5002
5170
|
}
|
|
5003
|
-
function aggregateSyntheticName(func, distinct, arg) {
|
|
5004
|
-
const argStr = arg.type === "WILDCARD" ? "*" : arithNodeLabel(arg);
|
|
5005
|
-
return distinct ? `${func}(DISTINCT ${argStr})` : `${func}(${argStr})`;
|
|
5006
|
-
}
|
|
5007
|
-
function arithNodeLabel(node) {
|
|
5008
|
-
if (node.type === "FIELD_REF") return node.field;
|
|
5009
|
-
if (node.type === "NUMBER") return numberLiteralText(node);
|
|
5010
|
-
if (node.type === "STRING_FUNC") return stringFuncLabel(node);
|
|
5011
|
-
return `(${arithNodeLabel(node.left)}${node.op}${arithNodeLabel(node.right)})`;
|
|
5012
|
-
}
|
|
5013
|
-
function stringFuncLabel(expr) {
|
|
5014
|
-
const args = expr.args.map((a) => {
|
|
5015
|
-
if (a.type === "AGG_REF") return aggregateSyntheticName(a.func, a.distinct, a.arg);
|
|
5016
|
-
if (a.type === "AGG_ARITH") return "agg_arith";
|
|
5017
|
-
return scalarValueLabel(a);
|
|
5018
|
-
});
|
|
5019
|
-
return `${expr.func}(${args.join(",")})`;
|
|
5020
|
-
}
|
|
5021
|
-
function scalarValueLabel(expr) {
|
|
5022
|
-
switch (expr.type) {
|
|
5023
|
-
case "STRING":
|
|
5024
|
-
return `'${expr.value}'`;
|
|
5025
|
-
case "NUMBER":
|
|
5026
|
-
return numberLiteralText(expr);
|
|
5027
|
-
case "VARIABLE":
|
|
5028
|
-
return `@${expr.name}`;
|
|
5029
|
-
case "FIELD":
|
|
5030
|
-
return expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field;
|
|
5031
|
-
case "STRING_FUNC":
|
|
5032
|
-
return stringFuncLabel(expr);
|
|
5033
|
-
case "CASE_WHEN":
|
|
5034
|
-
return "case";
|
|
5035
|
-
case "SCALAR_ARITH":
|
|
5036
|
-
return `(${scalarValueLabel(expr.left)}${expr.op}${scalarValueLabel(expr.right)})`;
|
|
5037
|
-
case "CONCAT_OP":
|
|
5038
|
-
return `(${scalarValueLabel(expr.left)}||${scalarValueLabel(expr.right)})`;
|
|
5039
|
-
}
|
|
5040
|
-
}
|
|
5041
5171
|
function isAggregateSyntheticName(name) {
|
|
5042
5172
|
return /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/i.test(name);
|
|
5043
5173
|
}
|
|
@@ -6059,6 +6189,38 @@ function evalScalarValueExpr(expr, row, resolveFieldType, resolveFieldSemantics2
|
|
|
6059
6189
|
}
|
|
6060
6190
|
}
|
|
6061
6191
|
}
|
|
6192
|
+
function evalScalarValueExprNullable(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
6193
|
+
switch (expr.type) {
|
|
6194
|
+
case "CASE_WHEN":
|
|
6195
|
+
return evalCaseWhenNullable(expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
6196
|
+
case "SCALAR_ARITH": {
|
|
6197
|
+
const left = evalScalarValueExprNullable(expr.left, row, resolveFieldType, resolveFieldSemantics2);
|
|
6198
|
+
const right = evalScalarValueExprNullable(expr.right, row, resolveFieldType, resolveFieldSemantics2);
|
|
6199
|
+
if (left === null || right === null) return null;
|
|
6200
|
+
const l = Number(left);
|
|
6201
|
+
const r = Number(right);
|
|
6202
|
+
switch (expr.op) {
|
|
6203
|
+
case "+":
|
|
6204
|
+
return l + r;
|
|
6205
|
+
case "-":
|
|
6206
|
+
return l - r;
|
|
6207
|
+
case "*":
|
|
6208
|
+
return l * r;
|
|
6209
|
+
case "/":
|
|
6210
|
+
return r !== 0 ? l / r : NaN;
|
|
6211
|
+
case "%":
|
|
6212
|
+
return r !== 0 ? l % r : NaN;
|
|
6213
|
+
}
|
|
6214
|
+
}
|
|
6215
|
+
case "CONCAT_OP": {
|
|
6216
|
+
const left = evalScalarValueExprNullable(expr.left, row, resolveFieldType, resolveFieldSemantics2);
|
|
6217
|
+
const right = evalScalarValueExprNullable(expr.right, row, resolveFieldType, resolveFieldSemantics2);
|
|
6218
|
+
return `${left ?? ""}${right ?? ""}`;
|
|
6219
|
+
}
|
|
6220
|
+
default:
|
|
6221
|
+
return evalScalarValueExpr(expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
6222
|
+
}
|
|
6223
|
+
}
|
|
6062
6224
|
function applyRoundOp(op, num, digits) {
|
|
6063
6225
|
const factor = Math.pow(10, digits);
|
|
6064
6226
|
const raw = Math[op](num * factor) / factor;
|
|
@@ -6768,6 +6930,20 @@ function evalCaseWhen(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
|
6768
6930
|
}
|
|
6769
6931
|
return "";
|
|
6770
6932
|
}
|
|
6933
|
+
function evalCaseWhenNullable(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
6934
|
+
for (const branch of expr.branches) {
|
|
6935
|
+
if (evalWhere(branch.condition, row, resolveFieldType, void 0, resolveFieldSemantics2)) {
|
|
6936
|
+
return evalCaseResultNullable(branch.result, row, resolveFieldType, resolveFieldSemantics2);
|
|
6937
|
+
}
|
|
6938
|
+
}
|
|
6939
|
+
return expr.elseResult === null ? null : evalCaseResultNullable(expr.elseResult, row, resolveFieldType, resolveFieldSemantics2);
|
|
6940
|
+
}
|
|
6941
|
+
function evalCaseResultNullable(result, row, resolveFieldType, resolveFieldSemantics2) {
|
|
6942
|
+
if (result.type === "ARRAY") return result.elements.map((entry) => entry.value).join(",");
|
|
6943
|
+
if (result.type === "FIELD_REF") return row[result.field] ?? "";
|
|
6944
|
+
if (result.type === "ARITH") return evalArithExpr(result, row);
|
|
6945
|
+
return evalScalarValueExprNullable(result, row, resolveFieldType, resolveFieldSemantics2);
|
|
6946
|
+
}
|
|
6771
6947
|
function evalCaseResult(result, row, resolveFieldType, resolveFieldSemantics2) {
|
|
6772
6948
|
if (result.type === "ARRAY") return result.elements.map((e) => e.value).join(",");
|
|
6773
6949
|
if (result.type === "FIELD_REF") {
|
|
@@ -7001,7 +7177,7 @@ function collectScalarValueFields2(expr, out) {
|
|
|
7001
7177
|
}
|
|
7002
7178
|
function collectAggOperandFields2(node, out) {
|
|
7003
7179
|
if (node.type === "AGG_REF") {
|
|
7004
|
-
if (node.arg.type !== "WILDCARD")
|
|
7180
|
+
if (node.arg.type !== "WILDCARD") collectAggregateArgFields2(node.arg, out);
|
|
7005
7181
|
return;
|
|
7006
7182
|
}
|
|
7007
7183
|
if (node.type === "AGG_ARITH") {
|
|
@@ -7009,6 +7185,10 @@ function collectAggOperandFields2(node, out) {
|
|
|
7009
7185
|
collectAggOperandFields2(node.right, out);
|
|
7010
7186
|
}
|
|
7011
7187
|
}
|
|
7188
|
+
function collectAggregateArgFields2(node, out) {
|
|
7189
|
+
if (node.type === "FIELD_REF" || node.type === "ARITH") collectArithNode2(node, out);
|
|
7190
|
+
else collectScalarValueFields2(node, out);
|
|
7191
|
+
}
|
|
7012
7192
|
function collectCaseResultFields(result, out) {
|
|
7013
7193
|
if (result.type === "ARRAY") return;
|
|
7014
7194
|
if (result.type === "FIELD_REF" || result.type === "ARITH") {
|
|
@@ -9999,7 +10179,7 @@ function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
|
|
|
9999
10179
|
}
|
|
10000
10180
|
for (const col of columns) {
|
|
10001
10181
|
if (col.type === "AGGREGATE") {
|
|
10002
|
-
const syntheticKey =
|
|
10182
|
+
const syntheticKey = aggregateSyntheticName(col.func, col.distinct, col.arg);
|
|
10003
10183
|
const value = String(evalAggregate(col.func, col.distinct, col.arg, col.separator, groupRows, resolveAggSortKind));
|
|
10004
10184
|
outRow[col.alias ?? syntheticKey] = value;
|
|
10005
10185
|
if (col.alias) outRow[syntheticKey] = value;
|
|
@@ -10036,10 +10216,16 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
|
|
|
10036
10216
|
const raw = row[arg.field];
|
|
10037
10217
|
if (raw === void 0 || raw === "" && func !== "MIN" && func !== "MAX") continue;
|
|
10038
10218
|
strVal = raw;
|
|
10039
|
-
} else {
|
|
10219
|
+
} else if (arg.type === "ARITH" || arg.type === "NUMBER" || arg.type === "STRING_FUNC") {
|
|
10040
10220
|
const n = evalArithExpr(arg, row);
|
|
10041
10221
|
if (isNaN(n)) continue;
|
|
10042
10222
|
strVal = String(n);
|
|
10223
|
+
} else {
|
|
10224
|
+
const value = evalScalarValueExprNullable(arg, row);
|
|
10225
|
+
if (value === null) continue;
|
|
10226
|
+
if (value === "" && func !== "MIN" && func !== "MAX") continue;
|
|
10227
|
+
if (typeof value === "number" && Number.isNaN(value)) continue;
|
|
10228
|
+
strVal = String(value);
|
|
10043
10229
|
}
|
|
10044
10230
|
strValues.push(strVal);
|
|
10045
10231
|
}
|
|
@@ -10054,8 +10240,8 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
|
|
|
10054
10240
|
const eff = distinct ? statistical ? [...new Set(numericValues)] : [...new Set(strValues)] : statistical ? numericValues : strValues;
|
|
10055
10241
|
if (func === "COUNT") return eff.length;
|
|
10056
10242
|
if (func === "GROUP_CONCAT") return eff.join(separator ?? ",");
|
|
10057
|
-
const comparison =
|
|
10058
|
-
const semantics = typeof comparison === "string" ? syntheticSemantics(comparison) : comparison ?? (arg.type === "FIELD_REF" ? syntheticSemantics("string") : syntheticSemantics("number"));
|
|
10243
|
+
const comparison = func === "MIN" || func === "MAX" || func === "MODE" ? resolveAggregateArgSemantics(arg, resolveAggSortKind) : void 0;
|
|
10244
|
+
const semantics = typeof comparison === "string" ? syntheticSemantics(comparison) : comparison ?? (arg.type === "FIELD_REF" || arg.type === "FIELD" || arg.type === "STRING" || arg.type === "CONCAT_OP" || arg.type === "CASE_WHEN" ? syntheticSemantics("string") : syntheticSemantics("number"));
|
|
10059
10245
|
if (func === "MODE") {
|
|
10060
10246
|
if (strValues.length === 0) return "";
|
|
10061
10247
|
const frequencies = /* @__PURE__ */ new Map();
|
|
@@ -10143,17 +10329,24 @@ function evalAggArithExpr(node, rows, resolveAggSortKind) {
|
|
|
10143
10329
|
}
|
|
10144
10330
|
}
|
|
10145
10331
|
function aggArithDefaultKey(node) {
|
|
10146
|
-
|
|
10147
|
-
if (node.type === "AGG_REF") return aggregateSyntheticName2(node.func, node.distinct, node.arg);
|
|
10148
|
-
return `${aggArithDefaultKey(node.left)}${node.op}${aggArithDefaultKey(node.right)}`;
|
|
10332
|
+
return aggregateOperandLabel(node);
|
|
10149
10333
|
}
|
|
10150
|
-
function
|
|
10151
|
-
if (arg.type === "
|
|
10152
|
-
return
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
10156
|
-
|
|
10334
|
+
function resolveAggregateArgSemantics(arg, resolver) {
|
|
10335
|
+
if (arg.type === "FIELD_REF") return resolver?.(toAggregateFieldRef(arg.field)) ?? "string";
|
|
10336
|
+
if (arg.type === "FIELD") return resolver?.(arg) ?? "string";
|
|
10337
|
+
if (arg.type === "NUMBER" || arg.type === "ARITH" || arg.type === "SCALAR_ARITH") return "number";
|
|
10338
|
+
if (arg.type === "STRING" || arg.type === "CONCAT_OP" || arg.type === "VARIABLE") return "string";
|
|
10339
|
+
if (arg.type === "STRING_FUNC") {
|
|
10340
|
+
const numeric = /* @__PURE__ */ new Set(["LENGTH", "LENGTH_CHAR", "INSTR", "ROUND", "FLOOR", "CEIL", "TRUNCATE", "YEAR", "MONTH", "DAY", "DATEDIFF", "ABS", "MOD", "POWER", "SQRT", "DAYOFWEEK", "QUARTER", "WEEK"]);
|
|
10341
|
+
if (arg.func === "CAST") return arg.args[1]?.type === "STRING" && arg.args[1].value === "NUMBER" ? "number" : "string";
|
|
10342
|
+
return numeric.has(arg.func) ? "number" : "string";
|
|
10343
|
+
}
|
|
10344
|
+
const results = [...arg.branches.map((branch) => branch.result), ...arg.elseResult === null ? [] : [arg.elseResult]].filter((result) => result.type !== "ARRAY").map((result) => resolveAggregateArgSemantics(result, resolver));
|
|
10345
|
+
if (results.length === 0 || results.some((result) => result === void 0)) return "string";
|
|
10346
|
+
const kinds = results.map((result) => typeof result === "string" ? result : result.compareMode === "number" || result.compareMode === "recordNumber" ? "number" : "string");
|
|
10347
|
+
if (!kinds.every((kind) => kind === kinds[0])) return "string";
|
|
10348
|
+
const first = results[0];
|
|
10349
|
+
return results.every((result) => JSON.stringify(result) === JSON.stringify(first)) ? first : kinds[0];
|
|
10157
10350
|
}
|
|
10158
10351
|
function applyHaving(rows, having, resolveFieldType, resolveFieldSemantics2) {
|
|
10159
10352
|
if (having === null) return rows;
|
|
@@ -10299,7 +10492,7 @@ function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, reso
|
|
|
10299
10492
|
evaluators.set(alias, () => column.value);
|
|
10300
10493
|
break;
|
|
10301
10494
|
case "AGGREGATE": {
|
|
10302
|
-
const source =
|
|
10495
|
+
const source = aggregateSyntheticName(column.func, column.distinct, column.arg);
|
|
10303
10496
|
evaluators.set(alias, (row) => row[alias] ?? row[source] ?? "0");
|
|
10304
10497
|
break;
|
|
10305
10498
|
}
|
|
@@ -10424,7 +10617,7 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns, re
|
|
|
10424
10617
|
break;
|
|
10425
10618
|
}
|
|
10426
10619
|
case "AGGREGATE": {
|
|
10427
|
-
const srcKey =
|
|
10620
|
+
const srcKey = aggregateSyntheticName(col.func, col.distinct, col.arg);
|
|
10428
10621
|
const dstKey = outputKeys?.[colIdx] ?? col.alias ?? srcKey;
|
|
10429
10622
|
out[dstKey] = row[col.alias ?? srcKey] ?? row[srcKey] ?? "0";
|
|
10430
10623
|
if (outputKeys === null && rowIdx === 0) orderedKeys.push(dstKey);
|
|
@@ -10510,7 +10703,7 @@ function computeOutputKey(col, colIdx, defaultFieldKeys) {
|
|
|
10510
10703
|
case "LITERAL_COL":
|
|
10511
10704
|
return col.alias ?? `'${col.value}'`;
|
|
10512
10705
|
case "AGGREGATE":
|
|
10513
|
-
return col.alias ??
|
|
10706
|
+
return col.alias ?? aggregateSyntheticName(col.func, col.distinct, col.arg);
|
|
10514
10707
|
case "ARITH_AGG_COL":
|
|
10515
10708
|
return col.alias ?? aggArithDefaultKey(col.expr);
|
|
10516
10709
|
case "ARITH_COL":
|
|
@@ -13110,7 +13303,14 @@ async function buildWhereFieldSemanticsResolver(stmt, client, cacheContext, mate
|
|
|
13110
13303
|
};
|
|
13111
13304
|
}
|
|
13112
13305
|
function selectCaseConditionsNeedFieldMetadata(stmt) {
|
|
13113
|
-
|
|
13306
|
+
const visit = (value) => {
|
|
13307
|
+
if (value === null || typeof value !== "object") return false;
|
|
13308
|
+
if (Array.isArray(value)) return value.some(visit);
|
|
13309
|
+
const node = value;
|
|
13310
|
+
if (node.type === "CASE_WHEN" && node.branches?.some((branch) => whereNeedsFieldMetadata(branch.condition))) return true;
|
|
13311
|
+
return Object.values(node).some(visit);
|
|
13312
|
+
};
|
|
13313
|
+
return stmt.columns.some(visit);
|
|
13114
13314
|
}
|
|
13115
13315
|
function buildHavingFieldSemanticsResolver(stmt, rowResolver) {
|
|
13116
13316
|
const aliases = /* @__PURE__ */ new Map();
|
|
@@ -13122,7 +13322,17 @@ function buildHavingFieldSemanticsResolver(stmt, rowResolver) {
|
|
|
13122
13322
|
semantics = syntheticSemantics("number");
|
|
13123
13323
|
} else if (column.type === "AGGREGATE") {
|
|
13124
13324
|
if (column.func === "MIN" || column.func === "MAX" || column.func === "MODE") {
|
|
13125
|
-
|
|
13325
|
+
if (column.arg.type !== "WILDCARD") {
|
|
13326
|
+
semantics = inferAggregateArgMeta(column.arg, (ref) => {
|
|
13327
|
+
const resolved = rowResolver(ref);
|
|
13328
|
+
if (!resolved) return void 0;
|
|
13329
|
+
return {
|
|
13330
|
+
sortKind: resolved.compareMode === "number" || resolved.compareMode === "recordNumber" ? "number" : "string",
|
|
13331
|
+
fieldType: resolved.fieldType,
|
|
13332
|
+
semantics: resolved
|
|
13333
|
+
};
|
|
13334
|
+
}).semantics;
|
|
13335
|
+
}
|
|
13126
13336
|
} else {
|
|
13127
13337
|
semantics = column.func === "GROUP_CONCAT" ? syntheticSemantics("string") : syntheticSemantics("number");
|
|
13128
13338
|
}
|
|
@@ -13571,8 +13781,38 @@ function aggregateFieldRef(field) {
|
|
|
13571
13781
|
return dot > 0 ? { type: "FIELD", tableAlias: field.slice(0, dot), field: field.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field };
|
|
13572
13782
|
}
|
|
13573
13783
|
function collectAggregateRef(func, arg, out) {
|
|
13574
|
-
if (
|
|
13784
|
+
if (func !== "MIN" && func !== "MAX" && func !== "MODE" || arg.type === "WILDCARD") return;
|
|
13785
|
+
collectAggregateArgFieldRefs(arg, out);
|
|
13786
|
+
}
|
|
13787
|
+
function collectAggregateArgFieldRefs(arg, out) {
|
|
13788
|
+
if (arg.type === "FIELD_REF") {
|
|
13575
13789
|
out.push(aggregateFieldRef(arg.field));
|
|
13790
|
+
return;
|
|
13791
|
+
}
|
|
13792
|
+
if (arg.type === "FIELD") {
|
|
13793
|
+
out.push(arg);
|
|
13794
|
+
return;
|
|
13795
|
+
}
|
|
13796
|
+
if (arg.type === "ARITH") {
|
|
13797
|
+
collectAggregateArgFieldRefs(arg.left, out);
|
|
13798
|
+
collectAggregateArgFieldRefs(arg.right, out);
|
|
13799
|
+
return;
|
|
13800
|
+
}
|
|
13801
|
+
if (arg.type === "SCALAR_ARITH" || arg.type === "CONCAT_OP") {
|
|
13802
|
+
collectAggregateArgFieldRefs(arg.left, out);
|
|
13803
|
+
collectAggregateArgFieldRefs(arg.right, out);
|
|
13804
|
+
return;
|
|
13805
|
+
}
|
|
13806
|
+
if (arg.type === "STRING_FUNC") {
|
|
13807
|
+
for (const child of arg.args) {
|
|
13808
|
+
if (child.type !== "AGG_REF" && child.type !== "AGG_ARITH") collectAggregateArgFieldRefs(child, out);
|
|
13809
|
+
}
|
|
13810
|
+
return;
|
|
13811
|
+
}
|
|
13812
|
+
if (arg.type === "CASE_WHEN") {
|
|
13813
|
+
for (const result of [...arg.branches.map((branch) => branch.result), ...arg.elseResult ? [arg.elseResult] : []]) {
|
|
13814
|
+
if (result.type !== "ARRAY") collectAggregateArgFieldRefs(result, out);
|
|
13815
|
+
}
|
|
13576
13816
|
}
|
|
13577
13817
|
}
|
|
13578
13818
|
function collectAggregateOperandRefs(node, out) {
|
|
@@ -13683,7 +13923,7 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext, materia
|
|
|
13683
13923
|
const base = info.semantics ?? resolveFieldSemantics(info);
|
|
13684
13924
|
return info.fieldType === "STATUS" && statusOrdersByApp.has(appId) ? { ...base, optionOrder: statusOrdersByApp.get(appId) } : base;
|
|
13685
13925
|
};
|
|
13686
|
-
|
|
13926
|
+
const resolveRef = (ref) => {
|
|
13687
13927
|
let info;
|
|
13688
13928
|
if (ref.tableAlias !== null) {
|
|
13689
13929
|
if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
@@ -13717,6 +13957,7 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext, materia
|
|
|
13717
13957
|
const sourceTable = ref.tableAlias !== null ? tables.find((table) => effectiveTableAlias(table) === ref.tableAlias) : stmt.joins.length === 0 ? stmt.from : void 0;
|
|
13718
13958
|
return semanticsForInfo(info, sourceTable?.appId ?? stmt.from.appId);
|
|
13719
13959
|
};
|
|
13960
|
+
return resolveRef;
|
|
13720
13961
|
}
|
|
13721
13962
|
function fieldCodeForTypeLookup(table, field) {
|
|
13722
13963
|
if (table.subtableCode && field.startsWith("_p.")) return field.slice(3);
|
|
@@ -13826,9 +14067,19 @@ function mergeExpressionColumnMeta(candidates) {
|
|
|
13826
14067
|
}
|
|
13827
14068
|
return unknownStringColumnMeta();
|
|
13828
14069
|
}
|
|
14070
|
+
function inferAggregateArgMeta(arg, resolveField2) {
|
|
14071
|
+
if (arg.type === "FIELD_REF") return resolveField2(aggregateFieldRef(arg.field)) ?? unknownStringColumnMeta();
|
|
14072
|
+
if (arg.type === "FIELD") return resolveField2(arg) ?? unknownStringColumnMeta();
|
|
14073
|
+
if (arg.type === "NUMBER" || arg.type === "ARITH" || arg.type === "SCALAR_ARITH") return syntheticColumnMeta("number");
|
|
14074
|
+
if (arg.type === "STRING" || arg.type === "CONCAT_OP" || arg.type === "VARIABLE") return syntheticColumnMeta("string");
|
|
14075
|
+
if (arg.type === "STRING_FUNC") return stringFunctionColumnMeta(arg);
|
|
14076
|
+
const results = arg.branches.map((branch) => caseResultColumnMeta(branch.result, resolveField2));
|
|
14077
|
+
if (arg.elseResult) results.push(caseResultColumnMeta(arg.elseResult, resolveField2));
|
|
14078
|
+
return mergeExpressionColumnMeta(results);
|
|
14079
|
+
}
|
|
13829
14080
|
function selectNeedsSourceColumnMeta(stmt) {
|
|
13830
14081
|
return stmt.columns.some(
|
|
13831
|
-
(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")
|
|
14082
|
+
(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")
|
|
13832
14083
|
);
|
|
13833
14084
|
}
|
|
13834
14085
|
async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext, materializedTables) {
|
|
@@ -13899,11 +14150,8 @@ async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext,
|
|
|
13899
14150
|
meta = syntheticColumnMeta("string");
|
|
13900
14151
|
} else if (column.func === "COUNT" || column.func === "SUM" || column.func === "AVG" || column.func === "STDDEV_POP" || column.func === "STDDEV_SAMP" || column.func === "VAR_POP" || column.func === "VAR_SAMP" || column.func === "MEDIAN") {
|
|
13901
14152
|
meta = syntheticColumnMeta("number");
|
|
13902
|
-
} else if ((column.func === "MIN" || column.func === "MAX" || column.func === "MODE") && column.arg.type
|
|
13903
|
-
|
|
13904
|
-
if (source) meta = source;
|
|
13905
|
-
} else if (column.func === "MODE") {
|
|
13906
|
-
meta = syntheticColumnMeta("number");
|
|
14153
|
+
} else if ((column.func === "MIN" || column.func === "MAX" || column.func === "MODE") && column.arg.type !== "WILDCARD") {
|
|
14154
|
+
meta = inferAggregateArgMeta(column.arg, resolveField2);
|
|
13907
14155
|
}
|
|
13908
14156
|
} else if (column.type === "ARITH_AGG_COL" || column.type === "ARITH_COL") {
|
|
13909
14157
|
meta = syntheticColumnMeta("number");
|
|
@@ -14669,7 +14917,7 @@ async function buildOrderSemanticsForSelect(stmt, client, cacheContext, material
|
|
|
14669
14917
|
meta = mergeExpressionColumnMeta(candidates);
|
|
14670
14918
|
} else if (column.type === "AGGREGATE") {
|
|
14671
14919
|
if (column.func === "MIN" || column.func === "MAX" || column.func === "MODE") {
|
|
14672
|
-
|
|
14920
|
+
if (column.arg.type !== "WILDCARD") meta = inferAggregateArgMeta(column.arg, resolveField2);
|
|
14673
14921
|
} else {
|
|
14674
14922
|
meta = column.func === "GROUP_CONCAT" ? syntheticColumnMeta("string") : syntheticColumnMeta("number");
|
|
14675
14923
|
}
|