@rex0220/kintone-sql-tools 3.10.0 → 3.12.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 +218 -103
- package/dist-mcp/ksql-mcp.js +356 -127
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,6 +71,8 @@ npm run build:plugin
|
|
|
71
71
|
- 一時テーブルで中間結果をサーバー内に保持し、AI のコンテキスト消費を抑えたい場合
|
|
72
72
|
- validation / EXPLAIN で論理名から最終的な物理アプリ ID への解決を確認したい場合
|
|
73
73
|
|
|
74
|
+
言語リファレンス・レシピは MCP resources(`ksql://language-reference` / `ksql://recipes`)に加えて、read-only ツール **`ksql_docs`** でも読めます。中継環境(リモート接続のプロキシ等)が resources を通さないクライアントでは、`ksql_docs` を引数なしで呼ぶと全章キーの索引が返るので、必要な章だけ `{"section":"language-reference/05-string-number-functions"}` の形で取得してください。
|
|
75
|
+
|
|
74
76
|
注意:
|
|
75
77
|
|
|
76
78
|
- `APP@profile` と `LAPP_<NAME>[@profile]` は Node.js runtime(CLI / MCP)の拡張です。plugin 側では非対応です。
|
package/dist-cli/ksql.js
CHANGED
|
@@ -577,6 +577,87 @@ function numberLiteralText(node) {
|
|
|
577
577
|
|
|
578
578
|
// src/parser/parser.ts
|
|
579
579
|
var MAX_BATCH_STATEMENTS = 20;
|
|
580
|
+
var PARSER_SCALAR_FUNCTION_TOKEN_MAP = Object.freeze({
|
|
581
|
+
["UPPER" /* UPPER */]: "UPPER",
|
|
582
|
+
["LOWER" /* LOWER */]: "LOWER",
|
|
583
|
+
["TRIM" /* TRIM */]: "TRIM",
|
|
584
|
+
["LTRIM" /* LTRIM */]: "LTRIM",
|
|
585
|
+
["RTRIM" /* RTRIM */]: "RTRIM",
|
|
586
|
+
["LENGTH" /* LENGTH */]: "LENGTH",
|
|
587
|
+
["LENGTH_CHAR" /* LENGTH_CHAR */]: "LENGTH_CHAR",
|
|
588
|
+
["SUBSTRING" /* SUBSTRING */]: "SUBSTRING",
|
|
589
|
+
["SUBSTR" /* SUBSTR */]: "SUBSTRING",
|
|
590
|
+
["LEFT" /* LEFT */]: "LEFT",
|
|
591
|
+
["RIGHT" /* RIGHT */]: "RIGHT",
|
|
592
|
+
["INSTR" /* INSTR */]: "INSTR",
|
|
593
|
+
["CONCAT" /* CONCAT */]: "CONCAT",
|
|
594
|
+
["REPLACE" /* REPLACE */]: "REPLACE",
|
|
595
|
+
["REGEXP_LIKE" /* REGEXP_LIKE */]: "REGEXP_LIKE",
|
|
596
|
+
["REGEXP_REPLACE" /* REGEXP_REPLACE */]: "REGEXP_REPLACE",
|
|
597
|
+
["REGEXP_SUBSTR" /* REGEXP_SUBSTR */]: "REGEXP_SUBSTR",
|
|
598
|
+
["TRANSLATE" /* TRANSLATE */]: "TRANSLATE",
|
|
599
|
+
["COALESCE" /* COALESCE */]: "COALESCE",
|
|
600
|
+
["ISNULL" /* ISNULL */]: "ISNULL",
|
|
601
|
+
["NULLIF" /* NULLIF */]: "NULLIF",
|
|
602
|
+
["GREATEST" /* GREATEST */]: "GREATEST",
|
|
603
|
+
["LEAST" /* LEAST */]: "LEAST",
|
|
604
|
+
["LPAD" /* LPAD */]: "LPAD",
|
|
605
|
+
["RPAD" /* RPAD */]: "RPAD",
|
|
606
|
+
["ROUND" /* ROUND */]: "ROUND",
|
|
607
|
+
["FLOOR" /* FLOOR */]: "FLOOR",
|
|
608
|
+
["CEIL" /* CEIL */]: "CEIL",
|
|
609
|
+
["CEILING" /* CEILING */]: "CEIL",
|
|
610
|
+
["TRUNCATE" /* TRUNCATE */]: "TRUNCATE",
|
|
611
|
+
["TRUNC" /* TRUNC */]: "TRUNCATE",
|
|
612
|
+
["ABS" /* ABS */]: "ABS",
|
|
613
|
+
["MOD" /* MOD */]: "MOD",
|
|
614
|
+
["POWER" /* POWER */]: "POWER",
|
|
615
|
+
["POW" /* POW */]: "POWER",
|
|
616
|
+
["SQRT" /* SQRT */]: "SQRT",
|
|
617
|
+
["FORMAT" /* FORMAT */]: "FORMAT",
|
|
618
|
+
["CAST" /* CAST */]: "CAST",
|
|
619
|
+
["CONVERT" /* CONVERT */]: "CAST",
|
|
620
|
+
["YEAR" /* YEAR */]: "YEAR",
|
|
621
|
+
["MONTH" /* MONTH */]: "MONTH",
|
|
622
|
+
["DAY" /* DAY */]: "DAY",
|
|
623
|
+
["DATE_FORMAT" /* DATE_FORMAT */]: "DATE_FORMAT",
|
|
624
|
+
["DATEDIFF" /* DATEDIFF */]: "DATEDIFF",
|
|
625
|
+
["DATE_ADD" /* DATE_ADD */]: "DATE_ADD",
|
|
626
|
+
["LAST_DAY" /* LAST_DAY */]: "LAST_DAY"
|
|
627
|
+
});
|
|
628
|
+
var PARSER_IDENT_SCALAR_FUNCTIONS = Object.freeze([
|
|
629
|
+
"CURRENT_DATE",
|
|
630
|
+
"CURRENT_TIMESTAMP"
|
|
631
|
+
]);
|
|
632
|
+
var PARSER_AGGREGATE_FUNCTION_TOKEN_MAP = Object.freeze({
|
|
633
|
+
["COUNT" /* COUNT */]: "COUNT",
|
|
634
|
+
["SUM" /* SUM */]: "SUM",
|
|
635
|
+
["AVG" /* AVG */]: "AVG",
|
|
636
|
+
["MAX" /* MAX */]: "MAX",
|
|
637
|
+
["MIN" /* MIN */]: "MIN",
|
|
638
|
+
["GROUP_CONCAT" /* GROUP_CONCAT */]: "GROUP_CONCAT"
|
|
639
|
+
});
|
|
640
|
+
var PARSER_WINDOW_FUNCTION_TOKEN_MAP = Object.freeze({
|
|
641
|
+
["ROW_NUMBER" /* ROW_NUMBER */]: "ROW_NUMBER",
|
|
642
|
+
["RANK" /* RANK */]: "RANK",
|
|
643
|
+
["DENSE_RANK" /* DENSE_RANK */]: "DENSE_RANK"
|
|
644
|
+
});
|
|
645
|
+
var PARSER_CONTEXTUAL_FUNCTION_TOKEN_MAP = Object.freeze({
|
|
646
|
+
["TODAY" /* TODAY */]: "TODAY",
|
|
647
|
+
["NOW" /* NOW */]: "NOW",
|
|
648
|
+
["LOGINUSER" /* LOGINUSER */]: "LOGINUSER"
|
|
649
|
+
});
|
|
650
|
+
function isContextualFunctionToken(kind) {
|
|
651
|
+
return PARSER_CONTEXTUAL_FUNCTION_TOKEN_MAP[kind] !== void 0;
|
|
652
|
+
}
|
|
653
|
+
var PARSER_FUNCTION_SPELLINGS = Object.freeze(Array.from(/* @__PURE__ */ new Set([
|
|
654
|
+
...Object.keys(PARSER_SCALAR_FUNCTION_TOKEN_MAP),
|
|
655
|
+
...PARSER_IDENT_SCALAR_FUNCTIONS,
|
|
656
|
+
...Object.keys(PARSER_AGGREGATE_FUNCTION_TOKEN_MAP),
|
|
657
|
+
...Object.keys(PARSER_WINDOW_FUNCTION_TOKEN_MAP),
|
|
658
|
+
...Object.keys(PARSER_CONTEXTUAL_FUNCTION_TOKEN_MAP),
|
|
659
|
+
"IF"
|
|
660
|
+
])));
|
|
580
661
|
var FUNC_CALL_PREFIX_KINDS = /* @__PURE__ */ new Set([
|
|
581
662
|
"IDENT" /* IDENT */,
|
|
582
663
|
"BIDENT" /* BIDENT */,
|
|
@@ -820,13 +901,14 @@ var Parser = class {
|
|
|
820
901
|
this.advance();
|
|
821
902
|
return { type: "STRING", value: tok.value };
|
|
822
903
|
}
|
|
823
|
-
|
|
904
|
+
const contextualFunction = PARSER_CONTEXTUAL_FUNCTION_TOKEN_MAP[tok.kind];
|
|
905
|
+
if (contextualFunction === "LOGINUSER") {
|
|
824
906
|
throw new ParseError(
|
|
825
907
|
`${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
908
|
tok
|
|
827
909
|
);
|
|
828
910
|
}
|
|
829
|
-
if (
|
|
911
|
+
if (contextualFunction !== void 0) {
|
|
830
912
|
return this.parseSqlValue();
|
|
831
913
|
}
|
|
832
914
|
const expr = this.parseArithAddSub();
|
|
@@ -1581,16 +1663,7 @@ var Parser = class {
|
|
|
1581
1663
|
return { type: "FIELD", field, alias };
|
|
1582
1664
|
}
|
|
1583
1665
|
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
|
-
}
|
|
1666
|
+
return PARSER_WINDOW_FUNCTION_TOKEN_MAP[this.peek().kind] ?? null;
|
|
1594
1667
|
}
|
|
1595
1668
|
parseWindowColumn(func) {
|
|
1596
1669
|
this.advance();
|
|
@@ -1947,64 +2020,14 @@ var Parser = class {
|
|
|
1947
2020
|
// ──────────────────────────────────────────────────
|
|
1948
2021
|
tryStringFuncName() {
|
|
1949
2022
|
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;
|
|
2023
|
+
const conditional = PARSER_SCALAR_FUNCTION_TOKEN_MAP[this.peek().kind];
|
|
2024
|
+
if (conditional === "LEFT" || conditional === "RIGHT") return conditional;
|
|
2025
|
+
}
|
|
2026
|
+
const byKind = PARSER_SCALAR_FUNCTION_TOKEN_MAP[this.peek().kind] ?? null;
|
|
2027
|
+
if (byKind !== null && byKind !== "LEFT" && byKind !== "RIGHT") return byKind;
|
|
2005
2028
|
if (this.peek().kind === "IDENT" /* IDENT */) {
|
|
2006
2029
|
const name = this.peek().value.toUpperCase();
|
|
2007
|
-
if (name
|
|
2030
|
+
if (PARSER_IDENT_SCALAR_FUNCTIONS.includes(name)) {
|
|
2008
2031
|
if (this.peekAt(1).kind === "(" /* LPAREN */) {
|
|
2009
2032
|
return name;
|
|
2010
2033
|
}
|
|
@@ -2094,16 +2117,7 @@ var Parser = class {
|
|
|
2094
2117
|
return false;
|
|
2095
2118
|
}
|
|
2096
2119
|
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;
|
|
2120
|
+
return PARSER_AGGREGATE_FUNCTION_TOKEN_MAP[this.peek().kind] ?? null;
|
|
2107
2121
|
}
|
|
2108
2122
|
/** 集計関数参照を読む。SELECT 列の alias は呼び出し側で式全体の後に処理する。 */
|
|
2109
2123
|
parseAggregateRef(func) {
|
|
@@ -2464,13 +2478,13 @@ var Parser = class {
|
|
|
2464
2478
|
this.advance();
|
|
2465
2479
|
return { type: "STRING", value: tok.value };
|
|
2466
2480
|
}
|
|
2467
|
-
if (tok.kind
|
|
2481
|
+
if (isContextualFunctionToken(tok.kind)) {
|
|
2468
2482
|
this.advance();
|
|
2469
2483
|
this.expect("(" /* LPAREN */);
|
|
2470
2484
|
this.expect(")" /* RPAREN */);
|
|
2471
2485
|
return {
|
|
2472
2486
|
type: "KINTONE_FUNC",
|
|
2473
|
-
name: tok.
|
|
2487
|
+
name: PARSER_CONTEXTUAL_FUNCTION_TOKEN_MAP[tok.kind]
|
|
2474
2488
|
};
|
|
2475
2489
|
}
|
|
2476
2490
|
if (tok.kind === "CASE" /* CASE */) {
|
|
@@ -3267,7 +3281,7 @@ var Parser = class {
|
|
|
3267
3281
|
}
|
|
3268
3282
|
if (tok.kind === "VARIABLE" /* VARIABLE */) return this.parseSqlValue();
|
|
3269
3283
|
if (tok.kind === "STRING" /* STRING */) return this.parseSqlValue();
|
|
3270
|
-
if (tok.kind
|
|
3284
|
+
if (isContextualFunctionToken(tok.kind)) return this.parseSqlValue();
|
|
3271
3285
|
if (tok.kind === "IN" /* IN */) return this.parseSqlValue();
|
|
3272
3286
|
if (tok.kind === "CASE" /* CASE */ || tok.kind === "IF" /* IF */) {
|
|
3273
3287
|
return this.parseSqlValue();
|
|
@@ -4930,6 +4944,9 @@ function canInlineSingleCte(stmt) {
|
|
|
4930
4944
|
if (stmt.ctes.length !== 1) return false;
|
|
4931
4945
|
const cteDef = stmt.ctes[0];
|
|
4932
4946
|
if (cteDef.query.type !== "SELECT" || resolveSelectMode(cteDef.query) !== "SIMPLE") return false;
|
|
4947
|
+
if (!cteDef.query.columns.every(
|
|
4948
|
+
(column) => column.type === "WILDCARD" || column.type === "FIELD" && (column.alias === null || column.alias === column.field)
|
|
4949
|
+
)) return false;
|
|
4933
4950
|
const finalQuery = stmt.query;
|
|
4934
4951
|
if (finalQuery.type !== "SELECT") return false;
|
|
4935
4952
|
if (finalQuery.from.cteName !== cteDef.name || finalQuery.joins.length > 0) return false;
|
|
@@ -9700,10 +9717,12 @@ function flatten(record, alias) {
|
|
|
9700
9717
|
}
|
|
9701
9718
|
return row;
|
|
9702
9719
|
}
|
|
9703
|
-
function applyJoin(leftRows, rightRows, join2) {
|
|
9720
|
+
function applyJoin(leftRows, rightRows, join2, columns = {}) {
|
|
9704
9721
|
const { on, type: joinType } = join2;
|
|
9705
9722
|
const leftKey = on.left.tableAlias ? `${on.left.tableAlias}.${on.left.field}` : on.left.field;
|
|
9706
9723
|
const rightKey = on.right.tableAlias ? `${on.right.tableAlias}.${on.right.field}` : on.right.field;
|
|
9724
|
+
assertJoinKeyAvailable(leftRows, leftKey, columns.leftColumns);
|
|
9725
|
+
assertJoinKeyAvailable(rightRows, rightKey, columns.rightColumns);
|
|
9707
9726
|
if (joinType === "RIGHT") {
|
|
9708
9727
|
const leftIndex = /* @__PURE__ */ new Map();
|
|
9709
9728
|
for (const lRow of leftRows) {
|
|
@@ -9713,7 +9732,7 @@ function applyJoin(leftRows, rightRows, join2) {
|
|
|
9713
9732
|
else leftIndex.set(k, [lRow]);
|
|
9714
9733
|
}
|
|
9715
9734
|
const emptyLeft = {};
|
|
9716
|
-
for (const key of Object.keys(leftRows[0] ?? {})) emptyLeft[key] = "";
|
|
9735
|
+
for (const key of columns.leftColumns ?? Object.keys(leftRows[0] ?? {})) emptyLeft[key] = "";
|
|
9717
9736
|
const result2 = [];
|
|
9718
9737
|
for (const rRow of rightRows) {
|
|
9719
9738
|
const k = rRow[rightKey] ?? "";
|
|
@@ -9735,7 +9754,7 @@ function applyJoin(leftRows, rightRows, join2) {
|
|
|
9735
9754
|
}
|
|
9736
9755
|
const result = [];
|
|
9737
9756
|
const emptyRight = {};
|
|
9738
|
-
for (const key of Object.keys(rightRows[0] ?? {})) emptyRight[key] = "";
|
|
9757
|
+
for (const key of columns.rightColumns ?? Object.keys(rightRows[0] ?? {})) emptyRight[key] = "";
|
|
9739
9758
|
for (const lRow of leftRows) {
|
|
9740
9759
|
const k = lRow[leftKey] ?? "";
|
|
9741
9760
|
const matched = rightIndex.get(k) ?? [];
|
|
@@ -9749,6 +9768,12 @@ function applyJoin(leftRows, rightRows, join2) {
|
|
|
9749
9768
|
}
|
|
9750
9769
|
return result;
|
|
9751
9770
|
}
|
|
9771
|
+
function assertJoinKeyAvailable(rows, key, savedColumns) {
|
|
9772
|
+
const missing = rows.length > 0 ? rows.some((row) => !Object.prototype.hasOwnProperty.call(row, key)) : savedColumns !== void 0 && !savedColumns.includes(key);
|
|
9773
|
+
if (missing) {
|
|
9774
|
+
throw new Error(`ArgumentError: JOIN key ${key} is not available in the materialized table.`);
|
|
9775
|
+
}
|
|
9776
|
+
}
|
|
9752
9777
|
function applyFilter(rows, where, resolveFieldType, appliedKlikes, resolveFieldSemantics2) {
|
|
9753
9778
|
if (where === null) return rows;
|
|
9754
9779
|
return rows.filter((row) => evalWhere(where, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2));
|
|
@@ -10047,9 +10072,12 @@ function applyLimit(rows, limit, offset) {
|
|
|
10047
10072
|
if (limit === null) return rows.slice(start);
|
|
10048
10073
|
return rows.slice(start, start + limit);
|
|
10049
10074
|
}
|
|
10050
|
-
function project(rows, columns, scalarCache, resolveFieldType, sourceColumns, resolveFieldSemantics2) {
|
|
10075
|
+
function project(rows, columns, scalarCache, resolveFieldType, sourceColumns, resolveFieldSemantics2, hiddenQualifiedAliases) {
|
|
10051
10076
|
if (columns.length === 1 && columns[0].type === "WILDCARD") {
|
|
10052
|
-
const projected2 = rows.map((row) =>
|
|
10077
|
+
const projected2 = rows.map((row) => stripHiddenQualifiedColumns(
|
|
10078
|
+
stripParentShortcutColumns(row),
|
|
10079
|
+
hiddenQualifiedAliases
|
|
10080
|
+
));
|
|
10053
10081
|
const cols = projected2.length > 0 ? Object.keys(projected2[0]) : [...sourceColumns ?? []];
|
|
10054
10082
|
return { rows: projected2, columns: cols };
|
|
10055
10083
|
}
|
|
@@ -10069,7 +10097,10 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns, re
|
|
|
10069
10097
|
case "VARIABLE_COL":
|
|
10070
10098
|
throw new Error(`internal error: unresolved SELECT variable @${col.name}`);
|
|
10071
10099
|
case "WILDCARD":
|
|
10072
|
-
Object.assign(out,
|
|
10100
|
+
Object.assign(out, stripHiddenQualifiedColumns(
|
|
10101
|
+
stripParentShortcutColumns(row),
|
|
10102
|
+
hiddenQualifiedAliases
|
|
10103
|
+
));
|
|
10073
10104
|
break;
|
|
10074
10105
|
case "PARENT_WILDCARD": {
|
|
10075
10106
|
const parentKeys = Object.keys(row).filter((k) => k.startsWith("_p.")).sort();
|
|
@@ -10322,6 +10353,27 @@ function resolveAggInStringFuncExpr(expr, rows, resolveAggSortKind) {
|
|
|
10322
10353
|
args: expr.args.map((arg) => resolveAggInStringFuncArg(arg, rows, resolveAggSortKind))
|
|
10323
10354
|
};
|
|
10324
10355
|
}
|
|
10356
|
+
function stripHiddenQualifiedColumns(row, hiddenQualifiedAliases) {
|
|
10357
|
+
if (!hiddenQualifiedAliases || hiddenQualifiedAliases.size === 0) return row;
|
|
10358
|
+
const out = {};
|
|
10359
|
+
for (const [key, value] of Object.entries(row)) {
|
|
10360
|
+
if ([...hiddenQualifiedAliases].some((alias) => key.startsWith(`${alias}.`))) continue;
|
|
10361
|
+
out[key] = value;
|
|
10362
|
+
}
|
|
10363
|
+
return out;
|
|
10364
|
+
}
|
|
10365
|
+
function flattenedColumns(columns, alias) {
|
|
10366
|
+
if (columns === void 0) return void 0;
|
|
10367
|
+
return alias ? columns.flatMap((column) => [`${alias}.${column}`, column]) : [...columns];
|
|
10368
|
+
}
|
|
10369
|
+
function mergeKnownColumns(left, right, rows) {
|
|
10370
|
+
if (left === void 0 && right === void 0 && rows.length === 0) return void 0;
|
|
10371
|
+
return [.../* @__PURE__ */ new Set([
|
|
10372
|
+
...left ?? [],
|
|
10373
|
+
...right ?? [],
|
|
10374
|
+
...Object.keys(rows[0] ?? {})
|
|
10375
|
+
])];
|
|
10376
|
+
}
|
|
10325
10377
|
function deriveOutputOrderSemantics(columns) {
|
|
10326
10378
|
const result = /* @__PURE__ */ new Map();
|
|
10327
10379
|
for (const column of columns) {
|
|
@@ -10356,7 +10408,9 @@ function runFullScan(input) {
|
|
|
10356
10408
|
havingFieldSemanticsResolver,
|
|
10357
10409
|
aggregateSortKindResolver,
|
|
10358
10410
|
appliedKlikes,
|
|
10359
|
-
sourceColumns
|
|
10411
|
+
sourceColumns,
|
|
10412
|
+
tableColumns,
|
|
10413
|
+
hiddenQualifiedAliases
|
|
10360
10414
|
} = input;
|
|
10361
10415
|
const effectiveOrderSemantics = deriveOutputOrderSemantics(stmt.columns);
|
|
10362
10416
|
for (const [key, value] of orderSemantics ?? []) effectiveOrderSemantics.set(key, value);
|
|
@@ -10364,11 +10418,25 @@ function runFullScan(input) {
|
|
|
10364
10418
|
const mainAlias = stmt.from.alias;
|
|
10365
10419
|
const mainRecords = tables.get(mainAlias) ?? tables.get(null) ?? [];
|
|
10366
10420
|
rows = mainRecords.map((r) => flatten(r, mainAlias));
|
|
10421
|
+
let knownColumns = mergeKnownColumns(
|
|
10422
|
+
flattenedColumns(tableColumns?.get(mainAlias), mainAlias),
|
|
10423
|
+
void 0,
|
|
10424
|
+
rows
|
|
10425
|
+
);
|
|
10367
10426
|
for (const join2 of stmt.joins) {
|
|
10368
10427
|
const rightAlias = join2.table.alias;
|
|
10369
10428
|
const rightRecords = tables.get(rightAlias) ?? [];
|
|
10370
10429
|
const rightRows = rightRecords.map((r) => flatten(r, rightAlias));
|
|
10371
|
-
|
|
10430
|
+
const rightColumns = mergeKnownColumns(
|
|
10431
|
+
flattenedColumns(tableColumns?.get(rightAlias), rightAlias),
|
|
10432
|
+
void 0,
|
|
10433
|
+
rightRows
|
|
10434
|
+
);
|
|
10435
|
+
rows = applyJoin(rows, rightRows, join2, {
|
|
10436
|
+
leftColumns: knownColumns,
|
|
10437
|
+
rightColumns
|
|
10438
|
+
});
|
|
10439
|
+
knownColumns = mergeKnownColumns(knownColumns, rightColumns, rows);
|
|
10372
10440
|
}
|
|
10373
10441
|
rows = applyFilter(rows, stmt.where, fieldTypeResolver, appliedKlikes, fieldSemanticsResolver);
|
|
10374
10442
|
if (stmt.groupBy.length > 0 || hasAggregateColumns(stmt.columns)) {
|
|
@@ -10381,7 +10449,15 @@ function runFullScan(input) {
|
|
|
10381
10449
|
}
|
|
10382
10450
|
rows = applyOrderBy(rows, stmt.orderBy, optionOrders, sortKinds, effectiveOrderSemantics);
|
|
10383
10451
|
rows = applyLimit(rows, stmt.limit, stmt.offset);
|
|
10384
|
-
return project(
|
|
10452
|
+
return project(
|
|
10453
|
+
rows,
|
|
10454
|
+
stmt.columns,
|
|
10455
|
+
scalarCache,
|
|
10456
|
+
fieldTypeResolver,
|
|
10457
|
+
sourceColumns,
|
|
10458
|
+
fieldSemanticsResolver,
|
|
10459
|
+
hiddenQualifiedAliases
|
|
10460
|
+
);
|
|
10385
10461
|
}
|
|
10386
10462
|
|
|
10387
10463
|
// src/converter/subtableAdapter.ts
|
|
@@ -12693,7 +12769,7 @@ async function buildWhereFieldSemanticsResolver(stmt, client, cacheContext, mate
|
|
|
12693
12769
|
if (field.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
12694
12770
|
return fromPhysical(stmt.from, field.field, false);
|
|
12695
12771
|
}
|
|
12696
|
-
const table = tables.find((candidate) => candidate
|
|
12772
|
+
const table = tables.find((candidate) => effectiveTableAlias(candidate) === field.tableAlias);
|
|
12697
12773
|
if (!table) return void 0;
|
|
12698
12774
|
if (table.cteName !== null) {
|
|
12699
12775
|
return materializedTables?.get(table.cteName)?.columnMeta?.get(field.field)?.semantics ?? syntheticSemantics("string");
|
|
@@ -13127,8 +13203,11 @@ function collectSelectTypedInFieldRefs(stmt) {
|
|
|
13127
13203
|
}
|
|
13128
13204
|
return refs;
|
|
13129
13205
|
}
|
|
13206
|
+
function effectiveTableAlias(table) {
|
|
13207
|
+
return table.alias ?? table.cteName;
|
|
13208
|
+
}
|
|
13130
13209
|
function findTableForAlias(stmt, alias) {
|
|
13131
|
-
return [stmt.from, ...stmt.joins.map((join2) => join2.table)].find((table) => table
|
|
13210
|
+
return [stmt.from, ...stmt.joins.map((join2) => join2.table)].find((table) => effectiveTableAlias(table) === alias);
|
|
13132
13211
|
}
|
|
13133
13212
|
function physicalSelectTables(stmt) {
|
|
13134
13213
|
return [stmt.from, ...stmt.joins.map((join2) => join2.table)].filter((table) => table.cteName === null);
|
|
@@ -13280,7 +13359,7 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext, materia
|
|
|
13280
13359
|
if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
13281
13360
|
info = fieldInfosByApp.get(stmt.from.appId)?.get(ref.field);
|
|
13282
13361
|
} else {
|
|
13283
|
-
const table = tables.find((candidate) => candidate
|
|
13362
|
+
const table = tables.find((candidate) => effectiveTableAlias(candidate) === ref.tableAlias);
|
|
13284
13363
|
if (!table) return void 0;
|
|
13285
13364
|
if (table.cteName !== null) {
|
|
13286
13365
|
return materializedTables?.get(table.cteName)?.columnMeta?.get(ref.field)?.semantics ?? syntheticSemantics("string");
|
|
@@ -13305,7 +13384,7 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext, materia
|
|
|
13305
13384
|
return matches[0];
|
|
13306
13385
|
}
|
|
13307
13386
|
if (!info) return void 0;
|
|
13308
|
-
const sourceTable = ref.tableAlias !== null ? tables.find((table) => table
|
|
13387
|
+
const sourceTable = ref.tableAlias !== null ? tables.find((table) => effectiveTableAlias(table) === ref.tableAlias) : stmt.joins.length === 0 ? stmt.from : void 0;
|
|
13309
13388
|
return semanticsForInfo(info, sourceTable?.appId ?? stmt.from.appId);
|
|
13310
13389
|
};
|
|
13311
13390
|
}
|
|
@@ -13435,7 +13514,7 @@ async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext,
|
|
|
13435
13514
|
const info2 = physicalInfos.get(stmt.from.appId)?.get(ref.field);
|
|
13436
13515
|
return info2 ? materializedMetaFromFieldInfo(info2, stmt.from.appId) : void 0;
|
|
13437
13516
|
}
|
|
13438
|
-
const table = tables.find((candidate) => candidate
|
|
13517
|
+
const table = tables.find((candidate) => effectiveTableAlias(candidate) === ref.tableAlias);
|
|
13439
13518
|
if (!table) return void 0;
|
|
13440
13519
|
if (table.cteName !== null) return materializedTables?.get(table.cteName)?.columnMeta?.get(ref.field);
|
|
13441
13520
|
const info = physicalInfos.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
@@ -13540,7 +13619,7 @@ function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
|
|
|
13540
13619
|
if (field.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
13541
13620
|
return fieldTypesByApp.get(stmt.from.appId)?.get(field.field);
|
|
13542
13621
|
}
|
|
13543
|
-
const table = tables.find((candidate) => candidate
|
|
13622
|
+
const table = tables.find((candidate) => effectiveTableAlias(candidate) === field.tableAlias);
|
|
13544
13623
|
if (!table || table.cteName !== null) return void 0;
|
|
13545
13624
|
return subtableSystemFieldType(table, field.field) ?? fieldTypesByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, field.field));
|
|
13546
13625
|
}
|
|
@@ -13765,6 +13844,37 @@ async function executeQueryWithCte(query, client, options, cteCache, cacheContex
|
|
|
13765
13844
|
return result;
|
|
13766
13845
|
}
|
|
13767
13846
|
async function executeFullScanWithCte(stmt, client, options, cteCache, cacheContext) {
|
|
13847
|
+
const hiddenQualifiedAliases = /* @__PURE__ */ new Set();
|
|
13848
|
+
const withEffectiveAlias = (table) => {
|
|
13849
|
+
if (table.alias !== null || table.cteName === null) return table;
|
|
13850
|
+
const alias = effectiveTableAlias(table);
|
|
13851
|
+
hiddenQualifiedAliases.add(alias);
|
|
13852
|
+
return { ...table, alias };
|
|
13853
|
+
};
|
|
13854
|
+
stmt = {
|
|
13855
|
+
...stmt,
|
|
13856
|
+
from: withEffectiveAlias(stmt.from),
|
|
13857
|
+
joins: stmt.joins.map((join2) => ({ ...join2, table: withEffectiveAlias(join2.table) }))
|
|
13858
|
+
};
|
|
13859
|
+
const aliases = /* @__PURE__ */ new Set();
|
|
13860
|
+
for (const table of [stmt.from, ...stmt.joins.map((join2) => join2.table)]) {
|
|
13861
|
+
const alias = effectiveTableAlias(table);
|
|
13862
|
+
if (alias === null) continue;
|
|
13863
|
+
if (aliases.has(alias)) {
|
|
13864
|
+
throw new Error(`ArgumentError: effective alias ${alias} is used by multiple tables.`);
|
|
13865
|
+
}
|
|
13866
|
+
aliases.add(alias);
|
|
13867
|
+
}
|
|
13868
|
+
const requireMaterializedTable = (name) => {
|
|
13869
|
+
const table = cteCache.get(name);
|
|
13870
|
+
if (!table) {
|
|
13871
|
+
throw new Error(`ArgumentError: materialized source ${name} is not available.`);
|
|
13872
|
+
}
|
|
13873
|
+
return table;
|
|
13874
|
+
};
|
|
13875
|
+
for (const table of [stmt.from, ...stmt.joins.map((join2) => join2.table)]) {
|
|
13876
|
+
if (table.cteName !== null) requireMaterializedTable(table.cteName);
|
|
13877
|
+
}
|
|
13768
13878
|
const maxRecords = options.maxRecords ?? 1e4;
|
|
13769
13879
|
const warnings = /* @__PURE__ */ new Set();
|
|
13770
13880
|
const parallel = options.fetchParallel ?? 1;
|
|
@@ -13811,9 +13921,11 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
13811
13921
|
orderByMetaPromise.catch(() => {
|
|
13812
13922
|
});
|
|
13813
13923
|
const tables = /* @__PURE__ */ new Map();
|
|
13924
|
+
const tableColumns = /* @__PURE__ */ new Map();
|
|
13814
13925
|
if (stmt.from.cteName != null) {
|
|
13815
|
-
const table =
|
|
13816
|
-
tables.set(stmt.from.alias,
|
|
13926
|
+
const table = requireMaterializedTable(stmt.from.cteName);
|
|
13927
|
+
tables.set(stmt.from.alias, table.rows.map(processRowToKintoneRecord));
|
|
13928
|
+
tableColumns.set(stmt.from.alias, table.columns);
|
|
13817
13929
|
} else {
|
|
13818
13930
|
const mainRecords = await fetchTableRecordsForFullScan(
|
|
13819
13931
|
stmt,
|
|
@@ -13831,8 +13943,9 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
13831
13943
|
}
|
|
13832
13944
|
const joinFetches = stmt.joins.map(async (join2) => {
|
|
13833
13945
|
if (join2.table.cteName != null) {
|
|
13834
|
-
const table =
|
|
13835
|
-
tables.set(join2.table.alias,
|
|
13946
|
+
const table = requireMaterializedTable(join2.table.cteName);
|
|
13947
|
+
tables.set(join2.table.alias, table.rows.map(processRowToKintoneRecord));
|
|
13948
|
+
tableColumns.set(join2.table.alias, table.columns);
|
|
13836
13949
|
} else {
|
|
13837
13950
|
const pushDownCond = join2.table.alias ? pushdownPlan.joinConditions.get(join2.table.alias) ?? null : null;
|
|
13838
13951
|
const optimized = await tryFetchJoinRecordsBySourceKeys(
|
|
@@ -13863,7 +13976,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
13863
13976
|
await Promise.all(joinFetches);
|
|
13864
13977
|
const scalarCache = await scalarCachePromise;
|
|
13865
13978
|
const { optionOrders, sortKinds, semantics } = await orderByMetaPromise;
|
|
13866
|
-
const sourceColumns = stmt.joins.length === 0 && stmt.from.cteName != null ?
|
|
13979
|
+
const sourceColumns = stmt.joins.length === 0 && stmt.from.cteName != null ? requireMaterializedTable(stmt.from.cteName).columns : void 0;
|
|
13867
13980
|
const { rows, columns } = runFullScan({
|
|
13868
13981
|
tables,
|
|
13869
13982
|
stmt,
|
|
@@ -13877,7 +13990,9 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
13877
13990
|
havingFieldSemanticsResolver,
|
|
13878
13991
|
aggregateSortKindResolver,
|
|
13879
13992
|
appliedKlikes: pushdownPlan.appliedKlikes,
|
|
13880
|
-
sourceColumns
|
|
13993
|
+
sourceColumns,
|
|
13994
|
+
tableColumns,
|
|
13995
|
+
hiddenQualifiedAliases
|
|
13881
13996
|
});
|
|
13882
13997
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
13883
13998
|
}
|
|
@@ -14179,7 +14294,7 @@ async function buildOrderSemanticsForSelect(stmt, client, cacheContext, material
|
|
|
14179
14294
|
const info2 = infosByApp.get(stmt.from.appId)?.get(ref.field);
|
|
14180
14295
|
return info2 ? materializedMetaFromFieldInfo(info2, stmt.from.appId) : void 0;
|
|
14181
14296
|
}
|
|
14182
|
-
const table = tables.find((candidate) => candidate
|
|
14297
|
+
const table = tables.find((candidate) => effectiveTableAlias(candidate) === ref.tableAlias);
|
|
14183
14298
|
if (!table) return void 0;
|
|
14184
14299
|
if (table.cteName !== null) return materializedTables?.get(table.cteName)?.columnMeta?.get(ref.field);
|
|
14185
14300
|
const info = infosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|