@rex0220/kintone-sql-tools 2.0.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cli/ksql.js +328 -54
- package/dist-mcp/ksql-mcp.js +329 -55
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-mcp/ksql-mcp.js
CHANGED
|
@@ -31096,6 +31096,7 @@ var Lexer = class {
|
|
|
31096
31096
|
if (opTok) return opTok;
|
|
31097
31097
|
if (isIdentStart(ch)) return this.readIdentOrKeyword(start);
|
|
31098
31098
|
if (ch === "#") return this.readHashIdent(start);
|
|
31099
|
+
if (ch === "@") return this.readVariable(start);
|
|
31099
31100
|
throw new LexError(
|
|
31100
31101
|
`\u4E88\u671F\u3057\u306A\u3044\u6587\u5B57 \u300C${ch}\u300D \u3067\u3059`,
|
|
31101
31102
|
this.pos,
|
|
@@ -31275,6 +31276,23 @@ var Lexer = class {
|
|
|
31275
31276
|
}
|
|
31276
31277
|
return this.makeToken("IDENT" /* IDENT */, value, start);
|
|
31277
31278
|
}
|
|
31279
|
+
/** バッチ変数: @[A-Za-z_][A-Za-z0-9_]{0,63} */
|
|
31280
|
+
readVariable(start) {
|
|
31281
|
+
this.pos++;
|
|
31282
|
+
const first = this.input[this.pos] ?? "";
|
|
31283
|
+
if (!/[A-Za-z_]/.test(first)) {
|
|
31284
|
+
throw new LexError("\u300C@\u300D \u306E\u76F4\u5F8C\u306B\u306F\u82F1\u5B57\u307E\u305F\u306F _ \u3067\u59CB\u307E\u308B\u5909\u6570\u540D\u304C\u5FC5\u8981\u3067\u3059", start, this.input);
|
|
31285
|
+
}
|
|
31286
|
+
this.pos++;
|
|
31287
|
+
while (this.pos < this.input.length && /[A-Za-z0-9_]/.test(this.input[this.pos])) {
|
|
31288
|
+
this.pos++;
|
|
31289
|
+
}
|
|
31290
|
+
const nameLength = this.pos - start - 1;
|
|
31291
|
+
if (nameLength > 64) {
|
|
31292
|
+
throw new LexError("\u5909\u6570\u540D\u306F 64 \u6587\u5B57\u4EE5\u5185\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044", start, this.input);
|
|
31293
|
+
}
|
|
31294
|
+
return this.makeToken("VARIABLE" /* VARIABLE */, this.input.slice(start, this.pos), start);
|
|
31295
|
+
}
|
|
31278
31296
|
// ----------------------------------------------------------
|
|
31279
31297
|
// 空白・コメントをスキップ
|
|
31280
31298
|
// ----------------------------------------------------------
|
|
@@ -31486,6 +31504,8 @@ var Parser = class {
|
|
|
31486
31504
|
return this.parseDescribe();
|
|
31487
31505
|
case "EXPLAIN" /* EXPLAIN */:
|
|
31488
31506
|
return this.parseExplain();
|
|
31507
|
+
case "SET" /* SET */:
|
|
31508
|
+
return this.parseSetVariable();
|
|
31489
31509
|
case "ASSERT" /* ASSERT */:
|
|
31490
31510
|
return this.parseAssert();
|
|
31491
31511
|
case "IDENT" /* IDENT */: {
|
|
@@ -31498,11 +31518,65 @@ var Parser = class {
|
|
|
31498
31518
|
break;
|
|
31499
31519
|
}
|
|
31500
31520
|
throw new ParseError(
|
|
31501
|
-
"SELECT / INSERT / UPDATE / DELETE / REORDER / WITH / SHOW / DESCRIBE / EXPLAIN / CREATE TEMP TABLE / DROP TEMP TABLE / ASSERT \u306E\u3044\u305A\u308C\u304B\u3067\u59CB\u307E\u308B SQL \u6587\u304C\u5FC5\u8981\u3067\u3059",
|
|
31521
|
+
"SELECT / INSERT / UPDATE / DELETE / REORDER / WITH / SHOW / DESCRIBE / EXPLAIN / CREATE TEMP TABLE / DROP TEMP TABLE / SET / ASSERT \u306E\u3044\u305A\u308C\u304B\u3067\u59CB\u307E\u308B SQL \u6587\u304C\u5FC5\u8981\u3067\u3059",
|
|
31502
31522
|
tok
|
|
31503
31523
|
);
|
|
31504
31524
|
}
|
|
31505
31525
|
// ----------------------------------------------------------
|
|
31526
|
+
// SET @name = <ScalarExpr>
|
|
31527
|
+
// ----------------------------------------------------------
|
|
31528
|
+
parseSetVariable() {
|
|
31529
|
+
this.expect("SET" /* SET */);
|
|
31530
|
+
const variable = this.expect("VARIABLE" /* VARIABLE */, "SET \u306E\u5F8C\u306B\u306F\u5909\u6570\u540D\uFF08\u4F8B: @name\uFF09\u304C\u5FC5\u8981\u3067\u3059");
|
|
31531
|
+
this.expect("=" /* EQ */);
|
|
31532
|
+
const expr = this.parseScalarExpr();
|
|
31533
|
+
return { type: "SET_VARIABLE", name: variable.value.slice(1).toLowerCase(), expr };
|
|
31534
|
+
}
|
|
31535
|
+
/** SET RHS 専用。既存式パーサーで構文を読み、フィールド参照を明示的に拒否する。 */
|
|
31536
|
+
parseScalarExpr() {
|
|
31537
|
+
const tok = this.peek();
|
|
31538
|
+
if (tok.kind === "VARIABLE" /* VARIABLE */) {
|
|
31539
|
+
throw new ParseError("SET \u306E\u53F3\u8FBA\u3067\u306F\u4ED6\u306E\u5909\u6570\u3092\u53C2\u7167\u3067\u304D\u307E\u305B\u3093\uFF08Phase 1a\uFF09", tok);
|
|
31540
|
+
}
|
|
31541
|
+
if (tok.kind === "NULL" /* NULL */) {
|
|
31542
|
+
throw new ParseError("SET \u306E\u53F3\u8FBA\u3067 NULL \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\uFF08Phase 1a\uFF09", tok);
|
|
31543
|
+
}
|
|
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);
|
|
31546
|
+
}
|
|
31547
|
+
if (tok.kind === "STRING" /* STRING */) {
|
|
31548
|
+
this.advance();
|
|
31549
|
+
return { type: "STRING", value: tok.value };
|
|
31550
|
+
}
|
|
31551
|
+
if (tok.kind === "LOGINUSER" /* LOGINUSER */) {
|
|
31552
|
+
throw new ParseError(
|
|
31553
|
+
"SET \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",
|
|
31554
|
+
tok
|
|
31555
|
+
);
|
|
31556
|
+
}
|
|
31557
|
+
if (tok.kind === "TODAY" /* TODAY */ || tok.kind === "NOW" /* NOW */) {
|
|
31558
|
+
return this.parseSqlValue();
|
|
31559
|
+
}
|
|
31560
|
+
const expr = this.parseArithAddSub();
|
|
31561
|
+
this.rejectNonScalarExpr(expr, tok);
|
|
31562
|
+
if (expr.type === "NUMBER" || expr.type === "STRING_FUNC" || expr.type === "ARITH") return expr;
|
|
31563
|
+
throw new ParseError("SET \u306E\u53F3\u8FBA\u306B\u306F\u30D5\u30A3\u30FC\u30EB\u30C9\u53C2\u7167\u3092\u542B\u307E\u306A\u3044\u30B9\u30AB\u30E9\u30FC\u5F0F\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044", tok);
|
|
31564
|
+
}
|
|
31565
|
+
rejectNonScalarExpr(node, tok) {
|
|
31566
|
+
if (node.type === "STRING" || node.type === "NUMBER") return;
|
|
31567
|
+
if (node.type === "FIELD_REF" || node.type === "AGG_REF") {
|
|
31568
|
+
throw new ParseError("SET \u306E\u53F3\u8FBA\u3067\u306F\u30D5\u30A3\u30FC\u30EB\u30C9\u53C2\u7167\u30FB\u96C6\u8A08\u95A2\u6570\u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", tok);
|
|
31569
|
+
}
|
|
31570
|
+
if (node.type === "ARITH" || node.type === "AGG_ARITH") {
|
|
31571
|
+
this.rejectNonScalarExpr(node.left, tok);
|
|
31572
|
+
this.rejectNonScalarExpr(node.right, tok);
|
|
31573
|
+
return;
|
|
31574
|
+
}
|
|
31575
|
+
if (node.type === "STRING_FUNC") {
|
|
31576
|
+
for (const arg of node.args) this.rejectNonScalarExpr(arg, tok);
|
|
31577
|
+
}
|
|
31578
|
+
}
|
|
31579
|
+
// ----------------------------------------------------------
|
|
31506
31580
|
// CREATE TEMP TABLE / DROP TEMP TABLE(バッチ内一時テーブル)
|
|
31507
31581
|
// CREATE / DROP / TEMP / TABLE は予約語にしない(ソフトキーワード)
|
|
31508
31582
|
// ----------------------------------------------------------
|
|
@@ -31646,6 +31720,10 @@ var Parser = class {
|
|
|
31646
31720
|
/** ASSERT のオペランド: 文字列 / スカラーサブクエリ / 数値算術式 */
|
|
31647
31721
|
parseAssertOperand() {
|
|
31648
31722
|
const tok = this.peek();
|
|
31723
|
+
if (tok.kind === "VARIABLE" /* VARIABLE */) {
|
|
31724
|
+
this.advance();
|
|
31725
|
+
return { type: "VARIABLE", name: tok.value.slice(1).toLowerCase() };
|
|
31726
|
+
}
|
|
31649
31727
|
if (tok.kind === "STRING" /* STRING */) {
|
|
31650
31728
|
this.advance();
|
|
31651
31729
|
return { type: "STRING", value: tok.value };
|
|
@@ -32553,6 +32631,10 @@ var Parser = class {
|
|
|
32553
32631
|
// 右辺の値
|
|
32554
32632
|
parseSqlValue() {
|
|
32555
32633
|
const tok = this.peek();
|
|
32634
|
+
if (tok.kind === "VARIABLE" /* VARIABLE */) {
|
|
32635
|
+
this.advance();
|
|
32636
|
+
return { type: "VARIABLE", name: tok.value.slice(1).toLowerCase() };
|
|
32637
|
+
}
|
|
32556
32638
|
if (tok.kind === "STRING" /* STRING */) {
|
|
32557
32639
|
this.advance();
|
|
32558
32640
|
return { type: "STRING", value: tok.value };
|
|
@@ -32615,8 +32697,10 @@ var Parser = class {
|
|
|
32615
32697
|
values.push({ type: "STRING", value: tok.value });
|
|
32616
32698
|
} else if (tok.kind === "NUMBER" /* NUMBER */) {
|
|
32617
32699
|
values.push({ type: "NUMBER", value: Number(tok.value) });
|
|
32700
|
+
} else if (tok.kind === "VARIABLE" /* VARIABLE */) {
|
|
32701
|
+
values.push({ type: "VARIABLE", name: tok.value.slice(1).toLowerCase() });
|
|
32618
32702
|
} else {
|
|
32619
|
-
throw new ParseError("IN \u30EA\u30B9\u30C8\u306B\u306F\u6587\u5B57\u5217\u307E\u305F\u306F\u6570\
|
|
32703
|
+
throw new ParseError("IN \u30EA\u30B9\u30C8\u306B\u306F\u6587\u5B57\u5217\u3001\u6570\u5024\u3001\u307E\u305F\u306F\u30D0\u30C3\u30C1\u5909\u6570\u304C\u5FC5\u8981\u3067\u3059", tok);
|
|
32620
32704
|
}
|
|
32621
32705
|
} while (this.consume("," /* COMMA */));
|
|
32622
32706
|
return values;
|
|
@@ -32848,6 +32932,7 @@ var Parser = class {
|
|
|
32848
32932
|
*/
|
|
32849
32933
|
parseAssignmentValue() {
|
|
32850
32934
|
const tok = this.peek();
|
|
32935
|
+
if (tok.kind === "VARIABLE" /* VARIABLE */) return this.parseSqlValue();
|
|
32851
32936
|
if (tok.kind === "STRING" /* STRING */) return this.parseSqlValue();
|
|
32852
32937
|
if (tok.kind === "TODAY" /* TODAY */ || tok.kind === "NOW" /* NOW */ || tok.kind === "LOGINUSER" /* LOGINUSER */) return this.parseSqlValue();
|
|
32853
32938
|
if (tok.kind === "IN" /* IN */) return this.parseSqlValue();
|
|
@@ -33109,7 +33194,7 @@ function isDmlType(type) {
|
|
|
33109
33194
|
return type === "INSERT" || type === "INSERT_SELECT" || type === "UPDATE" || type === "DELETE" || type === "UPSERT" || type === "UPSERT_SELECT" || type === "REORDER";
|
|
33110
33195
|
}
|
|
33111
33196
|
function isReadOnlyType(type) {
|
|
33112
|
-
return type === "SELECT" || type === "UNION" || type === "WITH" || type === "EXPLAIN" || type === "SHOW_APPS" || type === "DESCRIBE" || type === "CREATE_TEMP_TABLE" || type === "DROP_TEMP_TABLE" || type === "ASSERT";
|
|
33197
|
+
return type === "SELECT" || type === "UNION" || type === "WITH" || type === "EXPLAIN" || type === "SHOW_APPS" || type === "DESCRIBE" || type === "CREATE_TEMP_TABLE" || type === "DROP_TEMP_TABLE" || type === "SET_VARIABLE" || type === "ASSERT";
|
|
33113
33198
|
}
|
|
33114
33199
|
function hasWhereClause(stmt) {
|
|
33115
33200
|
if (!stmt || typeof stmt !== "object") return false;
|
|
@@ -33130,6 +33215,7 @@ function getInsertValuesCount(stmt) {
|
|
|
33130
33215
|
|
|
33131
33216
|
// src/core/batch.ts
|
|
33132
33217
|
var MAX_TEMP_TABLES = 16;
|
|
33218
|
+
var MAX_BATCH_VARIABLES = 64;
|
|
33133
33219
|
var BatchAnalysisError = class extends Error {
|
|
33134
33220
|
constructor(message, statementIndex) {
|
|
33135
33221
|
super(message);
|
|
@@ -33150,12 +33236,29 @@ function collectRefs(node, tempRefs, appIds) {
|
|
|
33150
33236
|
for (const v of Object.values(obj)) collectRefs(v, tempRefs, appIds);
|
|
33151
33237
|
}
|
|
33152
33238
|
}
|
|
33239
|
+
function collectVariableRefs(node, refs) {
|
|
33240
|
+
if (Array.isArray(node)) {
|
|
33241
|
+
for (const v of node) collectVariableRefs(v, refs);
|
|
33242
|
+
return;
|
|
33243
|
+
}
|
|
33244
|
+
if (node !== null && typeof node === "object") {
|
|
33245
|
+
const obj = node;
|
|
33246
|
+
if (obj["type"] === "VARIABLE" && typeof obj["name"] === "string") {
|
|
33247
|
+
refs.add(obj["name"]);
|
|
33248
|
+
return;
|
|
33249
|
+
}
|
|
33250
|
+
for (const v of Object.values(obj)) collectVariableRefs(v, refs);
|
|
33251
|
+
}
|
|
33252
|
+
}
|
|
33153
33253
|
function analyzeBatch(statements) {
|
|
33154
33254
|
if (statements.length === 0) {
|
|
33155
33255
|
throw new BatchAnalysisError("ArgumentError: SQL is empty.", 0);
|
|
33156
33256
|
}
|
|
33157
33257
|
if (statements.length === 1) {
|
|
33158
33258
|
const t = statements[0].type;
|
|
33259
|
+
if (t === "SET_VARIABLE") {
|
|
33260
|
+
throw new BatchAnalysisError("ArgumentError: SET variable requires a batch.", 0);
|
|
33261
|
+
}
|
|
33159
33262
|
if (t === "CREATE_TEMP_TABLE" || t === "DROP_TEMP_TABLE") {
|
|
33160
33263
|
const verb = t === "CREATE_TEMP_TABLE" ? "CREATE TEMP TABLE" : "DROP TEMP TABLE";
|
|
33161
33264
|
throw new BatchAnalysisError(
|
|
@@ -33167,6 +33270,8 @@ function analyzeBatch(statements) {
|
|
|
33167
33270
|
const defined = /* @__PURE__ */ new Map();
|
|
33168
33271
|
const createdOrder = [];
|
|
33169
33272
|
const results = [];
|
|
33273
|
+
const variableDefs = /* @__PURE__ */ new Map();
|
|
33274
|
+
const variableOrder = [];
|
|
33170
33275
|
statements.forEach((stmt, index) => {
|
|
33171
33276
|
const statementType = getStatementType(stmt);
|
|
33172
33277
|
const created = [];
|
|
@@ -33174,6 +33279,31 @@ function analyzeBatch(statements) {
|
|
|
33174
33279
|
const refs = /* @__PURE__ */ new Set();
|
|
33175
33280
|
const stmtAppIds = /* @__PURE__ */ new Set();
|
|
33176
33281
|
const dependsOn = /* @__PURE__ */ new Set();
|
|
33282
|
+
const variableRefs = /* @__PURE__ */ new Set();
|
|
33283
|
+
collectVariableRefs(stmt, variableRefs);
|
|
33284
|
+
for (const name of variableRefs) {
|
|
33285
|
+
const def = variableDefs.get(name);
|
|
33286
|
+
if (def === void 0) {
|
|
33287
|
+
throw new BatchAnalysisError(
|
|
33288
|
+
`ParseError: variable @${name} is not defined before statement ${index + 1}.`,
|
|
33289
|
+
index
|
|
33290
|
+
);
|
|
33291
|
+
}
|
|
33292
|
+
def.referencedBy.push(index);
|
|
33293
|
+
}
|
|
33294
|
+
if (stmt.type === "SET_VARIABLE") {
|
|
33295
|
+
if (variableDefs.has(stmt.name)) {
|
|
33296
|
+
throw new BatchAnalysisError(`ParseError: variable @${stmt.name} is already defined.`, index);
|
|
33297
|
+
}
|
|
33298
|
+
variableDefs.set(stmt.name, { index, referencedBy: [] });
|
|
33299
|
+
variableOrder.push(stmt.name);
|
|
33300
|
+
if (variableOrder.length > MAX_BATCH_VARIABLES) {
|
|
33301
|
+
throw new BatchAnalysisError(
|
|
33302
|
+
`ParseError: batch exceeds ${MAX_BATCH_VARIABLES} variables.`,
|
|
33303
|
+
index
|
|
33304
|
+
);
|
|
33305
|
+
}
|
|
33306
|
+
}
|
|
33177
33307
|
if (stmt.type === "CREATE_TEMP_TABLE") {
|
|
33178
33308
|
collectRefs(stmt.query, refs, stmtAppIds);
|
|
33179
33309
|
} else if (stmt.type === "DROP_TEMP_TABLE") {
|
|
@@ -33243,11 +33373,17 @@ function analyzeBatch(statements) {
|
|
|
33243
33373
|
});
|
|
33244
33374
|
});
|
|
33245
33375
|
const containsDml = results.some((r) => r.isDml);
|
|
33376
|
+
const variables = variableOrder.map((name) => ({
|
|
33377
|
+
name,
|
|
33378
|
+
referencedBy: [...variableDefs.get(name).referencedBy]
|
|
33379
|
+
}));
|
|
33246
33380
|
return {
|
|
33247
33381
|
statementCount: statements.length,
|
|
33248
33382
|
isReadOnlyBatch: !containsDml && results.every((r) => r.isReadOnly),
|
|
33249
33383
|
containsDml,
|
|
33250
33384
|
tempTables: createdOrder,
|
|
33385
|
+
variables,
|
|
33386
|
+
warnings: variables.filter((v) => v.referencedBy.length === 0).map((v) => `variable @${v.name} is never used.`),
|
|
33251
33387
|
statements: results
|
|
33252
33388
|
};
|
|
33253
33389
|
}
|
|
@@ -33418,6 +33554,8 @@ function convertField(field) {
|
|
|
33418
33554
|
}
|
|
33419
33555
|
function convertValue(value, op) {
|
|
33420
33556
|
switch (value.type) {
|
|
33557
|
+
case "VARIABLE":
|
|
33558
|
+
throw new KintoneQueryError(`\u672A\u89E3\u6C7A\u306E\u30D0\u30C3\u30C1\u5909\u6570 @${value.name} \u304C\u3042\u308A\u307E\u3059`);
|
|
33421
33559
|
case "STRING":
|
|
33422
33560
|
return convertString(value);
|
|
33423
33561
|
case "NUMBER":
|
|
@@ -33448,11 +33586,18 @@ function convertInList(v, op) {
|
|
|
33448
33586
|
if (op !== "IN" && op !== "NOT_IN") {
|
|
33449
33587
|
throw new KintoneQueryError("IN_LIST \u306F IN / NOT IN \u6F14\u7B97\u5B50\u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059");
|
|
33450
33588
|
}
|
|
33589
|
+
assertResolvedInListValues(v.values);
|
|
33451
33590
|
const values = v.values.map(
|
|
33452
33591
|
(item) => item.type === "STRING" ? convertString(item) : String(item.value)
|
|
33453
33592
|
).join(",");
|
|
33454
33593
|
return `(${values})`;
|
|
33455
33594
|
}
|
|
33595
|
+
function assertResolvedInListValues(values) {
|
|
33596
|
+
const unresolved = values.find((item) => item.type === "VARIABLE");
|
|
33597
|
+
if (unresolved?.type === "VARIABLE") {
|
|
33598
|
+
throw new KintoneQueryError(`\u672A\u89E3\u6C7A\u306E\u30D0\u30C3\u30C1\u5909\u6570 @${unresolved.name} \u304C\u3042\u308A\u307E\u3059`);
|
|
33599
|
+
}
|
|
33600
|
+
}
|
|
33456
33601
|
function quoteIdentifier(name) {
|
|
33457
33602
|
if (/^[\w$\u3000-\u9FFF]+$/u.test(name)) {
|
|
33458
33603
|
return name;
|
|
@@ -34196,15 +34341,17 @@ function evalBinary(expr, row) {
|
|
|
34196
34341
|
return evalOp(expr.op, left, expr.right, row);
|
|
34197
34342
|
}
|
|
34198
34343
|
function evalOp(op, leftStr, right, row) {
|
|
34199
|
-
if (op === "IN") {
|
|
34200
|
-
if (right.type === "IN_LIST")
|
|
34201
|
-
|
|
34202
|
-
|
|
34203
|
-
|
|
34204
|
-
|
|
34205
|
-
if (right.type === "
|
|
34206
|
-
|
|
34207
|
-
|
|
34344
|
+
if (op === "IN" || op === "NOT_IN") {
|
|
34345
|
+
if (right.type === "IN_LIST") {
|
|
34346
|
+
assertResolvedInListValues2(right.values);
|
|
34347
|
+
const contains = right.values.some((v) => leftStr === String(v.value));
|
|
34348
|
+
return op === "IN" ? contains : !contains;
|
|
34349
|
+
}
|
|
34350
|
+
if (right.type === "SUBQUERY_IN_LIST") {
|
|
34351
|
+
const contains = right.resolved.has(leftStr);
|
|
34352
|
+
return op === "IN" ? contains : !contains;
|
|
34353
|
+
}
|
|
34354
|
+
return op === "NOT_IN";
|
|
34208
34355
|
}
|
|
34209
34356
|
if (op === "LIKE") {
|
|
34210
34357
|
const pattern = resolveValue(right, row);
|
|
@@ -34234,6 +34381,12 @@ function evalOp(op, leftStr, right, row) {
|
|
|
34234
34381
|
return numeric ? leftNum <= rightNum : leftStr <= rightStr;
|
|
34235
34382
|
}
|
|
34236
34383
|
}
|
|
34384
|
+
function assertResolvedInListValues2(values) {
|
|
34385
|
+
const unresolved = values.find((item) => item.type === "VARIABLE");
|
|
34386
|
+
if (unresolved?.type === "VARIABLE") {
|
|
34387
|
+
throw new Error(`ParseError: unresolved batch variable @${unresolved.name}.`);
|
|
34388
|
+
}
|
|
34389
|
+
}
|
|
34237
34390
|
function evalNullCheck(expr, row) {
|
|
34238
34391
|
const val = resolveField(expr.field, row);
|
|
34239
34392
|
return expr.not ? val !== "" : val === "";
|
|
@@ -34253,6 +34406,8 @@ function resolveField(field, row) {
|
|
|
34253
34406
|
}
|
|
34254
34407
|
function resolveValue(value, row) {
|
|
34255
34408
|
switch (value.type) {
|
|
34409
|
+
case "VARIABLE":
|
|
34410
|
+
throw new Error(`ParseError: unresolved batch variable @${value.name}.`);
|
|
34256
34411
|
case "STRING":
|
|
34257
34412
|
return value.value;
|
|
34258
34413
|
case "NUMBER":
|
|
@@ -34616,6 +34771,8 @@ function evalCaseWhenValue(expr, row, fieldType) {
|
|
|
34616
34771
|
}
|
|
34617
34772
|
function toKintoneValue(value, fieldType) {
|
|
34618
34773
|
switch (value.type) {
|
|
34774
|
+
case "VARIABLE":
|
|
34775
|
+
throw new DmlConvertError(`\u672A\u89E3\u6C7A\u306E\u30D0\u30C3\u30C1\u5909\u6570 @${value.name} \u304C\u3042\u308A\u307E\u3059`);
|
|
34619
34776
|
case "STRING":
|
|
34620
34777
|
return convertString2(value.value, fieldType);
|
|
34621
34778
|
case "NUMBER":
|
|
@@ -35206,8 +35363,12 @@ function project(rows, columns, scalarCache) {
|
|
|
35206
35363
|
const cols = projected2.length > 0 ? Object.keys(projected2[0]) : [];
|
|
35207
35364
|
return { rows: projected2, columns: cols };
|
|
35208
35365
|
}
|
|
35209
|
-
const orderedKeys = [];
|
|
35210
35366
|
const defaultFieldKeys = buildDefaultFieldOutputKeys(columns);
|
|
35367
|
+
const hasWildcard = columns.some(
|
|
35368
|
+
(col) => col.type === "WILDCARD" || col.type === "PARENT_WILDCARD"
|
|
35369
|
+
);
|
|
35370
|
+
const outputKeys = hasWildcard ? null : computeOutputKeys(columns, defaultFieldKeys);
|
|
35371
|
+
const orderedKeys = outputKeys ?? [];
|
|
35211
35372
|
const projected = rows.map((row, rowIdx) => {
|
|
35212
35373
|
const out = {};
|
|
35213
35374
|
for (const [colIdx, col] of columns.entries()) {
|
|
@@ -35224,58 +35385,58 @@ function project(rows, columns, scalarCache) {
|
|
|
35224
35385
|
break;
|
|
35225
35386
|
}
|
|
35226
35387
|
case "FIELD": {
|
|
35227
|
-
const key = col.alias ?? defaultFieldKeys.get(colIdx) ?? col.field;
|
|
35388
|
+
const key = outputKeys?.[colIdx] ?? col.alias ?? defaultFieldKeys.get(colIdx) ?? col.field;
|
|
35228
35389
|
out[key] = resolveFieldRef(row, col.field);
|
|
35229
|
-
if (rowIdx === 0) orderedKeys.push(key);
|
|
35390
|
+
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
35230
35391
|
break;
|
|
35231
35392
|
}
|
|
35232
35393
|
case "LITERAL_COL": {
|
|
35233
|
-
const key = col.alias ?? `'${col.value}'`;
|
|
35394
|
+
const key = outputKeys?.[colIdx] ?? col.alias ?? `'${col.value}'`;
|
|
35234
35395
|
out[key] = col.value;
|
|
35235
|
-
if (rowIdx === 0) orderedKeys.push(key);
|
|
35396
|
+
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
35236
35397
|
break;
|
|
35237
35398
|
}
|
|
35238
35399
|
case "AGGREGATE": {
|
|
35239
35400
|
const srcKey = aggregateSyntheticName2(col.func, col.distinct, col.arg);
|
|
35240
|
-
const dstKey = col.alias ?? srcKey;
|
|
35401
|
+
const dstKey = outputKeys?.[colIdx] ?? col.alias ?? srcKey;
|
|
35241
35402
|
out[dstKey] = row[col.alias ?? srcKey] ?? row[srcKey] ?? "0";
|
|
35242
|
-
if (rowIdx === 0) orderedKeys.push(dstKey);
|
|
35403
|
+
if (outputKeys === null && rowIdx === 0) orderedKeys.push(dstKey);
|
|
35243
35404
|
break;
|
|
35244
35405
|
}
|
|
35245
35406
|
case "ARITH_AGG_COL": {
|
|
35246
|
-
const key = col.alias ?? aggArithDefaultKey(col.expr);
|
|
35407
|
+
const key = outputKeys?.[colIdx] ?? col.alias ?? aggArithDefaultKey(col.expr);
|
|
35247
35408
|
out[key] = row[key] ?? "0";
|
|
35248
|
-
if (rowIdx === 0) orderedKeys.push(key);
|
|
35409
|
+
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
35249
35410
|
break;
|
|
35250
35411
|
}
|
|
35251
35412
|
case "ARITH_COL": {
|
|
35252
35413
|
const val = evalArithExpr(col.expr, row);
|
|
35253
|
-
const key = col.alias ?? arithColDefaultKey(col.expr);
|
|
35414
|
+
const key = outputKeys?.[colIdx] ?? col.alias ?? arithColDefaultKey(col.expr);
|
|
35254
35415
|
out[key] = String(val);
|
|
35255
|
-
if (rowIdx === 0) orderedKeys.push(key);
|
|
35416
|
+
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
35256
35417
|
break;
|
|
35257
35418
|
}
|
|
35258
35419
|
case "CASE_COL": {
|
|
35259
|
-
const key = col.alias ?? "case";
|
|
35420
|
+
const key = outputKeys?.[colIdx] ?? col.alias ?? "case";
|
|
35260
35421
|
out[key] = evalCaseWhen(col.expr, row);
|
|
35261
|
-
if (rowIdx === 0) orderedKeys.push(key);
|
|
35422
|
+
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
35262
35423
|
break;
|
|
35263
35424
|
}
|
|
35264
35425
|
case "STRFUNC_COL": {
|
|
35265
|
-
const key = col.alias ?? stringFuncDefaultKey(col.expr);
|
|
35426
|
+
const key = outputKeys?.[colIdx] ?? col.alias ?? stringFuncDefaultKey(col.expr);
|
|
35266
35427
|
if (hasAggregateInStringFuncExpr2(col.expr)) {
|
|
35267
35428
|
const srcKey = stringFuncDefaultKey(col.expr);
|
|
35268
35429
|
out[key] = row[col.alias ?? srcKey] ?? row[srcKey] ?? evalStringFunc(col.expr, row);
|
|
35269
35430
|
} else {
|
|
35270
35431
|
out[key] = evalStringFunc(col.expr, row);
|
|
35271
35432
|
}
|
|
35272
|
-
if (rowIdx === 0) orderedKeys.push(key);
|
|
35433
|
+
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
35273
35434
|
break;
|
|
35274
35435
|
}
|
|
35275
35436
|
case "SCALAR_SUBQUERY_COL": {
|
|
35276
|
-
const key = col.alias ?? "(subquery)";
|
|
35437
|
+
const key = outputKeys?.[colIdx] ?? col.alias ?? "(subquery)";
|
|
35277
35438
|
out[key] = scalarCache?.get(colIdx) ?? "";
|
|
35278
|
-
if (rowIdx === 0) orderedKeys.push(key);
|
|
35439
|
+
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
35279
35440
|
break;
|
|
35280
35441
|
}
|
|
35281
35442
|
}
|
|
@@ -35284,6 +35445,31 @@ function project(rows, columns, scalarCache) {
|
|
|
35284
35445
|
});
|
|
35285
35446
|
return { rows: projected, columns: orderedKeys };
|
|
35286
35447
|
}
|
|
35448
|
+
function computeOutputKeys(columns, defaultFieldKeys) {
|
|
35449
|
+
return columns.map((col, colIdx) => {
|
|
35450
|
+
switch (col.type) {
|
|
35451
|
+
case "FIELD":
|
|
35452
|
+
return col.alias ?? defaultFieldKeys.get(colIdx) ?? col.field;
|
|
35453
|
+
case "LITERAL_COL":
|
|
35454
|
+
return col.alias ?? `'${col.value}'`;
|
|
35455
|
+
case "AGGREGATE":
|
|
35456
|
+
return col.alias ?? aggregateSyntheticName2(col.func, col.distinct, col.arg);
|
|
35457
|
+
case "ARITH_AGG_COL":
|
|
35458
|
+
return col.alias ?? aggArithDefaultKey(col.expr);
|
|
35459
|
+
case "ARITH_COL":
|
|
35460
|
+
return col.alias ?? arithColDefaultKey(col.expr);
|
|
35461
|
+
case "CASE_COL":
|
|
35462
|
+
return col.alias ?? "case";
|
|
35463
|
+
case "STRFUNC_COL":
|
|
35464
|
+
return col.alias ?? stringFuncDefaultKey(col.expr);
|
|
35465
|
+
case "SCALAR_SUBQUERY_COL":
|
|
35466
|
+
return col.alias ?? "(subquery)";
|
|
35467
|
+
case "WILDCARD":
|
|
35468
|
+
case "PARENT_WILDCARD":
|
|
35469
|
+
throw new Error("internal: computeOutputKeys received a wildcard column");
|
|
35470
|
+
}
|
|
35471
|
+
});
|
|
35472
|
+
}
|
|
35287
35473
|
function buildDefaultFieldOutputKeys(columns) {
|
|
35288
35474
|
const qualifierCollisionCount = /* @__PURE__ */ new Map();
|
|
35289
35475
|
for (const col of columns) {
|
|
@@ -35491,6 +35677,10 @@ async function executeStatement(sql, client, options) {
|
|
|
35491
35677
|
return executeParsedStatement(stmt, client, options, cacheContext);
|
|
35492
35678
|
}
|
|
35493
35679
|
async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
35680
|
+
const unresolved = findVariableRef(stmt);
|
|
35681
|
+
if (unresolved !== null) {
|
|
35682
|
+
throw new Error(`ParseError: variable @${unresolved} is not defined in a batch.`);
|
|
35683
|
+
}
|
|
35494
35684
|
switch (stmt.type) {
|
|
35495
35685
|
case "SELECT":
|
|
35496
35686
|
return executeSelect(stmt, client, options, cacheContext);
|
|
@@ -35523,6 +35713,8 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
|
35523
35713
|
throw new Error("ArgumentError: CREATE TEMP TABLE requires a batch (temp tables are batch-scoped).");
|
|
35524
35714
|
case "DROP_TEMP_TABLE":
|
|
35525
35715
|
throw new Error("ArgumentError: DROP TEMP TABLE requires a batch (temp tables are batch-scoped).");
|
|
35716
|
+
case "SET_VARIABLE":
|
|
35717
|
+
throw new Error("ArgumentError: SET variable requires a batch.");
|
|
35526
35718
|
case "ASSERT":
|
|
35527
35719
|
return executeAssert(stmt, client, options, cacheContext);
|
|
35528
35720
|
}
|
|
@@ -35553,6 +35745,7 @@ async function executeBatch(sql, client, options = {}) {
|
|
|
35553
35745
|
const deadline = options.timeoutMs != null ? startedAt + options.timeoutMs : null;
|
|
35554
35746
|
const cacheContext = options.cacheContext ?? "default";
|
|
35555
35747
|
const tempTables = /* @__PURE__ */ new Map();
|
|
35748
|
+
const variables = /* @__PURE__ */ new Map();
|
|
35556
35749
|
const results = [];
|
|
35557
35750
|
const failed = /* @__PURE__ */ new Set();
|
|
35558
35751
|
let aborted2 = null;
|
|
@@ -35590,7 +35783,7 @@ async function executeBatch(sql, client, options = {}) {
|
|
|
35590
35783
|
})
|
|
35591
35784
|
} : options;
|
|
35592
35785
|
const outcome = await runWithDeadline(
|
|
35593
|
-
executeBatchStatement(statements[i], info, countedClient, stmtOptions, cacheContext, tempTables),
|
|
35786
|
+
executeBatchStatement(statements[i], info, countedClient, stmtOptions, cacheContext, tempTables, variables),
|
|
35594
35787
|
remaining
|
|
35595
35788
|
);
|
|
35596
35789
|
results.push({ ...base, status: "success", ...outcome });
|
|
@@ -35601,6 +35794,8 @@ async function executeBatch(sql, client, options = {}) {
|
|
|
35601
35794
|
aborted2 = "timeout";
|
|
35602
35795
|
} else if (e instanceof AssertError) {
|
|
35603
35796
|
aborted2 = "assertion";
|
|
35797
|
+
} else if (info.statementType === "SET_VARIABLE") {
|
|
35798
|
+
aborted2 = "fail-fast";
|
|
35604
35799
|
} else if (!options.continueOnError) {
|
|
35605
35800
|
aborted2 = "fail-fast";
|
|
35606
35801
|
}
|
|
@@ -35615,44 +35810,49 @@ async function executeBatch(sql, client, options = {}) {
|
|
|
35615
35810
|
metrics
|
|
35616
35811
|
};
|
|
35617
35812
|
}
|
|
35618
|
-
async function executeBatchStatement(stmt, info, client, options, cacheContext, tempTables) {
|
|
35619
|
-
if (stmt.type === "
|
|
35813
|
+
async function executeBatchStatement(stmt, info, client, options, cacheContext, tempTables, variables) {
|
|
35814
|
+
if (stmt.type === "SET_VARIABLE") {
|
|
35815
|
+
variables.set(stmt.name, evaluateScalarExpr(stmt.expr));
|
|
35816
|
+
return {};
|
|
35817
|
+
}
|
|
35818
|
+
const resolvedStmt = resolveVariableRefs(stmt, variables);
|
|
35819
|
+
if (resolvedStmt.type === "CREATE_TEMP_TABLE") {
|
|
35620
35820
|
const materializeOptions = {
|
|
35621
35821
|
...options,
|
|
35622
35822
|
maxRecords: options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
|
|
35623
35823
|
onLimitReached: "error"
|
|
35624
35824
|
};
|
|
35625
|
-
const result = await runSelectLike(
|
|
35626
|
-
tempTables.set(
|
|
35627
|
-
return { tempTable:
|
|
35825
|
+
const result = await runSelectLike(resolvedStmt.query, client, materializeOptions, cacheContext, tempTables);
|
|
35826
|
+
tempTables.set(resolvedStmt.name, result.rows);
|
|
35827
|
+
return { tempTable: resolvedStmt.name, rowCount: result.rows.length };
|
|
35628
35828
|
}
|
|
35629
35829
|
if (stmt.type === "DROP_TEMP_TABLE") {
|
|
35630
35830
|
tempTables.delete(stmt.name);
|
|
35631
35831
|
return { tempTable: stmt.name };
|
|
35632
35832
|
}
|
|
35633
35833
|
if (stmt.type === "EXPLAIN") {
|
|
35634
|
-
return { result: await executeParsedStatement(
|
|
35834
|
+
return { result: await executeParsedStatement(resolvedStmt, client, options, cacheContext) };
|
|
35635
35835
|
}
|
|
35636
|
-
if (
|
|
35637
|
-
await executeAssert(
|
|
35836
|
+
if (resolvedStmt.type === "ASSERT") {
|
|
35837
|
+
await executeAssert(resolvedStmt, client, options, cacheContext, tempTables);
|
|
35638
35838
|
return {};
|
|
35639
35839
|
}
|
|
35640
35840
|
if (info.tempTablesReferenced.length > 0) {
|
|
35641
|
-
if (
|
|
35642
|
-
return { result: await executeQueryWithCte(
|
|
35841
|
+
if (resolvedStmt.type === "SELECT" || resolvedStmt.type === "UNION") {
|
|
35842
|
+
return { result: await executeQueryWithCte(resolvedStmt, client, options, tempTables, cacheContext) };
|
|
35643
35843
|
}
|
|
35644
|
-
if (
|
|
35645
|
-
return { result: await executeWith(
|
|
35844
|
+
if (resolvedStmt.type === "WITH") {
|
|
35845
|
+
return { result: await executeWith(resolvedStmt, client, options, cacheContext, tempTables) };
|
|
35646
35846
|
}
|
|
35647
|
-
if (
|
|
35648
|
-
return { result: await executeInsertSelect(
|
|
35847
|
+
if (resolvedStmt.type === "INSERT_SELECT") {
|
|
35848
|
+
return { result: await executeInsertSelect(resolvedStmt, client, options, cacheContext, tempTables) };
|
|
35649
35849
|
}
|
|
35650
|
-
if (
|
|
35651
|
-
return { result: await executeUpsertSelect(
|
|
35850
|
+
if (resolvedStmt.type === "UPSERT_SELECT") {
|
|
35851
|
+
return { result: await executeUpsertSelect(resolvedStmt, client, options, cacheContext, tempTables) };
|
|
35652
35852
|
}
|
|
35653
35853
|
throw new Error(`ArgumentError: temp table references in ${stmt.type} are not supported yet.`);
|
|
35654
35854
|
}
|
|
35655
|
-
return { result: await executeParsedStatement(
|
|
35855
|
+
return { result: await executeParsedStatement(resolvedStmt, client, options, cacheContext) };
|
|
35656
35856
|
}
|
|
35657
35857
|
async function runSelectLike(query, client, options, cacheContext, tempTables) {
|
|
35658
35858
|
if (query.type === "WITH") {
|
|
@@ -35713,6 +35913,62 @@ function parseSqlBatch(sql) {
|
|
|
35713
35913
|
const tokens = new Lexer(sql).tokenize();
|
|
35714
35914
|
return new Parser(tokens).parseStatements();
|
|
35715
35915
|
}
|
|
35916
|
+
function evaluateScalarExpr(expr) {
|
|
35917
|
+
switch (expr.type) {
|
|
35918
|
+
case "STRING":
|
|
35919
|
+
return { type: "string", value: expr.value };
|
|
35920
|
+
case "NUMBER":
|
|
35921
|
+
return { type: "number", value: expr.value };
|
|
35922
|
+
case "KINTONE_FUNC":
|
|
35923
|
+
return { type: "string", value: resolveKintoneFunc(expr.name) };
|
|
35924
|
+
case "STRING_FUNC":
|
|
35925
|
+
return { type: "string", value: evalStringFunc(expr, {}) };
|
|
35926
|
+
case "ARITH": {
|
|
35927
|
+
const value = evalArithExpr(expr, {});
|
|
35928
|
+
if (!Number.isFinite(value)) {
|
|
35929
|
+
throw new Error("ArgumentError: SET scalar arithmetic produced a non-finite number.");
|
|
35930
|
+
}
|
|
35931
|
+
return { type: "number", value };
|
|
35932
|
+
}
|
|
35933
|
+
}
|
|
35934
|
+
}
|
|
35935
|
+
function resolveVariableRefs(node, variables) {
|
|
35936
|
+
if (Array.isArray(node)) {
|
|
35937
|
+
return node.map((v) => resolveVariableRefs(v, variables));
|
|
35938
|
+
}
|
|
35939
|
+
if (node !== null && typeof node === "object") {
|
|
35940
|
+
const obj = node;
|
|
35941
|
+
if (obj["type"] === "VARIABLE" && typeof obj["name"] === "string") {
|
|
35942
|
+
const value = variables.get(obj["name"]);
|
|
35943
|
+
if (value === void 0) {
|
|
35944
|
+
throw new Error(`ParseError: variable @${obj["name"]} is not defined in this batch.`);
|
|
35945
|
+
}
|
|
35946
|
+
return value.type === "number" ? { type: "NUMBER", value: value.value } : { type: "STRING", value: value.value };
|
|
35947
|
+
}
|
|
35948
|
+
return Object.fromEntries(
|
|
35949
|
+
Object.entries(obj).map(([key, value]) => [key, resolveVariableRefs(value, variables)])
|
|
35950
|
+
);
|
|
35951
|
+
}
|
|
35952
|
+
return node;
|
|
35953
|
+
}
|
|
35954
|
+
function findVariableRef(node) {
|
|
35955
|
+
if (Array.isArray(node)) {
|
|
35956
|
+
for (const value of node) {
|
|
35957
|
+
const found = findVariableRef(value);
|
|
35958
|
+
if (found !== null) return found;
|
|
35959
|
+
}
|
|
35960
|
+
return null;
|
|
35961
|
+
}
|
|
35962
|
+
if (node !== null && typeof node === "object") {
|
|
35963
|
+
const obj = node;
|
|
35964
|
+
if (obj["type"] === "VARIABLE" && typeof obj["name"] === "string") return obj["name"];
|
|
35965
|
+
for (const value of Object.values(obj)) {
|
|
35966
|
+
const found = findVariableRef(value);
|
|
35967
|
+
if (found !== null) return found;
|
|
35968
|
+
}
|
|
35969
|
+
}
|
|
35970
|
+
return null;
|
|
35971
|
+
}
|
|
35716
35972
|
var AssertError = class extends Error {
|
|
35717
35973
|
constructor(message) {
|
|
35718
35974
|
super(`AssertError: ${message}`);
|
|
@@ -35743,6 +35999,8 @@ async function executeAssert(stmt, client, options, cacheContext, tempTables) {
|
|
|
35743
35999
|
}
|
|
35744
36000
|
async function evalAssertOperand(operand, client, options, cacheContext, tempTables) {
|
|
35745
36001
|
switch (operand.type) {
|
|
36002
|
+
case "VARIABLE":
|
|
36003
|
+
throw new Error(`ParseError: unresolved batch variable @${operand.name}.`);
|
|
35746
36004
|
case "NUMBER":
|
|
35747
36005
|
return String(operand.value);
|
|
35748
36006
|
case "STRING":
|
|
@@ -36602,8 +36860,9 @@ async function executeInsertSelect(stmt, client, options, cacheContext, cteCache
|
|
|
36602
36860
|
const selectResult = cteCache !== void 0 && cteCache.size > 0 ? await executeQueryWithCte(stmt.select, client, options, cteCache, cacheContext) : await executeSelect(stmt.select, client, options, cacheContext);
|
|
36603
36861
|
const { rows, columns } = selectResult;
|
|
36604
36862
|
if (columns.length !== stmt.fields.length) {
|
|
36863
|
+
const emptySourceHint = columns.length === 0 && rows.length === 0 ? "\u3002\u7D50\u679C\u304C 0 \u884C\u306E\u305F\u3081\u5217\u3092\u7279\u5B9A\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08SELECT * \u3092\u7A7A\u30BD\u30FC\u30B9\u306B\u4F7F\u3046\u3068\u5217\u3092\u6C7A\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002\u660E\u793A\u5217\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF09" : "";
|
|
36605
36864
|
throw new Error(
|
|
36606
|
-
`SELECT \u306E\u5217\u6570\uFF08${columns.length}\uFF09\u3068 INSERT \u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u6570\uFF08${stmt.fields.length}\uFF09\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093`
|
|
36865
|
+
`SELECT \u306E\u5217\u6570\uFF08${columns.length}\uFF09\u3068 INSERT \u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u6570\uFF08${stmt.fields.length}\uFF09\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093${emptySourceHint}`
|
|
36607
36866
|
);
|
|
36608
36867
|
}
|
|
36609
36868
|
if (options.confirm) {
|
|
@@ -37076,8 +37335,9 @@ async function executeUpsertSelect(stmt, client, options, cacheContext, cteCache
|
|
|
37076
37335
|
const selectResult = cteCache !== void 0 && cteCache.size > 0 ? await executeQueryWithCte(stmt.select, client, options, cteCache, cacheContext) : await executeSelect(stmt.select, client, options, cacheContext);
|
|
37077
37336
|
const { rows, columns } = selectResult;
|
|
37078
37337
|
if (columns.length !== stmt.fields.length) {
|
|
37338
|
+
const emptySourceHint = columns.length === 0 && rows.length === 0 ? "\u3002\u7D50\u679C\u304C 0 \u884C\u306E\u305F\u3081\u5217\u3092\u7279\u5B9A\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08SELECT * \u3092\u7A7A\u30BD\u30FC\u30B9\u306B\u4F7F\u3046\u3068\u5217\u3092\u6C7A\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002\u660E\u793A\u5217\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF09" : "";
|
|
37079
37339
|
throw new Error(
|
|
37080
|
-
`SELECT \u306E\u5217\u6570\uFF08${columns.length}\uFF09\u3068 UPSERT \u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u6570\uFF08${stmt.fields.length}\uFF09\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093`
|
|
37340
|
+
`SELECT \u306E\u5217\u6570\uFF08${columns.length}\uFF09\u3068 UPSERT \u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u6570\uFF08${stmt.fields.length}\uFF09\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093${emptySourceHint}`
|
|
37081
37341
|
);
|
|
37082
37342
|
}
|
|
37083
37343
|
for (const key of stmt.keyFields) {
|
|
@@ -37244,13 +37504,21 @@ async function resolveScalarColumns(columns, client, options, cacheContext, cteC
|
|
|
37244
37504
|
function buildBatchExplainPlans(sql) {
|
|
37245
37505
|
const statements = parseSqlBatch(sql);
|
|
37246
37506
|
const analysis = analyzeBatch(statements);
|
|
37507
|
+
const variables = /* @__PURE__ */ new Map();
|
|
37247
37508
|
return {
|
|
37248
37509
|
statementCount: statements.length,
|
|
37249
|
-
statements: statements.map((stmt, i) =>
|
|
37250
|
-
|
|
37251
|
-
|
|
37252
|
-
|
|
37253
|
-
|
|
37510
|
+
statements: statements.map((stmt, i) => {
|
|
37511
|
+
const planStmt = stmt.type === "SET_VARIABLE" ? stmt : resolveVariableRefs(stmt, variables);
|
|
37512
|
+
const result = {
|
|
37513
|
+
index: i,
|
|
37514
|
+
type: analysis.statements[i].statementType,
|
|
37515
|
+
plan: buildBatchStatementPlan(planStmt, analysis.statements[i])
|
|
37516
|
+
};
|
|
37517
|
+
if (stmt.type === "SET_VARIABLE") {
|
|
37518
|
+
variables.set(stmt.name, { type: "string", value: `@${stmt.name}` });
|
|
37519
|
+
}
|
|
37520
|
+
return result;
|
|
37521
|
+
})
|
|
37254
37522
|
};
|
|
37255
37523
|
}
|
|
37256
37524
|
function buildBatchStatementPlan(stmt, info) {
|
|
@@ -37268,6 +37536,12 @@ function buildBatchStatementPlan(stmt, info) {
|
|
|
37268
37536
|
" \u4E00\u6642\u30C6\u30FC\u30D6\u30EB\u30B9\u30C8\u30A2\u306E\u89E3\u653E\u306E\u307F\uFF08kintone \u30A2\u30AF\u30BB\u30B9\u306A\u3057\uFF09"
|
|
37269
37537
|
];
|
|
37270
37538
|
}
|
|
37539
|
+
if (stmt.type === "SET_VARIABLE") {
|
|
37540
|
+
return [
|
|
37541
|
+
`SET @${stmt.name} = <scalar expression>`,
|
|
37542
|
+
" 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"
|
|
37543
|
+
];
|
|
37544
|
+
}
|
|
37271
37545
|
if (stmt.type === "SHOW_APPS") return ["SHOW APPS\uFF08\u30A2\u30D7\u30EA\u4E00\u89A7\u306E\u53D6\u5F97\uFF09"];
|
|
37272
37546
|
if (stmt.type === "DESCRIBE") return [`DESCRIBE APP${stmt.appId}\uFF08\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u306E\u53D6\u5F97\uFF09`];
|
|
37273
37547
|
if (stmt.type === "EXPLAIN") return buildPlanForBatchQuery(stmt.query, info);
|
|
@@ -39703,7 +39977,7 @@ Options:
|
|
|
39703
39977
|
-h, --help Show help
|
|
39704
39978
|
`);
|
|
39705
39979
|
}
|
|
39706
|
-
var SERVER_VERSION = true ? "2.
|
|
39980
|
+
var SERVER_VERSION = true ? "2.1.1" : "0.0.0-dev";
|
|
39707
39981
|
function createServer(args) {
|
|
39708
39982
|
const server = new McpServer({
|
|
39709
39983
|
name: "ksql-mcp",
|