@rex0220/kintone-sql-tools 3.11.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 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
- if (tok.kind === "LOGINUSER" /* LOGINUSER */) {
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 (tok.kind === "TODAY" /* TODAY */ || tok.kind === "NOW" /* NOW */) {
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
- switch (this.peek().kind) {
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
- if (this.peek().kind === "LEFT" /* LEFT */) return "LEFT";
1951
- if (this.peek().kind === "RIGHT" /* RIGHT */) return "RIGHT";
1952
- }
1953
- const map = {
1954
- ["UPPER" /* UPPER */]: "UPPER",
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 === "CURRENT_DATE" || name === "CURRENT_TIMESTAMP") {
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
- const map = {
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 === "TODAY" /* TODAY */ || tok.kind === "NOW" /* NOW */ || tok.kind === "LOGINUSER" /* LOGINUSER */) {
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.value
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 === "TODAY" /* TODAY */ || tok.kind === "NOW" /* NOW */ || tok.kind === "LOGINUSER" /* LOGINUSER */) return this.parseSqlValue();
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();