@rex0220/kintone-sql-tools 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist-cli/ksql.js CHANGED
@@ -629,7 +629,22 @@ var Parser = class {
629
629
  throw new ParseError("SET \u306E\u53F3\u8FBA\u3067 NULL \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\uFF08Phase 1a\uFF09", tok);
630
630
  }
631
631
  if (tok.kind === "(" /* LPAREN */ && this.peekAt(1).kind === "SELECT" /* SELECT */) {
632
- throw new ParseError("SET \u306E\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u4EE3\u5165\u306F Phase 1b \u3067\u5BFE\u5FDC\u4E88\u5B9A\u3067\u3059", tok);
632
+ this.advance();
633
+ const query = this.parseSelect();
634
+ this.expect(")" /* RPAREN */);
635
+ if (this.isArithOp(this.peek().kind)) {
636
+ throw new ParseError(
637
+ "\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u306E\u5F8C\u306B\u7B97\u8853\u6F14\u7B97\u5B50\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u30B5\u30D6\u30AF\u30A8\u30EA\u5185\u3067\u8A08\u7B97\u3057\u3066\u304F\u3060\u3055\u3044",
638
+ this.peek()
639
+ );
640
+ }
641
+ const hasWildcard = query.columns.some(
642
+ (c) => c.type === "WILDCARD" || c.type === "PARENT_WILDCARD"
643
+ );
644
+ if (!hasWildcard && query.columns.length !== 1) {
645
+ throw new ParseError("scalar subquery in SET must return exactly 1 column.", tok);
646
+ }
647
+ return { type: "SCALAR_SUBQUERY", query };
633
648
  }
634
649
  if (tok.kind === "STRING" /* STRING */) {
635
650
  this.advance();
@@ -4920,7 +4935,26 @@ async function executeBatch(sql, client, options = {}) {
4920
4935
  }
4921
4936
  async function executeBatchStatement(stmt, info, client, options, cacheContext, tempTables, variables) {
4922
4937
  if (stmt.type === "SET_VARIABLE") {
4923
- variables.set(stmt.name, evaluateScalarExpr(stmt.expr));
4938
+ const resolvedStmt2 = resolveVariableRefs(stmt, variables);
4939
+ if (resolvedStmt2.expr.type === "SCALAR_SUBQUERY") {
4940
+ try {
4941
+ const value = await evaluateScalarSubquery(
4942
+ resolvedStmt2.expr.query,
4943
+ client,
4944
+ options,
4945
+ cacheContext,
4946
+ tempTables
4947
+ );
4948
+ variables.set(stmt.name, { type: "string", value });
4949
+ } catch (e) {
4950
+ if (e instanceof ScalarSubqueryError) {
4951
+ throw new Error(`ArgumentError: ${e.message}`);
4952
+ }
4953
+ throw e;
4954
+ }
4955
+ } else {
4956
+ variables.set(stmt.name, evaluateScalarExpr(resolvedStmt2.expr));
4957
+ }
4924
4958
  return {};
4925
4959
  }
4926
4960
  const resolvedStmt = resolveVariableRefs(stmt, variables);
@@ -5083,6 +5117,12 @@ var AssertError = class extends Error {
5083
5117
  this.name = "AssertError";
5084
5118
  }
5085
5119
  };
5120
+ var ScalarSubqueryError = class extends Error {
5121
+ constructor(message) {
5122
+ super(message);
5123
+ this.name = "ScalarSubqueryError";
5124
+ }
5125
+ };
5086
5126
  async function executeAssert(stmt, client, options, cacheContext, tempTables) {
5087
5127
  const left = await evalAssertOperand(stmt.left, client, options, cacheContext, tempTables);
5088
5128
  if (stmt.op === "BETWEEN") {
@@ -5116,25 +5156,38 @@ async function evalAssertOperand(operand, client, options, cacheContext, tempTab
5116
5156
  case "ARITH":
5117
5157
  return String(evalAssertArith(operand));
5118
5158
  case "SCALAR_SUBQUERY": {
5119
- const { query, probed } = withScalarProbeLimit(operand.query);
5120
- const result = await runSubquery(query, client, options, cacheContext, tempTables);
5121
- if (result.columns.length > 1) {
5122
- throw new AssertError(
5123
- `scalar subquery returned ${result.columns.length} columns (expected 1 column).`
5159
+ try {
5160
+ return await evaluateScalarSubquery(
5161
+ operand.query,
5162
+ client,
5163
+ options,
5164
+ cacheContext,
5165
+ tempTables
5124
5166
  );
5167
+ } catch (e) {
5168
+ if (e instanceof ScalarSubqueryError) throw new AssertError(e.message);
5169
+ throw e;
5125
5170
  }
5126
- if (result.rowCount === 0) {
5127
- throw new AssertError("scalar subquery returned no rows (expected 1 row).");
5128
- }
5129
- if (result.rowCount > 1) {
5130
- const rows = probed && result.rowCount === 2 ? "2 or more rows" : `${result.rowCount} rows`;
5131
- throw new AssertError(`scalar subquery returned ${rows} (expected 1 row).`);
5132
- }
5133
- const col = result.columns[0] ?? "";
5134
- return result.rows[0]?.[col] ?? "";
5135
5171
  }
5136
5172
  }
5137
5173
  }
5174
+ async function evaluateScalarSubquery(sourceQuery, client, options, cacheContext, tempTables) {
5175
+ const { query, probed } = withScalarProbeLimit(sourceQuery);
5176
+ const result = await runSubquery(query, client, options, cacheContext, tempTables);
5177
+ if (result.columns.length !== 1) {
5178
+ throw new ScalarSubqueryError(
5179
+ `scalar subquery returned ${result.columns.length} columns (expected 1 column).`
5180
+ );
5181
+ }
5182
+ if (result.rowCount === 0) {
5183
+ throw new ScalarSubqueryError("scalar subquery returned no rows (expected 1 row).");
5184
+ }
5185
+ if (result.rowCount > 1) {
5186
+ const rows = probed && result.rowCount === 2 ? "2 or more rows" : `${result.rowCount} rows`;
5187
+ throw new ScalarSubqueryError(`scalar subquery returned ${rows} (expected 1 row).`);
5188
+ }
5189
+ return result.rows[0]?.[result.columns[0]] ?? "";
5190
+ }
5138
5191
  function withScalarProbeLimit(query) {
5139
5192
  const hasAgg = query.groupBy.length > 0 || query.columns.some((c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL");
5140
5193
  if (hasAgg || query.distinct || query.limit !== null) return { query, probed: false };
@@ -6636,7 +6689,7 @@ function buildBatchExplainPlans(sql) {
6636
6689
  return {
6637
6690
  statementCount: statements.length,
6638
6691
  statements: statements.map((stmt, i) => {
6639
- const planStmt = stmt.type === "SET_VARIABLE" ? stmt : resolveVariableRefs(stmt, variables);
6692
+ const planStmt = stmt.type === "SET_VARIABLE" ? stmt.expr.type === "SCALAR_SUBQUERY" ? { ...stmt, expr: resolveVariableRefs(stmt.expr, variables) } : stmt : resolveVariableRefs(stmt, variables);
6640
6693
  const result = {
6641
6694
  index: i,
6642
6695
  type: analysis.statements[i].statementType,
@@ -6665,6 +6718,15 @@ function buildBatchStatementPlan(stmt, info) {
6665
6718
  ];
6666
6719
  }
6667
6720
  if (stmt.type === "SET_VARIABLE") {
6721
+ if (stmt.expr.type === "SCALAR_SUBQUERY") {
6722
+ const subInfo = hasTempTableRef(stmt.expr.query) ? info : { ...info, tempTablesReferenced: [] };
6723
+ return [
6724
+ `SET @${stmt.name} = (SELECT ...)`,
6725
+ " value: \u30B5\u30D6\u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u6642\u306B1\u56DE\u8A55\u4FA1\uFF081\u884C1\u5217\u30FB\u30D0\u30C3\u30C1\u5185\u5B9A\u6570\u30FB\u7D50\u679C\u30E1\u30BF\u30C7\u30FC\u30BF\u306B\u306F\u975E\u516C\u958B\uFF09",
6726
+ " subquery:",
6727
+ ...buildPlanForBatchQuery(stmt.expr.query, subInfo).map((l) => ` ${l}`)
6728
+ ];
6729
+ }
6668
6730
  return [
6669
6731
  `SET @${stmt.name} = <scalar expression>`,
6670
6732
  " value: \u5B9F\u884C\u6642\u306B1\u56DE\u8A55\u4FA1\uFF08\u30D0\u30C3\u30C1\u5185\u5B9A\u6570\u30FB\u7D50\u679C\u30E1\u30BF\u30C7\u30FC\u30BF\u306B\u306F\u975E\u516C\u958B\uFF09"
@@ -31542,7 +31542,22 @@ var Parser = class {
31542
31542
  throw new ParseError("SET \u306E\u53F3\u8FBA\u3067 NULL \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\uFF08Phase 1a\uFF09", tok);
31543
31543
  }
31544
31544
  if (tok.kind === "(" /* LPAREN */ && this.peekAt(1).kind === "SELECT" /* SELECT */) {
31545
- throw new ParseError("SET \u306E\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u4EE3\u5165\u306F Phase 1b \u3067\u5BFE\u5FDC\u4E88\u5B9A\u3067\u3059", tok);
31545
+ this.advance();
31546
+ const query = this.parseSelect();
31547
+ this.expect(")" /* RPAREN */);
31548
+ if (this.isArithOp(this.peek().kind)) {
31549
+ throw new ParseError(
31550
+ "\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u306E\u5F8C\u306B\u7B97\u8853\u6F14\u7B97\u5B50\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u30B5\u30D6\u30AF\u30A8\u30EA\u5185\u3067\u8A08\u7B97\u3057\u3066\u304F\u3060\u3055\u3044",
31551
+ this.peek()
31552
+ );
31553
+ }
31554
+ const hasWildcard = query.columns.some(
31555
+ (c) => c.type === "WILDCARD" || c.type === "PARENT_WILDCARD"
31556
+ );
31557
+ if (!hasWildcard && query.columns.length !== 1) {
31558
+ throw new ParseError("scalar subquery in SET must return exactly 1 column.", tok);
31559
+ }
31560
+ return { type: "SCALAR_SUBQUERY", query };
31546
31561
  }
31547
31562
  if (tok.kind === "STRING" /* STRING */) {
31548
31563
  this.advance();
@@ -35821,7 +35836,26 @@ async function executeBatch(sql, client, options = {}) {
35821
35836
  }
35822
35837
  async function executeBatchStatement(stmt, info, client, options, cacheContext, tempTables, variables) {
35823
35838
  if (stmt.type === "SET_VARIABLE") {
35824
- variables.set(stmt.name, evaluateScalarExpr(stmt.expr));
35839
+ const resolvedStmt2 = resolveVariableRefs(stmt, variables);
35840
+ if (resolvedStmt2.expr.type === "SCALAR_SUBQUERY") {
35841
+ try {
35842
+ const value = await evaluateScalarSubquery(
35843
+ resolvedStmt2.expr.query,
35844
+ client,
35845
+ options,
35846
+ cacheContext,
35847
+ tempTables
35848
+ );
35849
+ variables.set(stmt.name, { type: "string", value });
35850
+ } catch (e) {
35851
+ if (e instanceof ScalarSubqueryError) {
35852
+ throw new Error(`ArgumentError: ${e.message}`);
35853
+ }
35854
+ throw e;
35855
+ }
35856
+ } else {
35857
+ variables.set(stmt.name, evaluateScalarExpr(resolvedStmt2.expr));
35858
+ }
35825
35859
  return {};
35826
35860
  }
35827
35861
  const resolvedStmt = resolveVariableRefs(stmt, variables);
@@ -35984,6 +36018,12 @@ var AssertError = class extends Error {
35984
36018
  this.name = "AssertError";
35985
36019
  }
35986
36020
  };
36021
+ var ScalarSubqueryError = class extends Error {
36022
+ constructor(message) {
36023
+ super(message);
36024
+ this.name = "ScalarSubqueryError";
36025
+ }
36026
+ };
35987
36027
  async function executeAssert(stmt, client, options, cacheContext, tempTables) {
35988
36028
  const left = await evalAssertOperand(stmt.left, client, options, cacheContext, tempTables);
35989
36029
  if (stmt.op === "BETWEEN") {
@@ -36017,25 +36057,38 @@ async function evalAssertOperand(operand, client, options, cacheContext, tempTab
36017
36057
  case "ARITH":
36018
36058
  return String(evalAssertArith(operand));
36019
36059
  case "SCALAR_SUBQUERY": {
36020
- const { query, probed } = withScalarProbeLimit(operand.query);
36021
- const result = await runSubquery(query, client, options, cacheContext, tempTables);
36022
- if (result.columns.length > 1) {
36023
- throw new AssertError(
36024
- `scalar subquery returned ${result.columns.length} columns (expected 1 column).`
36060
+ try {
36061
+ return await evaluateScalarSubquery(
36062
+ operand.query,
36063
+ client,
36064
+ options,
36065
+ cacheContext,
36066
+ tempTables
36025
36067
  );
36068
+ } catch (e) {
36069
+ if (e instanceof ScalarSubqueryError) throw new AssertError(e.message);
36070
+ throw e;
36026
36071
  }
36027
- if (result.rowCount === 0) {
36028
- throw new AssertError("scalar subquery returned no rows (expected 1 row).");
36029
- }
36030
- if (result.rowCount > 1) {
36031
- const rows = probed && result.rowCount === 2 ? "2 or more rows" : `${result.rowCount} rows`;
36032
- throw new AssertError(`scalar subquery returned ${rows} (expected 1 row).`);
36033
- }
36034
- const col = result.columns[0] ?? "";
36035
- return result.rows[0]?.[col] ?? "";
36036
36072
  }
36037
36073
  }
36038
36074
  }
36075
+ async function evaluateScalarSubquery(sourceQuery, client, options, cacheContext, tempTables) {
36076
+ const { query, probed } = withScalarProbeLimit(sourceQuery);
36077
+ const result = await runSubquery(query, client, options, cacheContext, tempTables);
36078
+ if (result.columns.length !== 1) {
36079
+ throw new ScalarSubqueryError(
36080
+ `scalar subquery returned ${result.columns.length} columns (expected 1 column).`
36081
+ );
36082
+ }
36083
+ if (result.rowCount === 0) {
36084
+ throw new ScalarSubqueryError("scalar subquery returned no rows (expected 1 row).");
36085
+ }
36086
+ if (result.rowCount > 1) {
36087
+ const rows = probed && result.rowCount === 2 ? "2 or more rows" : `${result.rowCount} rows`;
36088
+ throw new ScalarSubqueryError(`scalar subquery returned ${rows} (expected 1 row).`);
36089
+ }
36090
+ return result.rows[0]?.[result.columns[0]] ?? "";
36091
+ }
36039
36092
  function withScalarProbeLimit(query) {
36040
36093
  const hasAgg = query.groupBy.length > 0 || query.columns.some((c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL");
36041
36094
  if (hasAgg || query.distinct || query.limit !== null) return { query, probed: false };
@@ -37537,7 +37590,7 @@ function buildBatchExplainPlans(sql) {
37537
37590
  return {
37538
37591
  statementCount: statements.length,
37539
37592
  statements: statements.map((stmt, i) => {
37540
- const planStmt = stmt.type === "SET_VARIABLE" ? stmt : resolveVariableRefs(stmt, variables);
37593
+ const planStmt = stmt.type === "SET_VARIABLE" ? stmt.expr.type === "SCALAR_SUBQUERY" ? { ...stmt, expr: resolveVariableRefs(stmt.expr, variables) } : stmt : resolveVariableRefs(stmt, variables);
37541
37594
  const result = {
37542
37595
  index: i,
37543
37596
  type: analysis.statements[i].statementType,
@@ -37566,6 +37619,15 @@ function buildBatchStatementPlan(stmt, info) {
37566
37619
  ];
37567
37620
  }
37568
37621
  if (stmt.type === "SET_VARIABLE") {
37622
+ if (stmt.expr.type === "SCALAR_SUBQUERY") {
37623
+ const subInfo = hasTempTableRef(stmt.expr.query) ? info : { ...info, tempTablesReferenced: [] };
37624
+ return [
37625
+ `SET @${stmt.name} = (SELECT ...)`,
37626
+ " value: \u30B5\u30D6\u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u6642\u306B1\u56DE\u8A55\u4FA1\uFF081\u884C1\u5217\u30FB\u30D0\u30C3\u30C1\u5185\u5B9A\u6570\u30FB\u7D50\u679C\u30E1\u30BF\u30C7\u30FC\u30BF\u306B\u306F\u975E\u516C\u958B\uFF09",
37627
+ " subquery:",
37628
+ ...buildPlanForBatchQuery(stmt.expr.query, subInfo).map((l) => ` ${l}`)
37629
+ ];
37630
+ }
37569
37631
  return [
37570
37632
  `SET @${stmt.name} = <scalar expression>`,
37571
37633
  " value: \u5B9F\u884C\u6642\u306B1\u56DE\u8A55\u4FA1\uFF08\u30D0\u30C3\u30C1\u5185\u5B9A\u6570\u30FB\u7D50\u679C\u30E1\u30BF\u30C7\u30FC\u30BF\u306B\u306F\u975E\u516C\u958B\uFF09"
@@ -40014,7 +40076,7 @@ Options:
40014
40076
  -h, --help Show help
40015
40077
  `);
40016
40078
  }
40017
- var SERVER_VERSION = true ? "2.2.0" : "0.0.0-dev";
40079
+ var SERVER_VERSION = true ? "2.3.0" : "0.0.0-dev";
40018
40080
  function createServer(args) {
40019
40081
  const server = new McpServer({
40020
40082
  name: "ksql-mcp",
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rex0220/kintone-sql-tools",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "kintone SQL plugin, CLI, and MCP tools (ksql)",
5
5
  "publishConfig": {
6
6
  "access": "public"