@rex0220/kintone-sql-tools 1.13.2 → 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 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 (hasWhereFunc(stmt.where)) return "FULL_SCAN";
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 hasWhereFunc(where) {
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 hasWhereFunc(where.left) || hasWhereFunc(where.right);
2593
+ return whereRequiresJsEval(where.left) || whereRequiresJsEval(where.right);
2566
2594
  case "NOT":
2567
2595
  case "GROUP":
2568
- return hasWhereFunc(where.expr);
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 && !hasWhereFunc(stmt.where)) {
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 (!pattern.includes("%") && !pattern.includes("_")) {
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 (hasWhereFunc(stmt.where))
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;
@@ -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 (hasWhereFunc(stmt.where)) return "FULL_SCAN";
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 hasWhereFunc(where) {
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 hasWhereFunc(where.left) || hasWhereFunc(where.right);
33494
+ return whereRequiresJsEval(where.left) || whereRequiresJsEval(where.right);
33467
33495
  case "NOT":
33468
33496
  case "GROUP":
33469
- return hasWhereFunc(where.expr);
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 && !hasWhereFunc(stmt.where)) {
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 (!pattern.includes("%") && !pattern.includes("_")) {
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 (hasWhereFunc(stmt.where))
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;
@@ -39661,7 +39703,7 @@ Options:
39661
39703
  -h, --help Show help
39662
39704
  `);
39663
39705
  }
39664
- var SERVER_VERSION = true ? "1.13.2" : "0.0.0-dev";
39706
+ var SERVER_VERSION = true ? "2.0.0" : "0.0.0-dev";
39665
39707
  function createServer(args) {
39666
39708
  const server = new McpServer({
39667
39709
  name: "ksql-mcp",
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rex0220/kintone-sql-tools",
3
- "version": "1.13.2",
3
+ "version": "2.0.0",
4
4
  "description": "kintone SQL plugin, CLI, and MCP tools (ksql)",
5
5
  "publishConfig": {
6
6
  "access": "public"