@rex0220/kintone-sql-tools 1.13.1 → 2.0.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 +70 -17
- package/dist-mcp/ksql-mcp.js +67 -17
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -2407,6 +2407,29 @@ function negateOp(op) {
|
|
|
2407
2407
|
}
|
|
2408
2408
|
}
|
|
2409
2409
|
|
|
2410
|
+
// src/core/like.ts
|
|
2411
|
+
function likePatternHasWildcard(pattern) {
|
|
2412
|
+
return pattern.includes("%") || pattern.includes("_");
|
|
2413
|
+
}
|
|
2414
|
+
function isLike(where) {
|
|
2415
|
+
return where.type === "BINARY" && (where.op === "LIKE" || where.op === "NOT_LIKE");
|
|
2416
|
+
}
|
|
2417
|
+
function whereHasLike(where) {
|
|
2418
|
+
if (where === null) return false;
|
|
2419
|
+
if (isLike(where)) return true;
|
|
2420
|
+
switch (where.type) {
|
|
2421
|
+
case "LOGICAL":
|
|
2422
|
+
return whereHasLike(where.left) || whereHasLike(where.right);
|
|
2423
|
+
case "NOT":
|
|
2424
|
+
case "GROUP":
|
|
2425
|
+
return whereHasLike(where.expr);
|
|
2426
|
+
case "BINARY":
|
|
2427
|
+
case "NULL_CHECK":
|
|
2428
|
+
case "EXISTS":
|
|
2429
|
+
return false;
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2410
2433
|
// src/converter/whereToKintone.ts
|
|
2411
2434
|
function whereToKintone(expr) {
|
|
2412
2435
|
switch (expr.type) {
|
|
@@ -2425,6 +2448,11 @@ function whereToKintone(expr) {
|
|
|
2425
2448
|
}
|
|
2426
2449
|
}
|
|
2427
2450
|
function convertBinary(expr) {
|
|
2451
|
+
if (isLike(expr)) {
|
|
2452
|
+
throw new KintoneQueryError(
|
|
2453
|
+
"LIKE / NOT LIKE \u306F kintone \u30AF\u30A8\u30EA\u306B\u5909\u63DB\u3067\u304D\u307E\u305B\u3093\uFF08\u5E38\u306B JS \u8A55\u4FA1\u304C\u5FC5\u8981\u3067\u3059\uFF09"
|
|
2454
|
+
);
|
|
2455
|
+
}
|
|
2428
2456
|
const left = convertField(expr.left);
|
|
2429
2457
|
const op = convertOp(expr.op);
|
|
2430
2458
|
const right = convertValue(expr.right, expr.op);
|
|
@@ -2550,22 +2578,22 @@ function resolveSelectMode(stmt) {
|
|
|
2550
2578
|
if (stmt.columns.some(
|
|
2551
2579
|
(c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "SCALAR_SUBQUERY_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr(c.expr)
|
|
2552
2580
|
)) return "FULL_SCAN";
|
|
2553
|
-
if (
|
|
2581
|
+
if (whereRequiresJsEval(stmt.where)) return "FULL_SCAN";
|
|
2554
2582
|
if (stmt.orderBy.some((o) => o.key.type !== "FIELD_NAME")) return "FULL_SCAN";
|
|
2555
2583
|
return "SIMPLE";
|
|
2556
2584
|
}
|
|
2557
|
-
function
|
|
2585
|
+
function whereRequiresJsEval(where) {
|
|
2558
2586
|
if (where === null) return false;
|
|
2559
2587
|
switch (where.type) {
|
|
2560
2588
|
case "BINARY":
|
|
2561
|
-
return isFunc(where.left) || where.right.type === "ARITH_VALUE" || where.right.type === "CASE_VALUE" || where.right.type === "SUBQUERY_IN_LIST" || where.right.type === "SCALAR_SUBQUERY";
|
|
2589
|
+
return isFunc(where.left) || where.right.type === "ARITH_VALUE" || where.right.type === "CASE_VALUE" || where.right.type === "SUBQUERY_IN_LIST" || where.right.type === "SCALAR_SUBQUERY" || isLike(where);
|
|
2562
2590
|
case "NULL_CHECK":
|
|
2563
2591
|
return isFunc(where.field);
|
|
2564
2592
|
case "LOGICAL":
|
|
2565
|
-
return
|
|
2593
|
+
return whereRequiresJsEval(where.left) || whereRequiresJsEval(where.right);
|
|
2566
2594
|
case "NOT":
|
|
2567
2595
|
case "GROUP":
|
|
2568
|
-
return
|
|
2596
|
+
return whereRequiresJsEval(where.expr);
|
|
2569
2597
|
case "EXISTS":
|
|
2570
2598
|
return true;
|
|
2571
2599
|
}
|
|
@@ -2601,7 +2629,7 @@ function selectToKintoneParams(stmt) {
|
|
|
2601
2629
|
}
|
|
2602
2630
|
function selectToFetchAllParams(stmt, appId) {
|
|
2603
2631
|
const queryParts = [];
|
|
2604
|
-
if (stmt.where !== null && stmt.joins.length === 0 && !
|
|
2632
|
+
if (stmt.where !== null && stmt.joins.length === 0 && !whereRequiresJsEval(stmt.where)) {
|
|
2605
2633
|
queryParts.push(whereToKintone(stmt.where));
|
|
2606
2634
|
}
|
|
2607
2635
|
return {
|
|
@@ -3339,6 +3367,8 @@ function resolveValue(value, row) {
|
|
|
3339
3367
|
case "SCALAR_SUBQUERY":
|
|
3340
3368
|
return value.resolved;
|
|
3341
3369
|
case "ARITH_VALUE":
|
|
3370
|
+
if (value.expr.type === "FIELD_REF") return resolveFieldRef(row, value.expr.field);
|
|
3371
|
+
if (value.expr.type === "STRING_FUNC") return evalStringFunc(value.expr, row);
|
|
3342
3372
|
return String(evalArithExpr(value.expr, row));
|
|
3343
3373
|
case "CASE_VALUE":
|
|
3344
3374
|
return evalCaseWhen(value.expr, row);
|
|
@@ -3382,7 +3412,7 @@ function resolveKintoneFunc(name) {
|
|
|
3382
3412
|
var likeRegexCache = /* @__PURE__ */ new Map();
|
|
3383
3413
|
var LIKE_REGEX_CACHE_MAX = 200;
|
|
3384
3414
|
function matchLike(value, pattern) {
|
|
3385
|
-
if (!
|
|
3415
|
+
if (!likePatternHasWildcard(pattern)) {
|
|
3386
3416
|
return value.includes(pattern);
|
|
3387
3417
|
}
|
|
3388
3418
|
let regex = likeRegexCache.get(pattern);
|
|
@@ -3407,6 +3437,12 @@ function matchLike(value, pattern) {
|
|
|
3407
3437
|
}
|
|
3408
3438
|
|
|
3409
3439
|
// src/converter/dmlToKintone.ts
|
|
3440
|
+
function assertDmlWhereIsSafe(where) {
|
|
3441
|
+
if (!whereHasLike(where)) return;
|
|
3442
|
+
throw new DmlConvertError(
|
|
3443
|
+
"UPDATE / DELETE \u306E WHERE \u306B LIKE / NOT LIKE \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002LIKE \u306F kSQL \u306E\u610F\u5473\u8AD6\u306B\u5F93\u3063\u3066 JS \u3067\u8A55\u4FA1\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u304C\u3001\u89AA\u30EC\u30B3\u30FC\u30C9 DML \u306B\u306F JS \u8A55\u4FA1\u7D4C\u8DEF\u304C\u306A\u3044\u305F\u3081\u3001\u5B89\u5168\u4E0A\u62D2\u5426\u3057\u307E\u3057\u305F\u3002SELECT \u3067\u5BFE\u8C61\u30EC\u30B3\u30FC\u30C9\u756A\u53F7\u3092\u78BA\u8A8D\u3057\u3001IN \u307E\u305F\u306F\u5B8C\u5168\u4E00\u81F4\u3067\u5BFE\u8C61\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
3444
|
+
);
|
|
3445
|
+
}
|
|
3410
3446
|
var USER_TYPES = /* @__PURE__ */ new Set(["USER_SELECT", "ORGANIZATION_SELECT", "GROUP_SELECT"]);
|
|
3411
3447
|
var ARRAY_TYPES = /* @__PURE__ */ new Set(["CHECK_BOX", "MULTI_SELECT"]);
|
|
3412
3448
|
function insertToPostBatches(stmt, fieldTypes = /* @__PURE__ */ new Map()) {
|
|
@@ -3431,6 +3467,7 @@ function buildInsertRecord(fields, row, fieldTypes) {
|
|
|
3431
3467
|
return record;
|
|
3432
3468
|
}
|
|
3433
3469
|
function updateToGetQuery(stmt) {
|
|
3470
|
+
assertDmlWhereIsSafe(stmt.where);
|
|
3434
3471
|
return {
|
|
3435
3472
|
app: stmt.appId,
|
|
3436
3473
|
query: whereToKintone(stmt.where),
|
|
@@ -3459,6 +3496,7 @@ function hasArithAssignment(stmt) {
|
|
|
3459
3496
|
);
|
|
3460
3497
|
}
|
|
3461
3498
|
function updateToGetQueryForArith(stmt) {
|
|
3499
|
+
assertDmlWhereIsSafe(stmt.where);
|
|
3462
3500
|
const refFields = /* @__PURE__ */ new Set();
|
|
3463
3501
|
for (const { value } of stmt.assignments) {
|
|
3464
3502
|
if (value.type === "ARITH") {
|
|
@@ -3604,6 +3642,7 @@ function resolveArithOperand(operand, raw) {
|
|
|
3604
3642
|
return n;
|
|
3605
3643
|
}
|
|
3606
3644
|
function deleteToGetQuery(stmt) {
|
|
3645
|
+
assertDmlWhereIsSafe(stmt.where);
|
|
3607
3646
|
return {
|
|
3608
3647
|
app: stmt.appId,
|
|
3609
3648
|
query: whereToKintone(stmt.where),
|
|
@@ -3888,6 +3927,7 @@ async function resolveDmlTargetIds(getRecords, app, query, options) {
|
|
|
3888
3927
|
function extractTableCondition(where, tableAlias) {
|
|
3889
3928
|
switch (where.type) {
|
|
3890
3929
|
case "BINARY":
|
|
3930
|
+
if (isLike(where)) return null;
|
|
3891
3931
|
if (!isSingleTableField(where.left, tableAlias)) return null;
|
|
3892
3932
|
if (!isPushDownableRight(where.right)) return null;
|
|
3893
3933
|
return where;
|
|
@@ -3927,7 +3967,7 @@ function isPushDownableRight(value) {
|
|
|
3927
3967
|
function referencesOnlyTable(expr, tableAlias) {
|
|
3928
3968
|
switch (expr.type) {
|
|
3929
3969
|
case "BINARY":
|
|
3930
|
-
return isSingleTableField(expr.left, tableAlias) && isPushDownableRight(expr.right);
|
|
3970
|
+
return !isLike(expr) && isSingleTableField(expr.left, tableAlias) && isPushDownableRight(expr.right);
|
|
3931
3971
|
case "NULL_CHECK":
|
|
3932
3972
|
return isSingleTableField(expr.field, tableAlias);
|
|
3933
3973
|
case "LOGICAL":
|
|
@@ -6486,8 +6526,10 @@ function collectFullScanReasons(stmt) {
|
|
|
6486
6526
|
r.push("\u96C6\u8A08\u95A2\u6570\uFF08COUNT / SUM \u7B49\uFF09\u3042\u308A");
|
|
6487
6527
|
if (stmt.columns.some((c) => c.type === "SCALAR_SUBQUERY_COL"))
|
|
6488
6528
|
r.push("SELECT \u5217\u306B\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA");
|
|
6489
|
-
if (
|
|
6529
|
+
if (whereRequiresJsEval(stmt.where))
|
|
6490
6530
|
r.push("WHERE \u53E5\u306B JS \u8A55\u4FA1\u304C\u5FC5\u8981\u306A\u5F0F");
|
|
6531
|
+
if (whereHasLike(stmt.where))
|
|
6532
|
+
r.push("LIKE \u306F\u5E38\u306B JS \u8A55\u4FA1\u306E\u305F\u3081\u5168\u4EF6\u53D6\u5F97");
|
|
6491
6533
|
if (stmt.orderBy.some((o) => o.key.type !== "FIELD_NAME"))
|
|
6492
6534
|
r.push("ORDER BY \u306B\u5F0F");
|
|
6493
6535
|
return r;
|
|
@@ -6540,7 +6582,7 @@ function buildInsertPlan(stmt, label) {
|
|
|
6540
6582
|
const lines = [];
|
|
6541
6583
|
if (label) lines.push(label);
|
|
6542
6584
|
lines.push(` [INSERT]`);
|
|
6543
|
-
lines.push(`
|
|
6585
|
+
lines.push(` target: APP${stmt.appId} (${stmt.appId})`);
|
|
6544
6586
|
lines.push(` records: ${totalRows} \u4EF6\uFF08\u30D0\u30C3\u30C1 ${batchCount} \u56DE \xD7 \u6700\u5927 100 \u4EF6\uFF09`);
|
|
6545
6587
|
lines.push(` api: POST /k/v1/records.json \xD7 ${batchCount}`);
|
|
6546
6588
|
lines.push(` fields: ${stmt.fields.join(", ")}`);
|
|
@@ -6550,7 +6592,7 @@ function buildInsertSelectPlan(stmt, label) {
|
|
|
6550
6592
|
const lines = [];
|
|
6551
6593
|
if (label) lines.push(label);
|
|
6552
6594
|
lines.push(` [INSERT SELECT]`);
|
|
6553
|
-
lines.push(`
|
|
6595
|
+
lines.push(` target: APP${stmt.appId} (${stmt.appId})`);
|
|
6554
6596
|
lines.push(` fields: ${stmt.fields.join(", ")}`);
|
|
6555
6597
|
lines.push(` api: POST /k/v1/records.json\uFF08\u4EF6\u6570\u306F SELECT \u7D50\u679C\u306B\u4F9D\u5B58\u3001100 \u4EF6\u3054\u3068\u306B\u30D0\u30C3\u30C1\uFF09`);
|
|
6556
6598
|
lines.push("");
|
|
@@ -6563,7 +6605,7 @@ function buildUpdatePlan(stmt, label) {
|
|
|
6563
6605
|
const lines = [];
|
|
6564
6606
|
if (label) lines.push(label);
|
|
6565
6607
|
lines.push(` [UPDATE]`);
|
|
6566
|
-
lines.push(`
|
|
6608
|
+
lines.push(` target: APP${stmt.appId} (${stmt.appId})`);
|
|
6567
6609
|
lines.push(` kintone query: ${safeWhereToKintone(stmt.where)}`);
|
|
6568
6610
|
lines.push(` api: GET /k/v1/records.json \u2192 PUT /k/v1/records.json`);
|
|
6569
6611
|
const setTypes = [];
|
|
@@ -6593,7 +6635,7 @@ function buildDeletePlan(stmt, label) {
|
|
|
6593
6635
|
const lines = [];
|
|
6594
6636
|
if (label) lines.push(label);
|
|
6595
6637
|
lines.push(` [DELETE]`);
|
|
6596
|
-
lines.push(`
|
|
6638
|
+
lines.push(` target: APP${stmt.appId} (${stmt.appId})`);
|
|
6597
6639
|
lines.push(` kintone query: ${safeWhereToKintone(stmt.where)}`);
|
|
6598
6640
|
lines.push(` api: GET /k/v1/records.json \u2192 DELETE /k/v1/records.json`);
|
|
6599
6641
|
return lines;
|
|
@@ -6604,7 +6646,7 @@ function buildUpsertPlan(stmt, label) {
|
|
|
6604
6646
|
return [
|
|
6605
6647
|
...label ? [label] : [],
|
|
6606
6648
|
` [UPSERT]`,
|
|
6607
|
-
`
|
|
6649
|
+
` target: APP${stmt.appId} (${stmt.appId})`,
|
|
6608
6650
|
` records: ${totalRows} \u4EF6\uFF08\u30D0\u30C3\u30C1 ${batchCount} \u56DE \xD7 \u6700\u5927 100 \u4EF6\uFF09`,
|
|
6609
6651
|
` key fields: ${stmt.keyFields.join(", ")}`,
|
|
6610
6652
|
` fields: ${stmt.fields.join(", ")}`,
|
|
@@ -6615,7 +6657,7 @@ function buildUpsertSelectPlan(stmt, label) {
|
|
|
6615
6657
|
const lines = [
|
|
6616
6658
|
...label ? [label] : [],
|
|
6617
6659
|
` [UPSERT SELECT]`,
|
|
6618
|
-
`
|
|
6660
|
+
` target: APP${stmt.appId} (${stmt.appId})`,
|
|
6619
6661
|
` key fields: ${stmt.keyFields.join(", ")}`,
|
|
6620
6662
|
` fields: ${stmt.fields.join(", ")}`,
|
|
6621
6663
|
` api: GET /k/v1/records.json\uFF08\u91CD\u8907\u5224\u5B9A\uFF09\u2192 POST \u307E\u305F\u306F PUT /k/v1/records.json\uFF08100 \u4EF6\u3054\u3068\u306B\u30D0\u30C3\u30C1\uFF09`,
|
|
@@ -6631,7 +6673,7 @@ function buildReorderPlan(stmt, label) {
|
|
|
6631
6673
|
const lines = [
|
|
6632
6674
|
...label ? [label] : [],
|
|
6633
6675
|
` [REORDER]`,
|
|
6634
|
-
`
|
|
6676
|
+
` target: APP${stmt.appId} (${stmt.appId})`,
|
|
6635
6677
|
` table: ${target}`,
|
|
6636
6678
|
` scope: ${scope}`,
|
|
6637
6679
|
` by: ${byStr}`,
|
|
@@ -7710,6 +7752,14 @@ function tryParseStatements(sql) {
|
|
|
7710
7752
|
// src/node/sqlDiagnostics.ts
|
|
7711
7753
|
function restoreSqlDiagnosticValue(value, bindings) {
|
|
7712
7754
|
if (typeof value === "string") {
|
|
7755
|
+
const dmlTarget = value.match(/^(\s*target:\s*)APP(\d+) \((\d+)\)\s*$/);
|
|
7756
|
+
if (dmlTarget && dmlTarget[2] === dmlTarget[3]) {
|
|
7757
|
+
const binding = bindings.get(Number(dmlTarget[2]));
|
|
7758
|
+
if (binding) {
|
|
7759
|
+
const target = binding.source === "logical" ? `LAPP_${binding.logicalName} -> APP${binding.appId}@${binding.profile}` : `APP${binding.appId}@${binding.profile}`;
|
|
7760
|
+
return `${dmlTarget[1]}${target}`;
|
|
7761
|
+
}
|
|
7762
|
+
}
|
|
7713
7763
|
let restored = value;
|
|
7714
7764
|
for (const binding of bindings.values()) {
|
|
7715
7765
|
const internal = `APP${binding.mappedAppId}`;
|
|
@@ -9453,13 +9503,16 @@ query=${label}`);
|
|
|
9453
9503
|
});
|
|
9454
9504
|
return writeBatchOutput(batchResult, { format, noHeader, pretty, displayOptions, outputPath, quiet });
|
|
9455
9505
|
}
|
|
9456
|
-
|
|
9506
|
+
let result = args.dryRun ? await execute(`EXPLAIN ${sql}`, client, { maxRecords, onLimitReached: onLimit, cacheContext }) : await execute(sql, client, {
|
|
9457
9507
|
maxRecords,
|
|
9458
9508
|
fetchParallel,
|
|
9459
9509
|
onLimitReached: onLimit,
|
|
9460
9510
|
confirm: isDmlStatement ? confirm : void 0,
|
|
9461
9511
|
cacheContext
|
|
9462
9512
|
});
|
|
9513
|
+
if (args.dryRun && sqlDiagnosticContext) {
|
|
9514
|
+
result = restoreSqlDiagnosticValue(result, sqlDiagnosticContext.appBindingByMappedApp);
|
|
9515
|
+
}
|
|
9463
9516
|
if (result.type === "ASSERT") {
|
|
9464
9517
|
const output2 = buildAssertOutput(result, format, pretty);
|
|
9465
9518
|
if (outputPath) (0, import_fs2.writeFileSync)(outputPath, `${output2}
|
package/dist-mcp/ksql-mcp.js
CHANGED
|
@@ -33308,6 +33308,29 @@ function negateOp(op) {
|
|
|
33308
33308
|
}
|
|
33309
33309
|
}
|
|
33310
33310
|
|
|
33311
|
+
// src/core/like.ts
|
|
33312
|
+
function likePatternHasWildcard(pattern) {
|
|
33313
|
+
return pattern.includes("%") || pattern.includes("_");
|
|
33314
|
+
}
|
|
33315
|
+
function isLike(where) {
|
|
33316
|
+
return where.type === "BINARY" && (where.op === "LIKE" || where.op === "NOT_LIKE");
|
|
33317
|
+
}
|
|
33318
|
+
function whereHasLike(where) {
|
|
33319
|
+
if (where === null) return false;
|
|
33320
|
+
if (isLike(where)) return true;
|
|
33321
|
+
switch (where.type) {
|
|
33322
|
+
case "LOGICAL":
|
|
33323
|
+
return whereHasLike(where.left) || whereHasLike(where.right);
|
|
33324
|
+
case "NOT":
|
|
33325
|
+
case "GROUP":
|
|
33326
|
+
return whereHasLike(where.expr);
|
|
33327
|
+
case "BINARY":
|
|
33328
|
+
case "NULL_CHECK":
|
|
33329
|
+
case "EXISTS":
|
|
33330
|
+
return false;
|
|
33331
|
+
}
|
|
33332
|
+
}
|
|
33333
|
+
|
|
33311
33334
|
// src/converter/whereToKintone.ts
|
|
33312
33335
|
function whereToKintone(expr) {
|
|
33313
33336
|
switch (expr.type) {
|
|
@@ -33326,6 +33349,11 @@ function whereToKintone(expr) {
|
|
|
33326
33349
|
}
|
|
33327
33350
|
}
|
|
33328
33351
|
function convertBinary(expr) {
|
|
33352
|
+
if (isLike(expr)) {
|
|
33353
|
+
throw new KintoneQueryError(
|
|
33354
|
+
"LIKE / NOT LIKE \u306F kintone \u30AF\u30A8\u30EA\u306B\u5909\u63DB\u3067\u304D\u307E\u305B\u3093\uFF08\u5E38\u306B JS \u8A55\u4FA1\u304C\u5FC5\u8981\u3067\u3059\uFF09"
|
|
33355
|
+
);
|
|
33356
|
+
}
|
|
33329
33357
|
const left = convertField(expr.left);
|
|
33330
33358
|
const op = convertOp(expr.op);
|
|
33331
33359
|
const right = convertValue(expr.right, expr.op);
|
|
@@ -33451,22 +33479,22 @@ function resolveSelectMode(stmt) {
|
|
|
33451
33479
|
if (stmt.columns.some(
|
|
33452
33480
|
(c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "SCALAR_SUBQUERY_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr(c.expr)
|
|
33453
33481
|
)) return "FULL_SCAN";
|
|
33454
|
-
if (
|
|
33482
|
+
if (whereRequiresJsEval(stmt.where)) return "FULL_SCAN";
|
|
33455
33483
|
if (stmt.orderBy.some((o) => o.key.type !== "FIELD_NAME")) return "FULL_SCAN";
|
|
33456
33484
|
return "SIMPLE";
|
|
33457
33485
|
}
|
|
33458
|
-
function
|
|
33486
|
+
function whereRequiresJsEval(where) {
|
|
33459
33487
|
if (where === null) return false;
|
|
33460
33488
|
switch (where.type) {
|
|
33461
33489
|
case "BINARY":
|
|
33462
|
-
return isFunc(where.left) || where.right.type === "ARITH_VALUE" || where.right.type === "CASE_VALUE" || where.right.type === "SUBQUERY_IN_LIST" || where.right.type === "SCALAR_SUBQUERY";
|
|
33490
|
+
return isFunc(where.left) || where.right.type === "ARITH_VALUE" || where.right.type === "CASE_VALUE" || where.right.type === "SUBQUERY_IN_LIST" || where.right.type === "SCALAR_SUBQUERY" || isLike(where);
|
|
33463
33491
|
case "NULL_CHECK":
|
|
33464
33492
|
return isFunc(where.field);
|
|
33465
33493
|
case "LOGICAL":
|
|
33466
|
-
return
|
|
33494
|
+
return whereRequiresJsEval(where.left) || whereRequiresJsEval(where.right);
|
|
33467
33495
|
case "NOT":
|
|
33468
33496
|
case "GROUP":
|
|
33469
|
-
return
|
|
33497
|
+
return whereRequiresJsEval(where.expr);
|
|
33470
33498
|
case "EXISTS":
|
|
33471
33499
|
return true;
|
|
33472
33500
|
}
|
|
@@ -33502,7 +33530,7 @@ function selectToKintoneParams(stmt) {
|
|
|
33502
33530
|
}
|
|
33503
33531
|
function selectToFetchAllParams(stmt, appId) {
|
|
33504
33532
|
const queryParts = [];
|
|
33505
|
-
if (stmt.where !== null && stmt.joins.length === 0 && !
|
|
33533
|
+
if (stmt.where !== null && stmt.joins.length === 0 && !whereRequiresJsEval(stmt.where)) {
|
|
33506
33534
|
queryParts.push(whereToKintone(stmt.where));
|
|
33507
33535
|
}
|
|
33508
33536
|
return {
|
|
@@ -34240,6 +34268,8 @@ function resolveValue(value, row) {
|
|
|
34240
34268
|
case "SCALAR_SUBQUERY":
|
|
34241
34269
|
return value.resolved;
|
|
34242
34270
|
case "ARITH_VALUE":
|
|
34271
|
+
if (value.expr.type === "FIELD_REF") return resolveFieldRef(row, value.expr.field);
|
|
34272
|
+
if (value.expr.type === "STRING_FUNC") return evalStringFunc(value.expr, row);
|
|
34243
34273
|
return String(evalArithExpr(value.expr, row));
|
|
34244
34274
|
case "CASE_VALUE":
|
|
34245
34275
|
return evalCaseWhen(value.expr, row);
|
|
@@ -34283,7 +34313,7 @@ function resolveKintoneFunc(name) {
|
|
|
34283
34313
|
var likeRegexCache = /* @__PURE__ */ new Map();
|
|
34284
34314
|
var LIKE_REGEX_CACHE_MAX = 200;
|
|
34285
34315
|
function matchLike(value, pattern) {
|
|
34286
|
-
if (!
|
|
34316
|
+
if (!likePatternHasWildcard(pattern)) {
|
|
34287
34317
|
return value.includes(pattern);
|
|
34288
34318
|
}
|
|
34289
34319
|
let regex = likeRegexCache.get(pattern);
|
|
@@ -34308,6 +34338,12 @@ function matchLike(value, pattern) {
|
|
|
34308
34338
|
}
|
|
34309
34339
|
|
|
34310
34340
|
// src/converter/dmlToKintone.ts
|
|
34341
|
+
function assertDmlWhereIsSafe(where) {
|
|
34342
|
+
if (!whereHasLike(where)) return;
|
|
34343
|
+
throw new DmlConvertError(
|
|
34344
|
+
"UPDATE / DELETE \u306E WHERE \u306B LIKE / NOT LIKE \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002LIKE \u306F kSQL \u306E\u610F\u5473\u8AD6\u306B\u5F93\u3063\u3066 JS \u3067\u8A55\u4FA1\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u304C\u3001\u89AA\u30EC\u30B3\u30FC\u30C9 DML \u306B\u306F JS \u8A55\u4FA1\u7D4C\u8DEF\u304C\u306A\u3044\u305F\u3081\u3001\u5B89\u5168\u4E0A\u62D2\u5426\u3057\u307E\u3057\u305F\u3002SELECT \u3067\u5BFE\u8C61\u30EC\u30B3\u30FC\u30C9\u756A\u53F7\u3092\u78BA\u8A8D\u3057\u3001IN \u307E\u305F\u306F\u5B8C\u5168\u4E00\u81F4\u3067\u5BFE\u8C61\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
34345
|
+
);
|
|
34346
|
+
}
|
|
34311
34347
|
var USER_TYPES = /* @__PURE__ */ new Set(["USER_SELECT", "ORGANIZATION_SELECT", "GROUP_SELECT"]);
|
|
34312
34348
|
var ARRAY_TYPES = /* @__PURE__ */ new Set(["CHECK_BOX", "MULTI_SELECT"]);
|
|
34313
34349
|
function insertToPostBatches(stmt, fieldTypes = /* @__PURE__ */ new Map()) {
|
|
@@ -34332,6 +34368,7 @@ function buildInsertRecord(fields, row, fieldTypes) {
|
|
|
34332
34368
|
return record2;
|
|
34333
34369
|
}
|
|
34334
34370
|
function updateToGetQuery(stmt) {
|
|
34371
|
+
assertDmlWhereIsSafe(stmt.where);
|
|
34335
34372
|
return {
|
|
34336
34373
|
app: stmt.appId,
|
|
34337
34374
|
query: whereToKintone(stmt.where),
|
|
@@ -34360,6 +34397,7 @@ function hasArithAssignment(stmt) {
|
|
|
34360
34397
|
);
|
|
34361
34398
|
}
|
|
34362
34399
|
function updateToGetQueryForArith(stmt) {
|
|
34400
|
+
assertDmlWhereIsSafe(stmt.where);
|
|
34363
34401
|
const refFields = /* @__PURE__ */ new Set();
|
|
34364
34402
|
for (const { value } of stmt.assignments) {
|
|
34365
34403
|
if (value.type === "ARITH") {
|
|
@@ -34505,6 +34543,7 @@ function resolveArithOperand(operand, raw) {
|
|
|
34505
34543
|
return n;
|
|
34506
34544
|
}
|
|
34507
34545
|
function deleteToGetQuery(stmt) {
|
|
34546
|
+
assertDmlWhereIsSafe(stmt.where);
|
|
34508
34547
|
return {
|
|
34509
34548
|
app: stmt.appId,
|
|
34510
34549
|
query: whereToKintone(stmt.where),
|
|
@@ -34789,6 +34828,7 @@ async function resolveDmlTargetIds(getRecords, app, query, options) {
|
|
|
34789
34828
|
function extractTableCondition(where, tableAlias) {
|
|
34790
34829
|
switch (where.type) {
|
|
34791
34830
|
case "BINARY":
|
|
34831
|
+
if (isLike(where)) return null;
|
|
34792
34832
|
if (!isSingleTableField(where.left, tableAlias)) return null;
|
|
34793
34833
|
if (!isPushDownableRight(where.right)) return null;
|
|
34794
34834
|
return where;
|
|
@@ -34828,7 +34868,7 @@ function isPushDownableRight(value) {
|
|
|
34828
34868
|
function referencesOnlyTable(expr, tableAlias) {
|
|
34829
34869
|
switch (expr.type) {
|
|
34830
34870
|
case "BINARY":
|
|
34831
|
-
return isSingleTableField(expr.left, tableAlias) && isPushDownableRight(expr.right);
|
|
34871
|
+
return !isLike(expr) && isSingleTableField(expr.left, tableAlias) && isPushDownableRight(expr.right);
|
|
34832
34872
|
case "NULL_CHECK":
|
|
34833
34873
|
return isSingleTableField(expr.field, tableAlias);
|
|
34834
34874
|
case "LOGICAL":
|
|
@@ -37387,8 +37427,10 @@ function collectFullScanReasons(stmt) {
|
|
|
37387
37427
|
r.push("\u96C6\u8A08\u95A2\u6570\uFF08COUNT / SUM \u7B49\uFF09\u3042\u308A");
|
|
37388
37428
|
if (stmt.columns.some((c) => c.type === "SCALAR_SUBQUERY_COL"))
|
|
37389
37429
|
r.push("SELECT \u5217\u306B\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA");
|
|
37390
|
-
if (
|
|
37430
|
+
if (whereRequiresJsEval(stmt.where))
|
|
37391
37431
|
r.push("WHERE \u53E5\u306B JS \u8A55\u4FA1\u304C\u5FC5\u8981\u306A\u5F0F");
|
|
37432
|
+
if (whereHasLike(stmt.where))
|
|
37433
|
+
r.push("LIKE \u306F\u5E38\u306B JS \u8A55\u4FA1\u306E\u305F\u3081\u5168\u4EF6\u53D6\u5F97");
|
|
37392
37434
|
if (stmt.orderBy.some((o) => o.key.type !== "FIELD_NAME"))
|
|
37393
37435
|
r.push("ORDER BY \u306B\u5F0F");
|
|
37394
37436
|
return r;
|
|
@@ -37441,7 +37483,7 @@ function buildInsertPlan(stmt, label) {
|
|
|
37441
37483
|
const lines = [];
|
|
37442
37484
|
if (label) lines.push(label);
|
|
37443
37485
|
lines.push(` [INSERT]`);
|
|
37444
|
-
lines.push(`
|
|
37486
|
+
lines.push(` target: APP${stmt.appId} (${stmt.appId})`);
|
|
37445
37487
|
lines.push(` records: ${totalRows} \u4EF6\uFF08\u30D0\u30C3\u30C1 ${batchCount} \u56DE \xD7 \u6700\u5927 100 \u4EF6\uFF09`);
|
|
37446
37488
|
lines.push(` api: POST /k/v1/records.json \xD7 ${batchCount}`);
|
|
37447
37489
|
lines.push(` fields: ${stmt.fields.join(", ")}`);
|
|
@@ -37451,7 +37493,7 @@ function buildInsertSelectPlan(stmt, label) {
|
|
|
37451
37493
|
const lines = [];
|
|
37452
37494
|
if (label) lines.push(label);
|
|
37453
37495
|
lines.push(` [INSERT SELECT]`);
|
|
37454
|
-
lines.push(`
|
|
37496
|
+
lines.push(` target: APP${stmt.appId} (${stmt.appId})`);
|
|
37455
37497
|
lines.push(` fields: ${stmt.fields.join(", ")}`);
|
|
37456
37498
|
lines.push(` api: POST /k/v1/records.json\uFF08\u4EF6\u6570\u306F SELECT \u7D50\u679C\u306B\u4F9D\u5B58\u3001100 \u4EF6\u3054\u3068\u306B\u30D0\u30C3\u30C1\uFF09`);
|
|
37457
37499
|
lines.push("");
|
|
@@ -37464,7 +37506,7 @@ function buildUpdatePlan(stmt, label) {
|
|
|
37464
37506
|
const lines = [];
|
|
37465
37507
|
if (label) lines.push(label);
|
|
37466
37508
|
lines.push(` [UPDATE]`);
|
|
37467
|
-
lines.push(`
|
|
37509
|
+
lines.push(` target: APP${stmt.appId} (${stmt.appId})`);
|
|
37468
37510
|
lines.push(` kintone query: ${safeWhereToKintone(stmt.where)}`);
|
|
37469
37511
|
lines.push(` api: GET /k/v1/records.json \u2192 PUT /k/v1/records.json`);
|
|
37470
37512
|
const setTypes = [];
|
|
@@ -37494,7 +37536,7 @@ function buildDeletePlan(stmt, label) {
|
|
|
37494
37536
|
const lines = [];
|
|
37495
37537
|
if (label) lines.push(label);
|
|
37496
37538
|
lines.push(` [DELETE]`);
|
|
37497
|
-
lines.push(`
|
|
37539
|
+
lines.push(` target: APP${stmt.appId} (${stmt.appId})`);
|
|
37498
37540
|
lines.push(` kintone query: ${safeWhereToKintone(stmt.where)}`);
|
|
37499
37541
|
lines.push(` api: GET /k/v1/records.json \u2192 DELETE /k/v1/records.json`);
|
|
37500
37542
|
return lines;
|
|
@@ -37505,7 +37547,7 @@ function buildUpsertPlan(stmt, label) {
|
|
|
37505
37547
|
return [
|
|
37506
37548
|
...label ? [label] : [],
|
|
37507
37549
|
` [UPSERT]`,
|
|
37508
|
-
`
|
|
37550
|
+
` target: APP${stmt.appId} (${stmt.appId})`,
|
|
37509
37551
|
` records: ${totalRows} \u4EF6\uFF08\u30D0\u30C3\u30C1 ${batchCount} \u56DE \xD7 \u6700\u5927 100 \u4EF6\uFF09`,
|
|
37510
37552
|
` key fields: ${stmt.keyFields.join(", ")}`,
|
|
37511
37553
|
` fields: ${stmt.fields.join(", ")}`,
|
|
@@ -37516,7 +37558,7 @@ function buildUpsertSelectPlan(stmt, label) {
|
|
|
37516
37558
|
const lines = [
|
|
37517
37559
|
...label ? [label] : [],
|
|
37518
37560
|
` [UPSERT SELECT]`,
|
|
37519
|
-
`
|
|
37561
|
+
` target: APP${stmt.appId} (${stmt.appId})`,
|
|
37520
37562
|
` key fields: ${stmt.keyFields.join(", ")}`,
|
|
37521
37563
|
` fields: ${stmt.fields.join(", ")}`,
|
|
37522
37564
|
` api: GET /k/v1/records.json\uFF08\u91CD\u8907\u5224\u5B9A\uFF09\u2192 POST \u307E\u305F\u306F PUT /k/v1/records.json\uFF08100 \u4EF6\u3054\u3068\u306B\u30D0\u30C3\u30C1\uFF09`,
|
|
@@ -37532,7 +37574,7 @@ function buildReorderPlan(stmt, label) {
|
|
|
37532
37574
|
const lines = [
|
|
37533
37575
|
...label ? [label] : [],
|
|
37534
37576
|
` [REORDER]`,
|
|
37535
|
-
`
|
|
37577
|
+
` target: APP${stmt.appId} (${stmt.appId})`,
|
|
37536
37578
|
` table: ${target}`,
|
|
37537
37579
|
` scope: ${scope}`,
|
|
37538
37580
|
` by: ${byStr}`,
|
|
@@ -37669,6 +37711,14 @@ function buildBatchEnvelope(batch, options = {}) {
|
|
|
37669
37711
|
// src/node/sqlDiagnostics.ts
|
|
37670
37712
|
function restoreSqlDiagnosticValue(value, bindings) {
|
|
37671
37713
|
if (typeof value === "string") {
|
|
37714
|
+
const dmlTarget = value.match(/^(\s*target:\s*)APP(\d+) \((\d+)\)\s*$/);
|
|
37715
|
+
if (dmlTarget && dmlTarget[2] === dmlTarget[3]) {
|
|
37716
|
+
const binding = bindings.get(Number(dmlTarget[2]));
|
|
37717
|
+
if (binding) {
|
|
37718
|
+
const target = binding.source === "logical" ? `LAPP_${binding.logicalName} -> APP${binding.appId}@${binding.profile}` : `APP${binding.appId}@${binding.profile}`;
|
|
37719
|
+
return `${dmlTarget[1]}${target}`;
|
|
37720
|
+
}
|
|
37721
|
+
}
|
|
37672
37722
|
let restored = value;
|
|
37673
37723
|
for (const binding of bindings.values()) {
|
|
37674
37724
|
const internal = `APP${binding.mappedAppId}`;
|
|
@@ -39653,7 +39703,7 @@ Options:
|
|
|
39653
39703
|
-h, --help Show help
|
|
39654
39704
|
`);
|
|
39655
39705
|
}
|
|
39656
|
-
var SERVER_VERSION = true ? "
|
|
39706
|
+
var SERVER_VERSION = true ? "2.0.0" : "0.0.0-dev";
|
|
39657
39707
|
function createServer(args) {
|
|
39658
39708
|
const server = new McpServer({
|
|
39659
39709
|
name: "ksql-mcp",
|
package/dist-mcpb/ksql-mcp.mcpb
CHANGED
|
Binary file
|