@rex0220/kintone-sql-tools 3.11.0 → 3.13.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 +2 -0
- package/dist-cli/ksql.js +518 -164
- package/dist-mcp/ksql-mcp.js +672 -188
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -93,6 +93,12 @@ var KEYWORDS = /* @__PURE__ */ new Map([
|
|
|
93
93
|
["MAX", "MAX" /* MAX */],
|
|
94
94
|
["MIN", "MIN" /* MIN */],
|
|
95
95
|
["GROUP_CONCAT", "GROUP_CONCAT" /* GROUP_CONCAT */],
|
|
96
|
+
["STDDEV_POP", "STDDEV_POP" /* STDDEV_POP */],
|
|
97
|
+
["STDDEV_SAMP", "STDDEV_SAMP" /* STDDEV_SAMP */],
|
|
98
|
+
["VAR_POP", "VAR_POP" /* VAR_POP */],
|
|
99
|
+
["VAR_SAMP", "VAR_SAMP" /* VAR_SAMP */],
|
|
100
|
+
["MEDIAN", "MEDIAN" /* MEDIAN */],
|
|
101
|
+
["MODE", "MODE" /* MODE */],
|
|
96
102
|
["ROW_NUMBER", "ROW_NUMBER" /* ROW_NUMBER */],
|
|
97
103
|
["RANK", "RANK" /* RANK */],
|
|
98
104
|
["DENSE_RANK", "DENSE_RANK" /* DENSE_RANK */],
|
|
@@ -155,6 +161,9 @@ var KEYWORDS = /* @__PURE__ */ new Map([
|
|
|
155
161
|
["YEAR", "YEAR" /* YEAR */],
|
|
156
162
|
["MONTH", "MONTH" /* MONTH */],
|
|
157
163
|
["DAY", "DAY" /* DAY */],
|
|
164
|
+
["DAYOFWEEK", "DAYOFWEEK" /* DAYOFWEEK */],
|
|
165
|
+
["QUARTER", "QUARTER" /* QUARTER */],
|
|
166
|
+
["WEEK", "WEEK" /* WEEK */],
|
|
158
167
|
["DATE_FORMAT", "DATE_FORMAT" /* DATE_FORMAT */],
|
|
159
168
|
["DATEDIFF", "DATEDIFF" /* DATEDIFF */],
|
|
160
169
|
["DATE_ADD", "DATE_ADD" /* DATE_ADD */],
|
|
@@ -577,6 +586,112 @@ function numberLiteralText(node) {
|
|
|
577
586
|
|
|
578
587
|
// src/parser/parser.ts
|
|
579
588
|
var MAX_BATCH_STATEMENTS = 20;
|
|
589
|
+
var PARSER_SCALAR_FUNCTION_TOKEN_MAP = Object.freeze({
|
|
590
|
+
["UPPER" /* UPPER */]: "UPPER",
|
|
591
|
+
["LOWER" /* LOWER */]: "LOWER",
|
|
592
|
+
["TRIM" /* TRIM */]: "TRIM",
|
|
593
|
+
["LTRIM" /* LTRIM */]: "LTRIM",
|
|
594
|
+
["RTRIM" /* RTRIM */]: "RTRIM",
|
|
595
|
+
["LENGTH" /* LENGTH */]: "LENGTH",
|
|
596
|
+
["LENGTH_CHAR" /* LENGTH_CHAR */]: "LENGTH_CHAR",
|
|
597
|
+
["SUBSTRING" /* SUBSTRING */]: "SUBSTRING",
|
|
598
|
+
["SUBSTR" /* SUBSTR */]: "SUBSTRING",
|
|
599
|
+
["LEFT" /* LEFT */]: "LEFT",
|
|
600
|
+
["RIGHT" /* RIGHT */]: "RIGHT",
|
|
601
|
+
["INSTR" /* INSTR */]: "INSTR",
|
|
602
|
+
["CONCAT" /* CONCAT */]: "CONCAT",
|
|
603
|
+
["REPLACE" /* REPLACE */]: "REPLACE",
|
|
604
|
+
["REGEXP_LIKE" /* REGEXP_LIKE */]: "REGEXP_LIKE",
|
|
605
|
+
["REGEXP_REPLACE" /* REGEXP_REPLACE */]: "REGEXP_REPLACE",
|
|
606
|
+
["REGEXP_SUBSTR" /* REGEXP_SUBSTR */]: "REGEXP_SUBSTR",
|
|
607
|
+
["TRANSLATE" /* TRANSLATE */]: "TRANSLATE",
|
|
608
|
+
["COALESCE" /* COALESCE */]: "COALESCE",
|
|
609
|
+
["ISNULL" /* ISNULL */]: "ISNULL",
|
|
610
|
+
["NULLIF" /* NULLIF */]: "NULLIF",
|
|
611
|
+
["GREATEST" /* GREATEST */]: "GREATEST",
|
|
612
|
+
["LEAST" /* LEAST */]: "LEAST",
|
|
613
|
+
["LPAD" /* LPAD */]: "LPAD",
|
|
614
|
+
["RPAD" /* RPAD */]: "RPAD",
|
|
615
|
+
["ROUND" /* ROUND */]: "ROUND",
|
|
616
|
+
["FLOOR" /* FLOOR */]: "FLOOR",
|
|
617
|
+
["CEIL" /* CEIL */]: "CEIL",
|
|
618
|
+
["CEILING" /* CEILING */]: "CEIL",
|
|
619
|
+
["TRUNCATE" /* TRUNCATE */]: "TRUNCATE",
|
|
620
|
+
["TRUNC" /* TRUNC */]: "TRUNCATE",
|
|
621
|
+
["ABS" /* ABS */]: "ABS",
|
|
622
|
+
["MOD" /* MOD */]: "MOD",
|
|
623
|
+
["POWER" /* POWER */]: "POWER",
|
|
624
|
+
["POW" /* POW */]: "POWER",
|
|
625
|
+
["SQRT" /* SQRT */]: "SQRT",
|
|
626
|
+
["FORMAT" /* FORMAT */]: "FORMAT",
|
|
627
|
+
["CAST" /* CAST */]: "CAST",
|
|
628
|
+
["CONVERT" /* CONVERT */]: "CAST",
|
|
629
|
+
["YEAR" /* YEAR */]: "YEAR",
|
|
630
|
+
["MONTH" /* MONTH */]: "MONTH",
|
|
631
|
+
["DAY" /* DAY */]: "DAY",
|
|
632
|
+
["DAYOFWEEK" /* DAYOFWEEK */]: "DAYOFWEEK",
|
|
633
|
+
["QUARTER" /* QUARTER */]: "QUARTER",
|
|
634
|
+
["WEEK" /* WEEK */]: "WEEK",
|
|
635
|
+
["DATE_FORMAT" /* DATE_FORMAT */]: "DATE_FORMAT",
|
|
636
|
+
["DATEDIFF" /* DATEDIFF */]: "DATEDIFF",
|
|
637
|
+
["DATE_ADD" /* DATE_ADD */]: "DATE_ADD",
|
|
638
|
+
["LAST_DAY" /* LAST_DAY */]: "LAST_DAY"
|
|
639
|
+
});
|
|
640
|
+
var PARSER_IDENT_SCALAR_FUNCTIONS = Object.freeze([
|
|
641
|
+
"CURRENT_DATE",
|
|
642
|
+
"CURRENT_TIMESTAMP"
|
|
643
|
+
]);
|
|
644
|
+
var PARSER_AGGREGATE_FUNCTION_TOKEN_MAP = Object.freeze({
|
|
645
|
+
["COUNT" /* COUNT */]: "COUNT",
|
|
646
|
+
["SUM" /* SUM */]: "SUM",
|
|
647
|
+
["AVG" /* AVG */]: "AVG",
|
|
648
|
+
["MAX" /* MAX */]: "MAX",
|
|
649
|
+
["MIN" /* MIN */]: "MIN",
|
|
650
|
+
["GROUP_CONCAT" /* GROUP_CONCAT */]: "GROUP_CONCAT",
|
|
651
|
+
["STDDEV_POP" /* STDDEV_POP */]: "STDDEV_POP",
|
|
652
|
+
["STDDEV_SAMP" /* STDDEV_SAMP */]: "STDDEV_SAMP",
|
|
653
|
+
["VAR_POP" /* VAR_POP */]: "VAR_POP",
|
|
654
|
+
["VAR_SAMP" /* VAR_SAMP */]: "VAR_SAMP",
|
|
655
|
+
["MEDIAN" /* MEDIAN */]: "MEDIAN",
|
|
656
|
+
["MODE" /* MODE */]: "MODE"
|
|
657
|
+
});
|
|
658
|
+
var PARSER_AGGREGATE_FUNCTIONS = Object.freeze(
|
|
659
|
+
Object.values(PARSER_AGGREGATE_FUNCTION_TOKEN_MAP).filter(
|
|
660
|
+
(func) => func !== void 0
|
|
661
|
+
)
|
|
662
|
+
);
|
|
663
|
+
var PARSER_AGGREGATE_WILDCARD_FUNCTIONS = Object.freeze([
|
|
664
|
+
"COUNT",
|
|
665
|
+
"SUM",
|
|
666
|
+
"AVG",
|
|
667
|
+
"MAX",
|
|
668
|
+
"MIN"
|
|
669
|
+
]);
|
|
670
|
+
var PARSER_AGGREGATE_WILDCARD_FUNCTION_SET = new Set(PARSER_AGGREGATE_WILDCARD_FUNCTIONS);
|
|
671
|
+
function aggregateAcceptsWildcard(func) {
|
|
672
|
+
return PARSER_AGGREGATE_WILDCARD_FUNCTION_SET.has(func);
|
|
673
|
+
}
|
|
674
|
+
var PARSER_WINDOW_FUNCTION_TOKEN_MAP = Object.freeze({
|
|
675
|
+
["ROW_NUMBER" /* ROW_NUMBER */]: "ROW_NUMBER",
|
|
676
|
+
["RANK" /* RANK */]: "RANK",
|
|
677
|
+
["DENSE_RANK" /* DENSE_RANK */]: "DENSE_RANK"
|
|
678
|
+
});
|
|
679
|
+
var PARSER_CONTEXTUAL_FUNCTION_TOKEN_MAP = Object.freeze({
|
|
680
|
+
["TODAY" /* TODAY */]: "TODAY",
|
|
681
|
+
["NOW" /* NOW */]: "NOW",
|
|
682
|
+
["LOGINUSER" /* LOGINUSER */]: "LOGINUSER"
|
|
683
|
+
});
|
|
684
|
+
function isContextualFunctionToken(kind) {
|
|
685
|
+
return PARSER_CONTEXTUAL_FUNCTION_TOKEN_MAP[kind] !== void 0;
|
|
686
|
+
}
|
|
687
|
+
var PARSER_FUNCTION_SPELLINGS = Object.freeze(Array.from(/* @__PURE__ */ new Set([
|
|
688
|
+
...Object.keys(PARSER_SCALAR_FUNCTION_TOKEN_MAP),
|
|
689
|
+
...PARSER_IDENT_SCALAR_FUNCTIONS,
|
|
690
|
+
...Object.keys(PARSER_AGGREGATE_FUNCTION_TOKEN_MAP),
|
|
691
|
+
...Object.keys(PARSER_WINDOW_FUNCTION_TOKEN_MAP),
|
|
692
|
+
...Object.keys(PARSER_CONTEXTUAL_FUNCTION_TOKEN_MAP),
|
|
693
|
+
"IF"
|
|
694
|
+
])));
|
|
580
695
|
var FUNC_CALL_PREFIX_KINDS = /* @__PURE__ */ new Set([
|
|
581
696
|
"IDENT" /* IDENT */,
|
|
582
697
|
"BIDENT" /* BIDENT */,
|
|
@@ -585,6 +700,13 @@ var FUNC_CALL_PREFIX_KINDS = /* @__PURE__ */ new Set([
|
|
|
585
700
|
"AVG" /* AVG */,
|
|
586
701
|
"MAX" /* MAX */,
|
|
587
702
|
"MIN" /* MIN */,
|
|
703
|
+
"GROUP_CONCAT" /* GROUP_CONCAT */,
|
|
704
|
+
"STDDEV_POP" /* STDDEV_POP */,
|
|
705
|
+
"STDDEV_SAMP" /* STDDEV_SAMP */,
|
|
706
|
+
"VAR_POP" /* VAR_POP */,
|
|
707
|
+
"VAR_SAMP" /* VAR_SAMP */,
|
|
708
|
+
"MEDIAN" /* MEDIAN */,
|
|
709
|
+
"MODE" /* MODE */,
|
|
588
710
|
"ROW_NUMBER" /* ROW_NUMBER */,
|
|
589
711
|
"RANK" /* RANK */,
|
|
590
712
|
"DENSE_RANK" /* DENSE_RANK */,
|
|
@@ -633,6 +755,9 @@ var FUNC_CALL_PREFIX_KINDS = /* @__PURE__ */ new Set([
|
|
|
633
755
|
"YEAR" /* YEAR */,
|
|
634
756
|
"MONTH" /* MONTH */,
|
|
635
757
|
"DAY" /* DAY */,
|
|
758
|
+
"DAYOFWEEK" /* DAYOFWEEK */,
|
|
759
|
+
"QUARTER" /* QUARTER */,
|
|
760
|
+
"WEEK" /* WEEK */,
|
|
636
761
|
"DATE_FORMAT" /* DATE_FORMAT */,
|
|
637
762
|
"DATEDIFF" /* DATEDIFF */,
|
|
638
763
|
"DATE_ADD" /* DATE_ADD */,
|
|
@@ -820,13 +945,14 @@ var Parser = class {
|
|
|
820
945
|
this.advance();
|
|
821
946
|
return { type: "STRING", value: tok.value };
|
|
822
947
|
}
|
|
823
|
-
|
|
948
|
+
const contextualFunction = PARSER_CONTEXTUAL_FUNCTION_TOKEN_MAP[tok.kind];
|
|
949
|
+
if (contextualFunction === "LOGINUSER") {
|
|
824
950
|
throw new ParseError(
|
|
825
951
|
`${context} \u306E\u53F3\u8FBA\u3067 LOGINUSER() \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\uFF08\u5B9F\u884C\u74B0\u5883\u5171\u901A\u306E\u30ED\u30B0\u30A4\u30F3\u30E6\u30FC\u30B6\u30FC\u89E3\u6C7A\u306F\u672A\u5BFE\u5FDC\u3067\u3059\uFF09`,
|
|
826
952
|
tok
|
|
827
953
|
);
|
|
828
954
|
}
|
|
829
|
-
if (
|
|
955
|
+
if (contextualFunction !== void 0) {
|
|
830
956
|
return this.parseSqlValue();
|
|
831
957
|
}
|
|
832
958
|
const expr = this.parseArithAddSub();
|
|
@@ -1581,16 +1707,7 @@ var Parser = class {
|
|
|
1581
1707
|
return { type: "FIELD", field, alias };
|
|
1582
1708
|
}
|
|
1583
1709
|
tryWindowFunc() {
|
|
1584
|
-
|
|
1585
|
-
case "ROW_NUMBER" /* ROW_NUMBER */:
|
|
1586
|
-
return "ROW_NUMBER";
|
|
1587
|
-
case "RANK" /* RANK */:
|
|
1588
|
-
return "RANK";
|
|
1589
|
-
case "DENSE_RANK" /* DENSE_RANK */:
|
|
1590
|
-
return "DENSE_RANK";
|
|
1591
|
-
default:
|
|
1592
|
-
return null;
|
|
1593
|
-
}
|
|
1710
|
+
return PARSER_WINDOW_FUNCTION_TOKEN_MAP[this.peek().kind] ?? null;
|
|
1594
1711
|
}
|
|
1595
1712
|
parseWindowColumn(func) {
|
|
1596
1713
|
this.advance();
|
|
@@ -1947,64 +2064,14 @@ var Parser = class {
|
|
|
1947
2064
|
// ──────────────────────────────────────────────────
|
|
1948
2065
|
tryStringFuncName() {
|
|
1949
2066
|
if (this.peekAt(1).kind === "(" /* LPAREN */) {
|
|
1950
|
-
|
|
1951
|
-
if (
|
|
1952
|
-
}
|
|
1953
|
-
const
|
|
1954
|
-
|
|
1955
|
-
["LOWER" /* LOWER */]: "LOWER",
|
|
1956
|
-
["TRIM" /* TRIM */]: "TRIM",
|
|
1957
|
-
["LTRIM" /* LTRIM */]: "LTRIM",
|
|
1958
|
-
["RTRIM" /* RTRIM */]: "RTRIM",
|
|
1959
|
-
["LENGTH" /* LENGTH */]: "LENGTH",
|
|
1960
|
-
["LENGTH_CHAR" /* LENGTH_CHAR */]: "LENGTH_CHAR",
|
|
1961
|
-
["SUBSTRING" /* SUBSTRING */]: "SUBSTRING",
|
|
1962
|
-
["SUBSTR" /* SUBSTR */]: "SUBSTRING",
|
|
1963
|
-
["CONCAT" /* CONCAT */]: "CONCAT",
|
|
1964
|
-
["REPLACE" /* REPLACE */]: "REPLACE",
|
|
1965
|
-
["REGEXP_LIKE" /* REGEXP_LIKE */]: "REGEXP_LIKE",
|
|
1966
|
-
["REGEXP_REPLACE" /* REGEXP_REPLACE */]: "REGEXP_REPLACE",
|
|
1967
|
-
["REGEXP_SUBSTR" /* REGEXP_SUBSTR */]: "REGEXP_SUBSTR",
|
|
1968
|
-
["TRANSLATE" /* TRANSLATE */]: "TRANSLATE",
|
|
1969
|
-
["COALESCE" /* COALESCE */]: "COALESCE",
|
|
1970
|
-
["NULLIF" /* NULLIF */]: "NULLIF",
|
|
1971
|
-
["ISNULL" /* ISNULL */]: "ISNULL",
|
|
1972
|
-
["INSTR" /* INSTR */]: "INSTR",
|
|
1973
|
-
["GREATEST" /* GREATEST */]: "GREATEST",
|
|
1974
|
-
["LEAST" /* LEAST */]: "LEAST",
|
|
1975
|
-
["LPAD" /* LPAD */]: "LPAD",
|
|
1976
|
-
["RPAD" /* RPAD */]: "RPAD",
|
|
1977
|
-
["CAST" /* CAST */]: "CAST",
|
|
1978
|
-
["CONVERT" /* CONVERT */]: "CAST",
|
|
1979
|
-
// CONVERT → CAST に正規化
|
|
1980
|
-
["FORMAT" /* FORMAT */]: "FORMAT",
|
|
1981
|
-
["ROUND" /* ROUND */]: "ROUND",
|
|
1982
|
-
["FLOOR" /* FLOOR */]: "FLOOR",
|
|
1983
|
-
["CEIL" /* CEIL */]: "CEIL",
|
|
1984
|
-
["CEILING" /* CEILING */]: "CEIL",
|
|
1985
|
-
// CEILING → CEIL に正規化
|
|
1986
|
-
["TRUNCATE" /* TRUNCATE */]: "TRUNCATE",
|
|
1987
|
-
["TRUNC" /* TRUNC */]: "TRUNCATE",
|
|
1988
|
-
// TRUNC → TRUNCATE に正規化
|
|
1989
|
-
["YEAR" /* YEAR */]: "YEAR",
|
|
1990
|
-
["MONTH" /* MONTH */]: "MONTH",
|
|
1991
|
-
["DAY" /* DAY */]: "DAY",
|
|
1992
|
-
["DATE_FORMAT" /* DATE_FORMAT */]: "DATE_FORMAT",
|
|
1993
|
-
["DATEDIFF" /* DATEDIFF */]: "DATEDIFF",
|
|
1994
|
-
["DATE_ADD" /* DATE_ADD */]: "DATE_ADD",
|
|
1995
|
-
["LAST_DAY" /* LAST_DAY */]: "LAST_DAY",
|
|
1996
|
-
["ABS" /* ABS */]: "ABS",
|
|
1997
|
-
["MOD" /* MOD */]: "MOD",
|
|
1998
|
-
["POWER" /* POWER */]: "POWER",
|
|
1999
|
-
["POW" /* POW */]: "POWER",
|
|
2000
|
-
// POW → POWER に正規化
|
|
2001
|
-
["SQRT" /* SQRT */]: "SQRT"
|
|
2002
|
-
};
|
|
2003
|
-
const byKind = map[this.peek().kind] ?? null;
|
|
2004
|
-
if (byKind !== null) return byKind;
|
|
2067
|
+
const conditional = PARSER_SCALAR_FUNCTION_TOKEN_MAP[this.peek().kind];
|
|
2068
|
+
if (conditional === "LEFT" || conditional === "RIGHT") return conditional;
|
|
2069
|
+
}
|
|
2070
|
+
const byKind = PARSER_SCALAR_FUNCTION_TOKEN_MAP[this.peek().kind] ?? null;
|
|
2071
|
+
if (byKind !== null && byKind !== "LEFT" && byKind !== "RIGHT") return byKind;
|
|
2005
2072
|
if (this.peek().kind === "IDENT" /* IDENT */) {
|
|
2006
2073
|
const name = this.peek().value.toUpperCase();
|
|
2007
|
-
if (name
|
|
2074
|
+
if (PARSER_IDENT_SCALAR_FUNCTIONS.includes(name)) {
|
|
2008
2075
|
if (this.peekAt(1).kind === "(" /* LPAREN */) {
|
|
2009
2076
|
return name;
|
|
2010
2077
|
}
|
|
@@ -2094,26 +2161,21 @@ var Parser = class {
|
|
|
2094
2161
|
return false;
|
|
2095
2162
|
}
|
|
2096
2163
|
tryAggregateFunc() {
|
|
2097
|
-
|
|
2098
|
-
["COUNT" /* COUNT */]: "COUNT",
|
|
2099
|
-
["SUM" /* SUM */]: "SUM",
|
|
2100
|
-
["AVG" /* AVG */]: "AVG",
|
|
2101
|
-
["MAX" /* MAX */]: "MAX",
|
|
2102
|
-
["MIN" /* MIN */]: "MIN",
|
|
2103
|
-
["GROUP_CONCAT" /* GROUP_CONCAT */]: "GROUP_CONCAT"
|
|
2104
|
-
};
|
|
2105
|
-
const kind = this.peek().kind;
|
|
2106
|
-
return map[kind] ?? null;
|
|
2164
|
+
return PARSER_AGGREGATE_FUNCTION_TOKEN_MAP[this.peek().kind] ?? null;
|
|
2107
2165
|
}
|
|
2108
2166
|
/** 集計関数参照を読む。SELECT 列の alias は呼び出し側で式全体の後に処理する。 */
|
|
2109
2167
|
parseAggregateRef(func) {
|
|
2110
2168
|
this.advance();
|
|
2111
2169
|
this.expect("(" /* LPAREN */);
|
|
2112
2170
|
const distinct = this.consume("DISTINCT" /* DISTINCT */);
|
|
2171
|
+
const distinctToken = distinct ? this.prev() : null;
|
|
2172
|
+
if (func === "MODE" && distinctToken) {
|
|
2173
|
+
throw new ParseError("MODE \u3067\u306F DISTINCT \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", distinctToken);
|
|
2174
|
+
}
|
|
2113
2175
|
let arg;
|
|
2114
2176
|
if (this.consume("*" /* STAR */)) {
|
|
2115
|
-
if (func
|
|
2116
|
-
throw new ParseError(
|
|
2177
|
+
if (!aggregateAcceptsWildcard(func)) {
|
|
2178
|
+
throw new ParseError(`${func}(*) \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());
|
|
2117
2179
|
}
|
|
2118
2180
|
arg = { type: "WILDCARD" };
|
|
2119
2181
|
} else {
|
|
@@ -2407,10 +2469,14 @@ var Parser = class {
|
|
|
2407
2469
|
this.advance();
|
|
2408
2470
|
this.expect("(" /* LPAREN */);
|
|
2409
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
|
+
}
|
|
2410
2476
|
let argStr;
|
|
2411
2477
|
if (this.consume("*" /* STAR */)) {
|
|
2412
|
-
if (aggFunc
|
|
2413
|
-
throw new ParseError(
|
|
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());
|
|
2414
2480
|
}
|
|
2415
2481
|
argStr = "*";
|
|
2416
2482
|
} else {
|
|
@@ -2464,13 +2530,13 @@ var Parser = class {
|
|
|
2464
2530
|
this.advance();
|
|
2465
2531
|
return { type: "STRING", value: tok.value };
|
|
2466
2532
|
}
|
|
2467
|
-
if (tok.kind
|
|
2533
|
+
if (isContextualFunctionToken(tok.kind)) {
|
|
2468
2534
|
this.advance();
|
|
2469
2535
|
this.expect("(" /* LPAREN */);
|
|
2470
2536
|
this.expect(")" /* RPAREN */);
|
|
2471
2537
|
return {
|
|
2472
2538
|
type: "KINTONE_FUNC",
|
|
2473
|
-
name: tok.
|
|
2539
|
+
name: PARSER_CONTEXTUAL_FUNCTION_TOKEN_MAP[tok.kind]
|
|
2474
2540
|
};
|
|
2475
2541
|
}
|
|
2476
2542
|
if (tok.kind === "CASE" /* CASE */) {
|
|
@@ -3267,7 +3333,7 @@ var Parser = class {
|
|
|
3267
3333
|
}
|
|
3268
3334
|
if (tok.kind === "VARIABLE" /* VARIABLE */) return this.parseSqlValue();
|
|
3269
3335
|
if (tok.kind === "STRING" /* STRING */) return this.parseSqlValue();
|
|
3270
|
-
if (tok.kind
|
|
3336
|
+
if (isContextualFunctionToken(tok.kind)) return this.parseSqlValue();
|
|
3271
3337
|
if (tok.kind === "IN" /* IN */) return this.parseSqlValue();
|
|
3272
3338
|
if (tok.kind === "CASE" /* CASE */ || tok.kind === "IF" /* IF */) {
|
|
3273
3339
|
return this.parseSqlValue();
|
|
@@ -3549,54 +3615,105 @@ function writesKintone(stmt) {
|
|
|
3549
3615
|
function isReadOnlyStatement(stmt) {
|
|
3550
3616
|
return !writesKintone(stmt) && (isReadOnlyType(stmt.type) || isDmlType(stmt.type));
|
|
3551
3617
|
}
|
|
3552
|
-
|
|
3553
|
-
|
|
3618
|
+
var STATISTICAL_AGGREGATES = /* @__PURE__ */ new Set([
|
|
3619
|
+
"STDDEV_POP",
|
|
3620
|
+
"STDDEV_SAMP",
|
|
3621
|
+
"VAR_POP",
|
|
3622
|
+
"VAR_SAMP",
|
|
3623
|
+
"MEDIAN",
|
|
3624
|
+
"MODE"
|
|
3625
|
+
]);
|
|
3626
|
+
function addReasons(target, source) {
|
|
3627
|
+
for (const reason of source) target.add(reason);
|
|
3628
|
+
}
|
|
3629
|
+
function containsStatisticalAggregate(value, seen = /* @__PURE__ */ new Set()) {
|
|
3630
|
+
if (value === null || typeof value !== "object") return false;
|
|
3631
|
+
if (seen.has(value)) return false;
|
|
3632
|
+
seen.add(value);
|
|
3633
|
+
const record = value;
|
|
3634
|
+
if ((record.type === "AGGREGATE" || record.type === "AGG_REF") && typeof record.func === "string" && STATISTICAL_AGGREGATES.has(record.func)) return true;
|
|
3635
|
+
if (record.type === "FIELD" && typeof record.field === "string" && /^(STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/i.test(record.field)) return true;
|
|
3636
|
+
return Object.values(record).some((child) => Array.isArray(child) ? child.some((entry) => containsStatisticalAggregate(entry, seen)) : containsStatisticalAggregate(child, seen));
|
|
3637
|
+
}
|
|
3638
|
+
function completeInputReasons(stmt) {
|
|
3639
|
+
const reasons = /* @__PURE__ */ new Set();
|
|
3640
|
+
if (isDmlType(stmt.type)) {
|
|
3641
|
+
reasons.add("DML");
|
|
3642
|
+
return reasons;
|
|
3643
|
+
}
|
|
3554
3644
|
switch (stmt.type) {
|
|
3555
3645
|
case "VALIDATE":
|
|
3556
|
-
|
|
3646
|
+
reasons.add("VALIDATE");
|
|
3647
|
+
break;
|
|
3557
3648
|
case "SELECT":
|
|
3558
|
-
|
|
3649
|
+
addReasons(reasons, selectCompleteInputReasons(stmt));
|
|
3650
|
+
break;
|
|
3559
3651
|
case "UNION":
|
|
3560
|
-
|
|
3652
|
+
addReasons(reasons, unionCompleteInputReasons(stmt));
|
|
3653
|
+
break;
|
|
3561
3654
|
case "WITH":
|
|
3562
|
-
|
|
3563
|
-
(
|
|
3564
|
-
|
|
3655
|
+
for (const cte of stmt.ctes) {
|
|
3656
|
+
addReasons(reasons, completeInputReasons(cte.query));
|
|
3657
|
+
}
|
|
3658
|
+
addReasons(reasons, completeInputReasons(stmt.query));
|
|
3659
|
+
break;
|
|
3565
3660
|
case "CREATE_TEMP_TABLE":
|
|
3566
|
-
|
|
3661
|
+
addReasons(reasons, completeInputReasons(stmt.query));
|
|
3662
|
+
break;
|
|
3567
3663
|
default:
|
|
3568
|
-
|
|
3664
|
+
break;
|
|
3569
3665
|
}
|
|
3666
|
+
if (containsStatisticalAggregate(stmt)) reasons.add("STATISTICAL_AGGREGATE");
|
|
3667
|
+
return reasons;
|
|
3570
3668
|
}
|
|
3571
|
-
function
|
|
3572
|
-
|
|
3573
|
-
return left || selectRequiresCompleteInput(stmt.right);
|
|
3669
|
+
function requiresCompleteInput(stmt) {
|
|
3670
|
+
return completeInputReasons(stmt).size > 0;
|
|
3574
3671
|
}
|
|
3575
|
-
function
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
(branch) => whereRequiresCompleteInput(branch.condition)
|
|
3580
|
-
)
|
|
3581
|
-
)) return true;
|
|
3582
|
-
return whereRequiresCompleteInput(stmt.where) || whereRequiresCompleteInput(stmt.having);
|
|
3672
|
+
function unionCompleteInputReasons(stmt) {
|
|
3673
|
+
const reasons = stmt.left.type === "SELECT" ? selectCompleteInputReasons(stmt.left) : unionCompleteInputReasons(stmt.left);
|
|
3674
|
+
addReasons(reasons, selectCompleteInputReasons(stmt.right));
|
|
3675
|
+
return reasons;
|
|
3583
3676
|
}
|
|
3584
|
-
function
|
|
3585
|
-
|
|
3677
|
+
function selectCompleteInputReasons(stmt) {
|
|
3678
|
+
const reasons = /* @__PURE__ */ new Set();
|
|
3679
|
+
if (stmt.orderBy.length > 0) reasons.add("LOCAL_ORDER");
|
|
3680
|
+
for (const column of stmt.columns) {
|
|
3681
|
+
if (column.type === "WINDOW_COL" && column.orderBy.length > 0) reasons.add("WINDOW_ORDER");
|
|
3682
|
+
if (column.type === "SCALAR_SUBQUERY_COL") addReasons(reasons, selectCompleteInputReasons(column.query));
|
|
3683
|
+
if (column.type === "CASE_COL") {
|
|
3684
|
+
for (const branch of column.expr.branches) addReasons(reasons, whereCompleteInputReasons(branch.condition));
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
addReasons(reasons, whereCompleteInputReasons(stmt.where));
|
|
3688
|
+
addReasons(reasons, whereCompleteInputReasons(stmt.having));
|
|
3689
|
+
if (containsStatisticalAggregate(stmt)) reasons.add("STATISTICAL_AGGREGATE");
|
|
3690
|
+
return reasons;
|
|
3691
|
+
}
|
|
3692
|
+
function whereCompleteInputReasons(where) {
|
|
3693
|
+
const reasons = /* @__PURE__ */ new Set();
|
|
3694
|
+
if (where === null) return reasons;
|
|
3586
3695
|
switch (where.type) {
|
|
3587
3696
|
case "BINARY":
|
|
3588
|
-
|
|
3697
|
+
if (where.right.type === "SUBQUERY_IN_LIST" || where.right.type === "SCALAR_SUBQUERY") {
|
|
3698
|
+
addReasons(reasons, selectCompleteInputReasons(where.right.query));
|
|
3699
|
+
}
|
|
3700
|
+
break;
|
|
3589
3701
|
case "LOGICAL":
|
|
3590
|
-
|
|
3702
|
+
addReasons(reasons, whereCompleteInputReasons(where.left));
|
|
3703
|
+
addReasons(reasons, whereCompleteInputReasons(where.right));
|
|
3704
|
+
break;
|
|
3591
3705
|
case "NOT":
|
|
3592
3706
|
case "GROUP":
|
|
3593
|
-
|
|
3707
|
+
addReasons(reasons, whereCompleteInputReasons(where.expr));
|
|
3708
|
+
break;
|
|
3594
3709
|
case "EXISTS":
|
|
3595
|
-
|
|
3710
|
+
addReasons(reasons, selectCompleteInputReasons(where.query));
|
|
3711
|
+
break;
|
|
3596
3712
|
case "NULL_CHECK":
|
|
3597
3713
|
case "BOOLEAN":
|
|
3598
|
-
|
|
3714
|
+
break;
|
|
3599
3715
|
}
|
|
3716
|
+
return reasons;
|
|
3600
3717
|
}
|
|
3601
3718
|
function hasWhereClause(stmt) {
|
|
3602
3719
|
if (!stmt || typeof stmt !== "object") return false;
|
|
@@ -4922,7 +5039,7 @@ function scalarValueLabel(expr) {
|
|
|
4922
5039
|
}
|
|
4923
5040
|
}
|
|
4924
5041
|
function isAggregateSyntheticName(name) {
|
|
4925
|
-
return /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT)\(/i.test(name);
|
|
5042
|
+
return /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/i.test(name);
|
|
4926
5043
|
}
|
|
4927
5044
|
|
|
4928
5045
|
// src/core/cteInlining.ts
|
|
@@ -5903,7 +6020,7 @@ function evalArithExpr(expr, row) {
|
|
|
5903
6020
|
return r !== 0 ? l % r : NaN;
|
|
5904
6021
|
}
|
|
5905
6022
|
}
|
|
5906
|
-
function evalScalarValueExpr(expr, row) {
|
|
6023
|
+
function evalScalarValueExpr(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
5907
6024
|
switch (expr.type) {
|
|
5908
6025
|
case "STRING":
|
|
5909
6026
|
return expr.value;
|
|
@@ -5914,19 +6031,19 @@ function evalScalarValueExpr(expr, row) {
|
|
|
5914
6031
|
case "VARIABLE":
|
|
5915
6032
|
throw new Error(`ArgumentError: unresolved variable @${expr.name} reached scalar evaluator.`);
|
|
5916
6033
|
case "STRING_FUNC":
|
|
5917
|
-
return evalStringFunc(expr, row);
|
|
6034
|
+
return evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
5918
6035
|
case "CASE_WHEN":
|
|
5919
|
-
return evalCaseWhen(expr, row);
|
|
6036
|
+
return evalCaseWhen(expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
5920
6037
|
case "CONCAT_OP": {
|
|
5921
6038
|
return evalStringFunc({
|
|
5922
6039
|
type: "STRING_FUNC",
|
|
5923
6040
|
func: "CONCAT",
|
|
5924
6041
|
args: [expr.left, expr.right]
|
|
5925
|
-
}, row);
|
|
6042
|
+
}, row, resolveFieldType, resolveFieldSemantics2);
|
|
5926
6043
|
}
|
|
5927
6044
|
case "SCALAR_ARITH": {
|
|
5928
|
-
const left = Number(evalScalarValueExpr(expr.left, row));
|
|
5929
|
-
const right = Number(evalScalarValueExpr(expr.right, row));
|
|
6045
|
+
const left = Number(evalScalarValueExpr(expr.left, row, resolveFieldType, resolveFieldSemantics2));
|
|
6046
|
+
const right = Number(evalScalarValueExpr(expr.right, row, resolveFieldType, resolveFieldSemantics2));
|
|
5930
6047
|
switch (expr.op) {
|
|
5931
6048
|
case "+":
|
|
5932
6049
|
return left + right;
|
|
@@ -6091,8 +6208,8 @@ function replaceNthMatch(input, globalRe, replacement, n) {
|
|
|
6091
6208
|
return expandRegexpReplacement(replacement, match, captures, namedGroups);
|
|
6092
6209
|
});
|
|
6093
6210
|
}
|
|
6094
|
-
function evalStringFunc(expr, row) {
|
|
6095
|
-
const args = expr.args.map((a) => evalStringFuncArg(a, row));
|
|
6211
|
+
function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
6212
|
+
const args = expr.args.map((a) => evalStringFuncArg(a, row, resolveFieldType, resolveFieldSemantics2));
|
|
6096
6213
|
switch (expr.func) {
|
|
6097
6214
|
case "UPPER":
|
|
6098
6215
|
return (args[0] ?? "").toUpperCase();
|
|
@@ -6225,6 +6342,15 @@ function evalStringFunc(expr, row) {
|
|
|
6225
6342
|
const d = args[0] ?? "";
|
|
6226
6343
|
return d.length >= 10 ? String(parseInt(d.slice(8, 10), 10)) : "";
|
|
6227
6344
|
}
|
|
6345
|
+
case "DAYOFWEEK":
|
|
6346
|
+
assertArity(expr.func, args, 1, 1);
|
|
6347
|
+
return isValidYmd(args[0]) ? String(dayOfWeekIndex(args[0]) + 1) : "";
|
|
6348
|
+
case "QUARTER":
|
|
6349
|
+
assertArity(expr.func, args, 1, 1);
|
|
6350
|
+
return isValidYmd(args[0]) ? String(Math.ceil(Number(args[0].slice(5, 7)) / 3)) : "";
|
|
6351
|
+
case "WEEK":
|
|
6352
|
+
assertArity(expr.func, args, 1, 1);
|
|
6353
|
+
return isValidYmd(args[0]) ? String(isoWeekNumber(args[0])) : "";
|
|
6228
6354
|
case "DATE_FORMAT":
|
|
6229
6355
|
return applyDateFormat(args[0] ?? "", args[1] ?? "");
|
|
6230
6356
|
case "DATEDIFF":
|
|
@@ -6271,10 +6397,78 @@ function parseDateParts(s) {
|
|
|
6271
6397
|
sec: s.length >= 19 ? s.slice(17, 19) : "00"
|
|
6272
6398
|
};
|
|
6273
6399
|
}
|
|
6400
|
+
function ymdUtcDate(dateStr) {
|
|
6401
|
+
const date = /* @__PURE__ */ new Date(0);
|
|
6402
|
+
date.setUTCHours(0, 0, 0, 0);
|
|
6403
|
+
date.setUTCFullYear(
|
|
6404
|
+
Number(dateStr.slice(0, 4)),
|
|
6405
|
+
Number(dateStr.slice(5, 7)) - 1,
|
|
6406
|
+
Number(dateStr.slice(8, 10))
|
|
6407
|
+
);
|
|
6408
|
+
return date;
|
|
6409
|
+
}
|
|
6410
|
+
function isValidYmd(dateStr) {
|
|
6411
|
+
const ymd = dateStr.slice(0, 10);
|
|
6412
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(ymd)) return false;
|
|
6413
|
+
const date = ymdUtcDate(ymd);
|
|
6414
|
+
return date.getUTCFullYear() === Number(ymd.slice(0, 4)) && date.getUTCMonth() + 1 === Number(ymd.slice(5, 7)) && date.getUTCDate() === Number(ymd.slice(8, 10));
|
|
6415
|
+
}
|
|
6416
|
+
function dayOfWeekIndex(dateStr) {
|
|
6417
|
+
return ymdUtcDate(dateStr).getUTCDay();
|
|
6418
|
+
}
|
|
6419
|
+
function isoWeekThursday(dateStr) {
|
|
6420
|
+
const date = ymdUtcDate(dateStr);
|
|
6421
|
+
const isoDay = date.getUTCDay() || 7;
|
|
6422
|
+
date.setUTCDate(date.getUTCDate() + 4 - isoDay);
|
|
6423
|
+
return date;
|
|
6424
|
+
}
|
|
6425
|
+
function isoWeekYear(dateStr) {
|
|
6426
|
+
return isoWeekThursday(dateStr).getUTCFullYear();
|
|
6427
|
+
}
|
|
6428
|
+
function isoWeekNumber(dateStr) {
|
|
6429
|
+
const thursday = isoWeekThursday(dateStr);
|
|
6430
|
+
const year = thursday.getUTCFullYear();
|
|
6431
|
+
const jan4 = ymdUtcDate(`${String(year).padStart(4, "0")}-01-04`);
|
|
6432
|
+
const jan4IsoDay = jan4.getUTCDay() || 7;
|
|
6433
|
+
jan4.setUTCDate(jan4.getUTCDate() + 4 - jan4IsoDay);
|
|
6434
|
+
return 1 + Math.round((thursday.getTime() - jan4.getTime()) / (7 * 864e5));
|
|
6435
|
+
}
|
|
6274
6436
|
function applyDateFormat(dateStr, pattern) {
|
|
6275
6437
|
if (!dateStr || dateStr.length < 10) return "";
|
|
6276
6438
|
const { y, mo, d, h, mi, sec } = parseDateParts(dateStr);
|
|
6277
|
-
|
|
6439
|
+
const validYmd = isValidYmd(dateStr);
|
|
6440
|
+
return pattern.replace(/%[YymcdeHiswavG]/g, (specifier) => {
|
|
6441
|
+
switch (specifier) {
|
|
6442
|
+
case "%Y":
|
|
6443
|
+
return y;
|
|
6444
|
+
case "%y":
|
|
6445
|
+
return y.slice(2);
|
|
6446
|
+
case "%m":
|
|
6447
|
+
return mo;
|
|
6448
|
+
case "%c":
|
|
6449
|
+
return String(parseInt(mo, 10));
|
|
6450
|
+
case "%d":
|
|
6451
|
+
return d;
|
|
6452
|
+
case "%e":
|
|
6453
|
+
return String(parseInt(d, 10));
|
|
6454
|
+
case "%H":
|
|
6455
|
+
return h;
|
|
6456
|
+
case "%i":
|
|
6457
|
+
return mi;
|
|
6458
|
+
case "%s":
|
|
6459
|
+
return sec;
|
|
6460
|
+
case "%w":
|
|
6461
|
+
return validYmd ? String(dayOfWeekIndex(dateStr)) : "";
|
|
6462
|
+
case "%a":
|
|
6463
|
+
return validYmd ? ["\u65E5", "\u6708", "\u706B", "\u6C34", "\u6728", "\u91D1", "\u571F"][dayOfWeekIndex(dateStr)] : "";
|
|
6464
|
+
case "%v":
|
|
6465
|
+
return validYmd ? String(isoWeekNumber(dateStr)).padStart(2, "0") : "";
|
|
6466
|
+
case "%G":
|
|
6467
|
+
return validYmd ? String(isoWeekYear(dateStr)).padStart(4, "0") : "";
|
|
6468
|
+
default:
|
|
6469
|
+
return specifier;
|
|
6470
|
+
}
|
|
6471
|
+
});
|
|
6278
6472
|
}
|
|
6279
6473
|
function applyDateDiff(date1, date2) {
|
|
6280
6474
|
if (date1.length < 10 || date2.length < 10) return "0";
|
|
@@ -6343,10 +6537,10 @@ function formatWithComma(num, digits) {
|
|
|
6343
6537
|
const intFmt = intStr.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
6344
6538
|
return decStr ? `${intFmt}.${decStr}` : intFmt;
|
|
6345
6539
|
}
|
|
6346
|
-
function evalStringFuncArg(arg, row) {
|
|
6540
|
+
function evalStringFuncArg(arg, row, resolveFieldType, resolveFieldSemantics2) {
|
|
6347
6541
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return "";
|
|
6348
6542
|
if (arg.type === "NUMBER") return numberLiteralText(arg);
|
|
6349
|
-
return String(evalScalarValueExpr(arg, row));
|
|
6543
|
+
return String(evalScalarValueExpr(arg, row, resolveFieldType, resolveFieldSemantics2));
|
|
6350
6544
|
}
|
|
6351
6545
|
function resolveFieldRef(row, field) {
|
|
6352
6546
|
const direct = row[field];
|
|
@@ -6433,7 +6627,10 @@ var NUMERIC_STRING_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
|
6433
6627
|
"ABS",
|
|
6434
6628
|
"MOD",
|
|
6435
6629
|
"POWER",
|
|
6436
|
-
"SQRT"
|
|
6630
|
+
"SQRT",
|
|
6631
|
+
"DAYOFWEEK",
|
|
6632
|
+
"QUARTER",
|
|
6633
|
+
"WEEK"
|
|
6437
6634
|
]);
|
|
6438
6635
|
function semanticsForLeft(left, fieldType, resolveSemantics) {
|
|
6439
6636
|
if (left.type === "FIELD") {
|
|
@@ -6563,15 +6760,15 @@ function resolveValue(value, row, resolveFieldType, resolveFieldSemantics2) {
|
|
|
6563
6760
|
function evalCaseWhen(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
6564
6761
|
for (const branch of expr.branches) {
|
|
6565
6762
|
if (evalWhere(branch.condition, row, resolveFieldType, void 0, resolveFieldSemantics2)) {
|
|
6566
|
-
return evalCaseResult(branch.result, row);
|
|
6763
|
+
return evalCaseResult(branch.result, row, resolveFieldType, resolveFieldSemantics2);
|
|
6567
6764
|
}
|
|
6568
6765
|
}
|
|
6569
6766
|
if (expr.elseResult !== null) {
|
|
6570
|
-
return evalCaseResult(expr.elseResult, row);
|
|
6767
|
+
return evalCaseResult(expr.elseResult, row, resolveFieldType, resolveFieldSemantics2);
|
|
6571
6768
|
}
|
|
6572
6769
|
return "";
|
|
6573
6770
|
}
|
|
6574
|
-
function evalCaseResult(result, row) {
|
|
6771
|
+
function evalCaseResult(result, row, resolveFieldType, resolveFieldSemantics2) {
|
|
6575
6772
|
if (result.type === "ARRAY") return result.elements.map((e) => e.value).join(",");
|
|
6576
6773
|
if (result.type === "FIELD_REF") {
|
|
6577
6774
|
return row[result.field] ?? "";
|
|
@@ -6579,7 +6776,7 @@ function evalCaseResult(result, row) {
|
|
|
6579
6776
|
if (result.type === "ARITH") {
|
|
6580
6777
|
return String(evalArithExpr(result, row));
|
|
6581
6778
|
}
|
|
6582
|
-
return String(evalScalarValueExpr(result, row));
|
|
6779
|
+
return String(evalScalarValueExpr(result, row, resolveFieldType, resolveFieldSemantics2));
|
|
6583
6780
|
}
|
|
6584
6781
|
function resolveKintoneFunc(name) {
|
|
6585
6782
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -6652,7 +6849,7 @@ function collectRefs2(root) {
|
|
|
6652
6849
|
for (const value of Object.values(obj)) visit(value);
|
|
6653
6850
|
};
|
|
6654
6851
|
const add = (tableAlias, field) => {
|
|
6655
|
-
if (/^(COUNT|SUM|AVG|MIN|MAX|GROUP_CONCAT)\(/i.test(field)) {
|
|
6852
|
+
if (/^(COUNT|SUM|AVG|MIN|MAX|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/i.test(field)) {
|
|
6656
6853
|
throw customCheckParseError("CHECK \u306B\u96C6\u7D04\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093");
|
|
6657
6854
|
}
|
|
6658
6855
|
const key = `${tableAlias ?? ""}\0${field}`;
|
|
@@ -9468,6 +9665,9 @@ var REST_LIMIT_MAX = 500;
|
|
|
9468
9665
|
function fieldSemantics(item, semantics) {
|
|
9469
9666
|
return item.key.type === "FIELD_NAME" ? semantics.get(item.key.name) : void 0;
|
|
9470
9667
|
}
|
|
9668
|
+
function hasSelectOutputAlias(stmt, name) {
|
|
9669
|
+
return stmt.columns.some((column) => "alias" in column && column.alias === name);
|
|
9670
|
+
}
|
|
9471
9671
|
function planCanonicalOrder(input) {
|
|
9472
9672
|
const { stmt } = input;
|
|
9473
9673
|
const reasons = [];
|
|
@@ -9495,7 +9695,7 @@ function planCanonicalOrder(input) {
|
|
|
9495
9695
|
throw new Error(`ArgumentError: ORDER BY key has no canonical comparison contract (reason=${reason}).`);
|
|
9496
9696
|
}
|
|
9497
9697
|
const allRestEquivalent = stmt.orderBy.length > 0 && windowOrderBy.length === 0 && stmt.orderBy.every(
|
|
9498
|
-
(item) => item.key.type === "FIELD_NAME" && item.key.name === "$id"
|
|
9698
|
+
(item) => item.key.type === "FIELD_NAME" && item.key.name === "$id" && !hasSelectOutputAlias(stmt, item.key.name)
|
|
9499
9699
|
);
|
|
9500
9700
|
if (!allRestEquivalent) reasons.push("ORDER_KEY_NOT_REST_EQUIVALENT");
|
|
9501
9701
|
if (input.whereCapability !== "EXACT_PUSHDOWN") reasons.push("WHERE_NOT_EXACT");
|
|
@@ -9544,6 +9744,9 @@ var KORDER_NATIVE_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
|
9544
9744
|
"CREATOR",
|
|
9545
9745
|
"MODIFIER"
|
|
9546
9746
|
]);
|
|
9747
|
+
function hasSelectOutputAlias2(stmt, name) {
|
|
9748
|
+
return stmt.columns.some((column) => "alias" in column && column.alias === name);
|
|
9749
|
+
}
|
|
9547
9750
|
function planKorder(input) {
|
|
9548
9751
|
const { stmt } = input;
|
|
9549
9752
|
const reasons = [];
|
|
@@ -9565,6 +9768,10 @@ function planKorder(input) {
|
|
|
9565
9768
|
reasons.push(`KORDER_KEY_UNRESOLVED(field=${name})`);
|
|
9566
9769
|
continue;
|
|
9567
9770
|
}
|
|
9771
|
+
if (hasSelectOutputAlias2(stmt, name)) {
|
|
9772
|
+
reasons.push(`KORDER_KEY_NOT_DIRECT_FIELD(field=${name})`);
|
|
9773
|
+
continue;
|
|
9774
|
+
}
|
|
9568
9775
|
if (name === "$id") continue;
|
|
9569
9776
|
if (!semantics.source || semantics.source.fieldCode !== name) {
|
|
9570
9777
|
reasons.push(`KORDER_KEY_NOT_DIRECT_FIELD(field=${name})`);
|
|
@@ -9836,26 +10043,81 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
|
|
|
9836
10043
|
}
|
|
9837
10044
|
strValues.push(strVal);
|
|
9838
10045
|
}
|
|
9839
|
-
const
|
|
10046
|
+
const statistical = func === "STDDEV_POP" || func === "STDDEV_SAMP" || func === "VAR_POP" || func === "VAR_SAMP" || func === "MEDIAN";
|
|
10047
|
+
const numericValues = statistical ? strValues.map((value) => {
|
|
10048
|
+
const numeric = Number(value);
|
|
10049
|
+
if (!Number.isFinite(numeric)) {
|
|
10050
|
+
throw new Error(`ArgumentError: ${func} \u306E\u5F15\u6570\u306B\u975E\u6570\u5024\u307E\u305F\u306F\u975E\u6709\u9650\u306E\u5024\u304C\u3042\u308A\u307E\u3059: ${value}`);
|
|
10051
|
+
}
|
|
10052
|
+
return numeric;
|
|
10053
|
+
}) : null;
|
|
10054
|
+
const eff = distinct ? statistical ? [...new Set(numericValues)] : [...new Set(strValues)] : statistical ? numericValues : strValues;
|
|
9840
10055
|
if (func === "COUNT") return eff.length;
|
|
9841
10056
|
if (func === "GROUP_CONCAT") return eff.join(separator ?? ",");
|
|
9842
|
-
const comparison = (func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" ? resolveAggSortKind?.(toAggregateFieldRef(arg.field)) : void 0;
|
|
10057
|
+
const comparison = (func === "MIN" || func === "MAX" || func === "MODE") && arg.type === "FIELD_REF" ? resolveAggSortKind?.(toAggregateFieldRef(arg.field)) : void 0;
|
|
10058
|
+
const semantics = typeof comparison === "string" ? syntheticSemantics(comparison) : comparison ?? (arg.type === "FIELD_REF" ? syntheticSemantics("string") : syntheticSemantics("number"));
|
|
10059
|
+
if (func === "MODE") {
|
|
10060
|
+
if (strValues.length === 0) return "";
|
|
10061
|
+
const frequencies = /* @__PURE__ */ new Map();
|
|
10062
|
+
for (const value of strValues) frequencies.set(value, (frequencies.get(value) ?? 0) + 1);
|
|
10063
|
+
let result = "";
|
|
10064
|
+
let maxFrequency = 0;
|
|
10065
|
+
for (const [candidate, frequency] of frequencies) {
|
|
10066
|
+
if (frequency > maxFrequency) {
|
|
10067
|
+
result = candidate;
|
|
10068
|
+
maxFrequency = frequency;
|
|
10069
|
+
continue;
|
|
10070
|
+
}
|
|
10071
|
+
if (frequency !== maxFrequency) continue;
|
|
10072
|
+
const canonical = compareCanonicalValues(candidate, result, semantics);
|
|
10073
|
+
if (canonical < 0 || canonical === 0 && compareCodePointStrings(candidate, result) < 0) {
|
|
10074
|
+
result = candidate;
|
|
10075
|
+
}
|
|
10076
|
+
}
|
|
10077
|
+
return result;
|
|
10078
|
+
}
|
|
9843
10079
|
if (func === "MIN" || func === "MAX") {
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
let result =
|
|
9847
|
-
for (const candidate of
|
|
10080
|
+
const comparableValues = eff;
|
|
10081
|
+
if (comparableValues.length === 0) return 0;
|
|
10082
|
+
let result = comparableValues[0];
|
|
10083
|
+
for (const candidate of comparableValues.slice(1)) {
|
|
9848
10084
|
const cmp = compareCanonicalValues(candidate, result, semantics);
|
|
9849
10085
|
if (func === "MAX" && cmp > 0 || func === "MIN" && cmp < 0) result = candidate;
|
|
9850
10086
|
}
|
|
9851
10087
|
return result;
|
|
9852
10088
|
}
|
|
9853
|
-
const nums = eff.map(Number);
|
|
10089
|
+
const nums = statistical ? eff : eff.map(Number);
|
|
9854
10090
|
switch (func) {
|
|
9855
10091
|
case "SUM":
|
|
9856
10092
|
return nums.reduce((a, b) => a + b, 0);
|
|
9857
10093
|
case "AVG":
|
|
9858
10094
|
return nums.length === 0 ? 0 : nums.reduce((a, b) => a + b, 0) / nums.length;
|
|
10095
|
+
case "MEDIAN": {
|
|
10096
|
+
if (nums.length === 0) return "";
|
|
10097
|
+
const sorted = [...nums].sort((a, b) => a - b);
|
|
10098
|
+
const middle = Math.floor(sorted.length / 2);
|
|
10099
|
+
return sorted.length % 2 === 1 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
|
|
10100
|
+
}
|
|
10101
|
+
case "VAR_POP":
|
|
10102
|
+
case "VAR_SAMP":
|
|
10103
|
+
case "STDDEV_POP":
|
|
10104
|
+
case "STDDEV_SAMP": {
|
|
10105
|
+
const sample = func === "VAR_SAMP" || func === "STDDEV_SAMP";
|
|
10106
|
+
if (nums.length === 0 || sample && nums.length < 2) return "";
|
|
10107
|
+
const origin = nums[0];
|
|
10108
|
+
let count = 0;
|
|
10109
|
+
let mean = 0;
|
|
10110
|
+
let m2 = 0;
|
|
10111
|
+
for (const rawValue of nums) {
|
|
10112
|
+
const value = rawValue - origin;
|
|
10113
|
+
count++;
|
|
10114
|
+
const delta = value - mean;
|
|
10115
|
+
mean += delta / count;
|
|
10116
|
+
m2 += delta * (value - mean);
|
|
10117
|
+
}
|
|
10118
|
+
const variance = Math.max(0, m2 / (sample ? count - 1 : count));
|
|
10119
|
+
return func === "STDDEV_POP" || func === "STDDEV_SAMP" ? Math.sqrt(variance) : variance;
|
|
10120
|
+
}
|
|
9859
10121
|
}
|
|
9860
10122
|
}
|
|
9861
10123
|
function toAggregateFieldRef(field) {
|
|
@@ -9947,11 +10209,11 @@ function buildDistinctKeyBuilder(rows, columns) {
|
|
|
9947
10209
|
return JSON.stringify(values);
|
|
9948
10210
|
};
|
|
9949
10211
|
}
|
|
9950
|
-
function applyOrderBy(rows, orderBy, optionOrders, sortKinds, fieldSemantics2) {
|
|
10212
|
+
function applyOrderBy(rows, orderBy, optionOrders, sortKinds, fieldSemantics2, aliasEvaluator) {
|
|
9951
10213
|
if (orderBy.length === 0) return rows;
|
|
9952
|
-
return sortDecoratedRows(rows, orderBy, optionOrders, sortKinds, fieldSemantics2).rows.map((item) => item.row);
|
|
10214
|
+
return sortDecoratedRows(rows, orderBy, optionOrders, sortKinds, fieldSemantics2, aliasEvaluator).rows.map((item) => item.row);
|
|
9953
10215
|
}
|
|
9954
|
-
function sortDecoratedRows(rows, orderBy, optionOrders, sortKinds, fieldSemantics2) {
|
|
10216
|
+
function sortDecoratedRows(rows, orderBy, optionOrders, sortKinds, fieldSemantics2, aliasEvaluator) {
|
|
9955
10217
|
const keyMeta = orderBy.map(({ key }) => {
|
|
9956
10218
|
if (key.type === "ARITH_KEY") return { semantics: syntheticSemantics("number") };
|
|
9957
10219
|
if (key.type === "FUNC_KEY") {
|
|
@@ -9976,7 +10238,7 @@ function sortDecoratedRows(rows, orderBy, optionOrders, sortKinds, fieldSemantic
|
|
|
9976
10238
|
const decorated = rows.map((row) => ({
|
|
9977
10239
|
row,
|
|
9978
10240
|
keys: orderBy.map(({ key }, i) => {
|
|
9979
|
-
const s = evalOrderKey(key, row);
|
|
10241
|
+
const s = evalOrderKey(key, row, aliasEvaluator);
|
|
9980
10242
|
return { s };
|
|
9981
10243
|
})
|
|
9982
10244
|
}));
|
|
@@ -10009,18 +10271,71 @@ var NUMERIC_ORDER_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
|
10009
10271
|
"ABS",
|
|
10010
10272
|
"MOD",
|
|
10011
10273
|
"POWER",
|
|
10012
|
-
"SQRT"
|
|
10274
|
+
"SQRT",
|
|
10275
|
+
"DAYOFWEEK",
|
|
10276
|
+
"QUARTER",
|
|
10277
|
+
"WEEK"
|
|
10013
10278
|
]);
|
|
10014
|
-
function evalOrderKey(key, row) {
|
|
10279
|
+
function evalOrderKey(key, row, aliasEvaluator) {
|
|
10015
10280
|
switch (key.type) {
|
|
10016
10281
|
case "FIELD_NAME":
|
|
10017
|
-
return row[key.name] ?? "";
|
|
10282
|
+
return aliasEvaluator?.(key.name, row) ?? row[key.name] ?? "";
|
|
10018
10283
|
case "ARITH_KEY":
|
|
10019
10284
|
return String(evalArithExpr(key.expr, row));
|
|
10020
10285
|
case "FUNC_KEY":
|
|
10021
10286
|
return evalStringFunc(key.expr, row);
|
|
10022
10287
|
}
|
|
10023
10288
|
}
|
|
10289
|
+
function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, resolveFieldSemantics2) {
|
|
10290
|
+
const evaluators = /* @__PURE__ */ new Map();
|
|
10291
|
+
for (const [columnIndex, column] of columns.entries()) {
|
|
10292
|
+
if (!("alias" in column) || column.alias === null) continue;
|
|
10293
|
+
const alias = column.alias;
|
|
10294
|
+
switch (column.type) {
|
|
10295
|
+
case "FIELD":
|
|
10296
|
+
evaluators.set(alias, (row) => resolveFieldRef(row, column.field));
|
|
10297
|
+
break;
|
|
10298
|
+
case "LITERAL_COL":
|
|
10299
|
+
evaluators.set(alias, () => column.value);
|
|
10300
|
+
break;
|
|
10301
|
+
case "AGGREGATE": {
|
|
10302
|
+
const source = aggregateSyntheticName2(column.func, column.distinct, column.arg);
|
|
10303
|
+
evaluators.set(alias, (row) => row[alias] ?? row[source] ?? "0");
|
|
10304
|
+
break;
|
|
10305
|
+
}
|
|
10306
|
+
case "ARITH_AGG_COL": {
|
|
10307
|
+
const source = aggArithDefaultKey(column.expr);
|
|
10308
|
+
evaluators.set(alias, (row) => row[alias] ?? row[source] ?? "0");
|
|
10309
|
+
break;
|
|
10310
|
+
}
|
|
10311
|
+
case "WINDOW_COL":
|
|
10312
|
+
evaluators.set(alias, (row) => row[alias] ?? "");
|
|
10313
|
+
break;
|
|
10314
|
+
case "ARITH_COL":
|
|
10315
|
+
evaluators.set(alias, (row) => String(evalArithExpr(column.expr, row)));
|
|
10316
|
+
break;
|
|
10317
|
+
case "STRFUNC_COL": {
|
|
10318
|
+
const source = stringFuncDefaultKey(column.expr);
|
|
10319
|
+
evaluators.set(alias, (row) => hasAggregateInStringFuncExpr2(column.expr) ? row[alias] ?? row[source] ?? evalStringFunc(column.expr, row, resolveFieldType, resolveFieldSemantics2) : evalStringFunc(column.expr, row, resolveFieldType, resolveFieldSemantics2));
|
|
10320
|
+
break;
|
|
10321
|
+
}
|
|
10322
|
+
case "CASE_COL":
|
|
10323
|
+
evaluators.set(alias, (row) => evalCaseWhen(column.expr, row, resolveFieldType, resolveFieldSemantics2));
|
|
10324
|
+
break;
|
|
10325
|
+
case "SCALAR_VALUE_COL": {
|
|
10326
|
+
const source = scalarValueDefaultKey(column.expr);
|
|
10327
|
+
evaluators.set(alias, (row) => scalarValueHasAggregate2(column.expr) ? row[alias] ?? row[source] ?? "" : String(evalScalarValueExpr(column.expr, row, resolveFieldType, resolveFieldSemantics2)));
|
|
10328
|
+
break;
|
|
10329
|
+
}
|
|
10330
|
+
case "SCALAR_SUBQUERY_COL":
|
|
10331
|
+
evaluators.set(alias, () => scalarCache?.get(columnIndex) ?? "");
|
|
10332
|
+
break;
|
|
10333
|
+
case "VARIABLE_COL":
|
|
10334
|
+
break;
|
|
10335
|
+
}
|
|
10336
|
+
}
|
|
10337
|
+
return (name, row) => evaluators.get(name)?.(row);
|
|
10338
|
+
}
|
|
10024
10339
|
function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2) {
|
|
10025
10340
|
const windows = columns.filter((column) => column.type === "WINDOW_COL");
|
|
10026
10341
|
if (rows.length === 0 || windows.length === 0) return rows;
|
|
@@ -10138,9 +10453,9 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns, re
|
|
|
10138
10453
|
const key = outputKeys?.[colIdx] ?? col.alias ?? stringFuncDefaultKey(col.expr);
|
|
10139
10454
|
if (hasAggregateInStringFuncExpr2(col.expr)) {
|
|
10140
10455
|
const srcKey = stringFuncDefaultKey(col.expr);
|
|
10141
|
-
out[key] = row[col.alias ?? srcKey] ?? row[srcKey] ?? evalStringFunc(col.expr, row);
|
|
10456
|
+
out[key] = row[col.alias ?? srcKey] ?? row[srcKey] ?? evalStringFunc(col.expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
10142
10457
|
} else {
|
|
10143
|
-
out[key] = evalStringFunc(col.expr, row);
|
|
10458
|
+
out[key] = evalStringFunc(col.expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
10144
10459
|
}
|
|
10145
10460
|
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
10146
10461
|
break;
|
|
@@ -10148,7 +10463,7 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns, re
|
|
|
10148
10463
|
case "SCALAR_VALUE_COL": {
|
|
10149
10464
|
const key = outputKeys?.[colIdx] ?? col.alias ?? scalarValueDefaultKey(col.expr);
|
|
10150
10465
|
const srcKey = scalarValueDefaultKey(col.expr);
|
|
10151
|
-
out[key] = scalarValueHasAggregate2(col.expr) ? row[col.alias ?? srcKey] ?? row[srcKey] ?? "" : String(evalScalarValueExpr(col.expr, row));
|
|
10466
|
+
out[key] = scalarValueHasAggregate2(col.expr) ? row[col.alias ?? srcKey] ?? row[srcKey] ?? "" : String(evalScalarValueExpr(col.expr, row, resolveFieldType, resolveFieldSemantics2));
|
|
10152
10467
|
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
10153
10468
|
break;
|
|
10154
10469
|
}
|
|
@@ -10367,7 +10682,7 @@ function deriveOutputOrderSemantics(columns) {
|
|
|
10367
10682
|
if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL" || column.type === "WINDOW_COL") {
|
|
10368
10683
|
result.set(column.alias, syntheticSemantics("number"));
|
|
10369
10684
|
} else if (column.type === "AGGREGATE") {
|
|
10370
|
-
if (column.func === "COUNT" || column.func === "SUM" || column.func === "AVG") {
|
|
10685
|
+
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") {
|
|
10371
10686
|
result.set(column.alias, syntheticSemantics("number"));
|
|
10372
10687
|
} else if (column.func === "GROUP_CONCAT") {
|
|
10373
10688
|
result.set(column.alias, syntheticSemantics("string"));
|
|
@@ -10433,7 +10748,14 @@ function runFullScan(input) {
|
|
|
10433
10748
|
if (stmt.distinct) {
|
|
10434
10749
|
rows = applyDistinct(rows, stmt.columns);
|
|
10435
10750
|
}
|
|
10436
|
-
rows = applyOrderBy(
|
|
10751
|
+
rows = applyOrderBy(
|
|
10752
|
+
rows,
|
|
10753
|
+
stmt.orderBy,
|
|
10754
|
+
optionOrders,
|
|
10755
|
+
sortKinds,
|
|
10756
|
+
effectiveOrderSemantics,
|
|
10757
|
+
buildOrderByAliasEvaluator(stmt.columns, scalarCache, fieldTypeResolver, fieldSemanticsResolver)
|
|
10758
|
+
);
|
|
10437
10759
|
rows = applyLimit(rows, stmt.limit, stmt.offset);
|
|
10438
10760
|
return project(
|
|
10439
10761
|
rows,
|
|
@@ -12254,7 +12576,17 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
12254
12576
|
tempTables
|
|
12255
12577
|
);
|
|
12256
12578
|
const first = resolvedStmt2.expr.query.columns[0];
|
|
12257
|
-
|
|
12579
|
+
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");
|
|
12580
|
+
if (first?.type === "AGGREGATE" && first.func === "MODE") {
|
|
12581
|
+
const meta = (await inferSelectColumnMeta(
|
|
12582
|
+
resolvedStmt2.expr.query,
|
|
12583
|
+
["__scalar__"],
|
|
12584
|
+
client,
|
|
12585
|
+
cacheContext,
|
|
12586
|
+
tempTables
|
|
12587
|
+
)).get("__scalar__");
|
|
12588
|
+
numeric = meta?.semantics?.compareMode === "number" || meta?.sortKind === "number";
|
|
12589
|
+
}
|
|
12258
12590
|
const numberValue = numeric ? Number(value) : Number.NaN;
|
|
12259
12591
|
variables.set(stmt.name, numeric && Number.isFinite(numberValue) ? { type: "number", value: numberValue, raw: value } : { type: "string", value });
|
|
12260
12592
|
} catch (e) {
|
|
@@ -12789,7 +13121,7 @@ function buildHavingFieldSemanticsResolver(stmt, rowResolver) {
|
|
|
12789
13121
|
else if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL" || column.type === "WINDOW_COL") {
|
|
12790
13122
|
semantics = syntheticSemantics("number");
|
|
12791
13123
|
} else if (column.type === "AGGREGATE") {
|
|
12792
|
-
if (column.func === "MIN" || column.func === "MAX") {
|
|
13124
|
+
if (column.func === "MIN" || column.func === "MAX" || column.func === "MODE") {
|
|
12793
13125
|
semantics = column.arg.type === "FIELD_REF" ? rowResolver(aggregateFieldRef(column.arg.field)) : syntheticSemantics("number");
|
|
12794
13126
|
} else {
|
|
12795
13127
|
semantics = column.func === "GROUP_CONCAT" ? syntheticSemantics("string") : syntheticSemantics("number");
|
|
@@ -12872,7 +13204,8 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache, capt
|
|
|
12872
13204
|
client,
|
|
12873
13205
|
cacheContext
|
|
12874
13206
|
);
|
|
12875
|
-
const
|
|
13207
|
+
const completeReasons = orderPlan?.kind === "CANONICAL_REST_TOP_N" || orderPlan?.kind === "KORDER_NATIVE" || orderPlan?.kind === "KORDER_CURSOR" ? completeInputReasons({ ...stmt, orderBy: [] }) : completeInputReasons(stmt);
|
|
13208
|
+
const completeInputRequired = completeReasons.size > 0;
|
|
12876
13209
|
const truncateWasDisabled = completeInputRequired && options.onLimitReached === "truncate";
|
|
12877
13210
|
const effectiveOptions = truncateWasDisabled ? { ...options, onLimitReached: "error" } : options;
|
|
12878
13211
|
try {
|
|
@@ -12892,7 +13225,7 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache, capt
|
|
|
12892
13225
|
} catch (error) {
|
|
12893
13226
|
if (completeInputRequired && error instanceof FetchAllLimitError) {
|
|
12894
13227
|
throw new FetchAllLimitError(
|
|
12895
|
-
|
|
13228
|
+
completeInputErrorPrefix(completeReasons) + (truncateWasDisabled ? "onLimit=truncate\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002" : "") + error.message
|
|
12896
13229
|
);
|
|
12897
13230
|
}
|
|
12898
13231
|
throw error;
|
|
@@ -12902,6 +13235,11 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache, capt
|
|
|
12902
13235
|
}
|
|
12903
13236
|
return result;
|
|
12904
13237
|
}
|
|
13238
|
+
function completeInputErrorPrefix(reasons) {
|
|
13239
|
+
const reasonList = [...reasons].join(", ");
|
|
13240
|
+
const subject = reasons.size === 1 && reasons.has("STATISTICAL_AGGREGATE") ? "\u7D71\u8A08\u96C6\u7D04\u306E\u6B63\u3057\u3044\u7D50\u679C" : "ORDER BY\u306E\u6B63\u3057\u3044\u7D50\u679C";
|
|
13241
|
+
return `${subject}\u306B\u306F\u5B8C\u5168\u306A\u5019\u88DC\u96C6\u5408\u304C\u5FC5\u8981\u3067\u3059\u3002complete input reason: ${reasonList}\u3002`;
|
|
13242
|
+
}
|
|
12905
13243
|
function isConstantFalseWhere(where) {
|
|
12906
13244
|
return where?.type === "BOOLEAN" && where.value === false;
|
|
12907
13245
|
}
|
|
@@ -13041,7 +13379,13 @@ async function executeSimpleSelect(stmt, client, options, cacheContext, orderPla
|
|
|
13041
13379
|
stmt.orderBy,
|
|
13042
13380
|
orderMeta.optionOrders,
|
|
13043
13381
|
orderMeta.sortKinds,
|
|
13044
|
-
orderMeta.semantics
|
|
13382
|
+
orderMeta.semantics,
|
|
13383
|
+
buildOrderByAliasEvaluator(
|
|
13384
|
+
stmt.columns,
|
|
13385
|
+
void 0,
|
|
13386
|
+
fieldTypeResolvers.row,
|
|
13387
|
+
projectionSemanticsResolver
|
|
13388
|
+
)
|
|
13045
13389
|
);
|
|
13046
13390
|
rows = applyLimit(rows, stmt.limit, stmt.offset);
|
|
13047
13391
|
}
|
|
@@ -13227,7 +13571,7 @@ function aggregateFieldRef(field) {
|
|
|
13227
13571
|
return dot > 0 ? { type: "FIELD", tableAlias: field.slice(0, dot), field: field.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field };
|
|
13228
13572
|
}
|
|
13229
13573
|
function collectAggregateRef(func, arg, out) {
|
|
13230
|
-
if ((func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" && arg.field) {
|
|
13574
|
+
if ((func === "MIN" || func === "MAX" || func === "MODE") && arg.type === "FIELD_REF" && arg.field) {
|
|
13231
13575
|
out.push(aggregateFieldRef(arg.field));
|
|
13232
13576
|
}
|
|
13233
13577
|
}
|
|
@@ -13440,7 +13784,10 @@ var NUMBER_RETURNING_STRING_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
|
13440
13784
|
"ABS",
|
|
13441
13785
|
"MOD",
|
|
13442
13786
|
"POWER",
|
|
13443
|
-
"SQRT"
|
|
13787
|
+
"SQRT",
|
|
13788
|
+
"DAYOFWEEK",
|
|
13789
|
+
"QUARTER",
|
|
13790
|
+
"WEEK"
|
|
13444
13791
|
]);
|
|
13445
13792
|
function stringFunctionColumnMeta(expr) {
|
|
13446
13793
|
if (expr.func === "CAST") {
|
|
@@ -13481,7 +13828,7 @@ function mergeExpressionColumnMeta(candidates) {
|
|
|
13481
13828
|
}
|
|
13482
13829
|
function selectNeedsSourceColumnMeta(stmt) {
|
|
13483
13830
|
return stmt.columns.some(
|
|
13484
|
-
(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.arg.type === "FIELD_REF"
|
|
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") && column.arg.type === "FIELD_REF"
|
|
13485
13832
|
);
|
|
13486
13833
|
}
|
|
13487
13834
|
async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext, materializedTables) {
|
|
@@ -13550,11 +13897,13 @@ async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext,
|
|
|
13550
13897
|
} else if (column.type === "AGGREGATE") {
|
|
13551
13898
|
if (column.func === "GROUP_CONCAT") {
|
|
13552
13899
|
meta = syntheticColumnMeta("string");
|
|
13553
|
-
} else if (column.func === "COUNT" || column.func === "SUM" || column.func === "AVG") {
|
|
13900
|
+
} 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") {
|
|
13554
13901
|
meta = syntheticColumnMeta("number");
|
|
13555
|
-
} else if ((column.func === "MIN" || column.func === "MAX") && column.arg.type === "FIELD_REF") {
|
|
13902
|
+
} else if ((column.func === "MIN" || column.func === "MAX" || column.func === "MODE") && column.arg.type === "FIELD_REF") {
|
|
13556
13903
|
const source = resolveField2(aggregateFieldRef(column.arg.field));
|
|
13557
13904
|
if (source) meta = source;
|
|
13905
|
+
} else if (column.func === "MODE") {
|
|
13906
|
+
meta = syntheticColumnMeta("number");
|
|
13558
13907
|
}
|
|
13559
13908
|
} else if (column.type === "ARITH_AGG_COL" || column.type === "ARITH_COL") {
|
|
13560
13909
|
meta = syntheticColumnMeta("number");
|
|
@@ -14319,7 +14668,7 @@ async function buildOrderSemanticsForSelect(stmt, client, cacheContext, material
|
|
|
14319
14668
|
if (column.expr.elseResult) candidates.push(caseResultColumnMeta(column.expr.elseResult, resolveField2));
|
|
14320
14669
|
meta = mergeExpressionColumnMeta(candidates);
|
|
14321
14670
|
} else if (column.type === "AGGREGATE") {
|
|
14322
|
-
if (column.func === "MIN" || column.func === "MAX") {
|
|
14671
|
+
if (column.func === "MIN" || column.func === "MAX" || column.func === "MODE") {
|
|
14323
14672
|
meta = column.arg.type === "FIELD_REF" ? resolveField2(aggregateFieldRef(column.arg.field)) : syntheticColumnMeta("number");
|
|
14324
14673
|
} else {
|
|
14325
14674
|
meta = column.func === "GROUP_CONCAT" ? syntheticColumnMeta("string") : syntheticColumnMeta("number");
|
|
@@ -17834,8 +18183,13 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans) {
|
|
|
17834
18183
|
lines.push(` scan rows: ${orderPlan.scanRows}`);
|
|
17835
18184
|
}
|
|
17836
18185
|
}
|
|
17837
|
-
|
|
17838
|
-
|
|
18186
|
+
const explainedStmt = orderPlan && !orderPlan.requiresCompleteInput ? { ...stmt, orderBy: [] } : stmt;
|
|
18187
|
+
const completeReasons = completeInputReasons(explainedStmt);
|
|
18188
|
+
if (orderPlan?.requiresCompleteInput) completeReasons.add("LOCAL_ORDER");
|
|
18189
|
+
if (completeReasons.size > 0) {
|
|
18190
|
+
lines.push(" complete input: required (onLimit=truncate disabled)");
|
|
18191
|
+
lines.push(` complete input reason: ${[...completeReasons].join(", ")}`);
|
|
18192
|
+
lines.push(" onLimit=truncate: disabled");
|
|
17839
18193
|
}
|
|
17840
18194
|
if (mode === "FULL_SCAN" && reasons.length > 0) {
|
|
17841
18195
|
lines.push(` reason: ${reasons.join(", ")}`);
|