@rex0220/kintone-sql-tools 2.5.0 → 2.6.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
@@ -3581,10 +3581,12 @@ function typedInContains(leftStr, values, fieldType) {
3581
3581
  if (!Array.isArray(parsed) || !parsed.every((item) => typeof item === "string")) {
3582
3582
  return fallback();
3583
3583
  }
3584
+ if (parsed.length === 0 && values.has("")) return true;
3584
3585
  return parsed.some((item) => values.has(item));
3585
3586
  }
3586
3587
  if (OBJECT_ARRAY_FIELD_TYPES.has(fieldType)) {
3587
3588
  if (!Array.isArray(parsed) || !parsed.every(hasStringCode)) return fallback();
3589
+ if (parsed.length === 0 && values.has("")) return true;
3588
3590
  return parsed.some((item) => values.has(item.code));
3589
3591
  }
3590
3592
  if (!hasStringCode(parsed)) return fallback();
@@ -4197,8 +4199,11 @@ async function resolveDmlTargetIds(getRecords, app, query, options) {
4197
4199
  function extractSafePushdownLeaves(where, options = {}) {
4198
4200
  return extractAndLeaves(where, (expr) => isSafeComparison(expr, options));
4199
4201
  }
4200
- function extractNumericPushdownCandidates(where, options = {}) {
4201
- return extractAndLeaves(where, (expr) => isNumericCandidate(expr, options));
4202
+ function extractTypedPushdownCandidates(where, options = {}) {
4203
+ return extractAndLeaves(
4204
+ where,
4205
+ (expr) => isNumericCandidate(expr, options) || isSelectionInCandidate(expr, options)
4206
+ );
4202
4207
  }
4203
4208
  function extractAndLeaves(where, accept) {
4204
4209
  switch (where.type) {
@@ -4222,8 +4227,27 @@ function extractAndLeaves(where, accept) {
4222
4227
  }
4223
4228
  function isSafeComparison(expr, options) {
4224
4229
  if (isSafeIdComparison(expr, options)) return true;
4225
- if (!isNumericCandidate(expr, options)) return false;
4226
- return options.fieldTypes?.get(expr.left.field) === "NUMBER";
4230
+ if (isNumericCandidate(expr, options)) {
4231
+ return options.fieldTypes?.get(expr.left.field) === "NUMBER";
4232
+ }
4233
+ return isSelectionInComparison(expr, options);
4234
+ }
4235
+ var SELECTION_IN_FIELD_TYPES = /* @__PURE__ */ new Set([
4236
+ "DROP_DOWN",
4237
+ "RADIO_BUTTON",
4238
+ "CHECK_BOX",
4239
+ "MULTI_SELECT"
4240
+ ]);
4241
+ function isSelectionInComparison(expr, options) {
4242
+ if (!isSelectionInCandidate(expr, options)) return false;
4243
+ if (expr.left.type !== "FIELD" || expr.right.type !== "IN_LIST") return false;
4244
+ const fieldType = options.fieldTypes?.get(expr.left.field);
4245
+ if (fieldType === void 0 || !SELECTION_IN_FIELD_TYPES.has(fieldType)) return false;
4246
+ const validOptions = options.fieldOptions?.get(expr.left.field);
4247
+ if (validOptions === void 0) return false;
4248
+ return expr.right.values.every(
4249
+ (value) => value.type === "STRING" && value.value !== "" && validOptions.has(value.value)
4250
+ );
4227
4251
  }
4228
4252
  function isSafeIdComparison(expr, options) {
4229
4253
  if (!isTargetIdField(expr.left, options)) return false;
@@ -4243,6 +4267,13 @@ function isNumericCandidate(expr, options) {
4243
4267
  if (expr.op === "=") return true;
4244
4268
  return (expr.op === "<" || expr.op === ">") && Number.isSafeInteger(expr.right.value);
4245
4269
  }
4270
+ function isSelectionInCandidate(expr, options) {
4271
+ if (expr.left.type !== "FIELD" || expr.left.field === "$id") return false;
4272
+ if (!isTargetField(expr.left, options)) return false;
4273
+ if (expr.op !== "IN" && expr.op !== "NOT_IN") return false;
4274
+ if (expr.right.type !== "IN_LIST" || expr.right.values.length === 0) return false;
4275
+ return expr.right.values.every((value) => value.type === "STRING" && value.value !== "");
4276
+ }
4246
4277
  function isTargetField(field, options) {
4247
4278
  const targetAlias = options.tableAlias ?? null;
4248
4279
  if (field.tableAlias === targetAlias) return true;
@@ -4254,7 +4285,7 @@ function flatten(record, alias) {
4254
4285
  const row = {};
4255
4286
  for (const [field, fv] of Object.entries(record)) {
4256
4287
  const val = fv.value;
4257
- const strVal = typeof val === "string" ? val : JSON.stringify(val ?? "");
4288
+ const strVal = val == null ? "" : typeof val === "string" ? val : JSON.stringify(val);
4258
4289
  if (alias) {
4259
4290
  row[`${alias}.${field}`] = strVal;
4260
4291
  row[field] = strVal;
@@ -5464,43 +5495,57 @@ async function validateSelectFieldCodes(stmt, mode, client, cacheContext) {
5464
5495
  }
5465
5496
  }
5466
5497
  }
5467
- function extractMainSafePushdown(stmt, fieldTypes) {
5498
+ function extractMainSafePushdown(stmt, fieldTypes, fieldOptions) {
5468
5499
  if (stmt.where === null || stmt.from.subtableCode || stmt.from.cteName !== null) return null;
5469
5500
  if (stmt.joins.length === 0) {
5470
5501
  return extractSafePushdownLeaves(stmt.where, {
5471
5502
  tableAlias: stmt.from.alias ?? void 0,
5472
5503
  allowUnqualifiedFields: true,
5473
- fieldTypes
5504
+ fieldTypes,
5505
+ fieldOptions
5474
5506
  });
5475
5507
  }
5476
5508
  if (!stmt.from.alias) return null;
5477
- return extractSafePushdownLeaves(stmt.where, { tableAlias: stmt.from.alias, fieldTypes });
5509
+ return extractSafePushdownLeaves(stmt.where, {
5510
+ tableAlias: stmt.from.alias,
5511
+ fieldTypes,
5512
+ fieldOptions
5513
+ });
5478
5514
  }
5479
- function extractMainNumericPushdownCandidate(stmt) {
5515
+ function extractMainTypedPushdownCandidate(stmt) {
5480
5516
  if (stmt.where === null || stmt.from.subtableCode || stmt.from.cteName !== null) return null;
5481
5517
  if (stmt.joins.length === 0) {
5482
- return extractNumericPushdownCandidates(stmt.where, {
5518
+ return extractTypedPushdownCandidates(stmt.where, {
5483
5519
  tableAlias: stmt.from.alias ?? void 0,
5484
5520
  allowUnqualifiedFields: true
5485
5521
  });
5486
5522
  }
5487
5523
  if (!stmt.from.alias) return null;
5488
- return extractNumericPushdownCandidates(stmt.where, { tableAlias: stmt.from.alias });
5524
+ return extractTypedPushdownCandidates(stmt.where, { tableAlias: stmt.from.alias });
5489
5525
  }
5490
- async function loadNumericPushdownFieldTypes(stmt, client, cacheContext) {
5526
+ async function loadTypedPushdownMeta(stmt, client, cacheContext) {
5491
5527
  const appIds = /* @__PURE__ */ new Set();
5492
- if (extractMainNumericPushdownCandidate(stmt) !== null) appIds.add(stmt.from.appId);
5528
+ if (extractMainTypedPushdownCandidate(stmt) !== null) appIds.add(stmt.from.appId);
5493
5529
  if (stmt.where !== null) {
5494
5530
  for (const join2 of stmt.joins) {
5495
5531
  if (!join2.table.alias || join2.table.subtableCode || join2.table.cteName !== null) continue;
5496
- const candidate = extractNumericPushdownCandidates(stmt.where, {
5532
+ const candidate = extractTypedPushdownCandidates(stmt.where, {
5497
5533
  tableAlias: join2.table.alias
5498
5534
  });
5499
5535
  if (candidate !== null) appIds.add(join2.table.appId);
5500
5536
  }
5501
5537
  }
5502
- const entries = await Promise.all([...appIds].map(async (appId) => [appId, await getFieldTypeMap(appId, client, cacheContext)]));
5503
- return new Map(entries);
5538
+ const entries = await Promise.all([...appIds].map(async (appId) => {
5539
+ const [fieldTypes, fieldOptions] = await Promise.all([
5540
+ getFieldTypeMap(appId, client, cacheContext),
5541
+ getFieldOptionSetMapByApp(appId, client, cacheContext)
5542
+ ]);
5543
+ return [appId, fieldTypes, fieldOptions];
5544
+ }));
5545
+ return {
5546
+ fieldTypesByApp: new Map(entries.map(([appId, fieldTypes]) => [appId, fieldTypes])),
5547
+ fieldOptionsByApp: new Map(entries.map(([appId, , fieldOptions]) => [appId, fieldOptions]))
5548
+ };
5504
5549
  }
5505
5550
  function collectTypedInFieldRefs(expr, out) {
5506
5551
  if (expr === null) return;
@@ -5612,14 +5657,15 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
5612
5657
  resolveSubqueries(stmt.where, client, options, cacheContext, cteCache),
5613
5658
  resolveSubqueries(stmt.having, client, options, cacheContext, cteCache)
5614
5659
  ]);
5615
- const [pushdownFieldTypes, typedInFieldTypes] = await Promise.all([
5616
- loadNumericPushdownFieldTypes(stmt, client, cacheContext),
5660
+ const [pushdownMeta, typedInFieldTypes] = await Promise.all([
5661
+ loadTypedPushdownMeta(stmt, client, cacheContext),
5617
5662
  loadTypedInFieldTypes(stmt, client, cacheContext)
5618
5663
  ]);
5619
5664
  const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
5620
5665
  const mainPushDown = extractMainSafePushdown(
5621
5666
  stmt,
5622
- pushdownFieldTypes.get(stmt.from.appId)
5667
+ pushdownMeta.fieldTypesByApp.get(stmt.from.appId),
5668
+ pushdownMeta.fieldOptionsByApp.get(stmt.from.appId)
5623
5669
  );
5624
5670
  const tableConditions = /* @__PURE__ */ new Map();
5625
5671
  if (stmt.where !== null) {
@@ -5627,7 +5673,8 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
5627
5673
  if (!join2.table.alias || join2.table.subtableCode || join2.table.cteName !== null) continue;
5628
5674
  const cond = extractSafePushdownLeaves(stmt.where, {
5629
5675
  tableAlias: join2.table.alias,
5630
- fieldTypes: pushdownFieldTypes.get(join2.table.appId)
5676
+ fieldTypes: pushdownMeta.fieldTypesByApp.get(join2.table.appId),
5677
+ fieldOptions: pushdownMeta.fieldOptionsByApp.get(join2.table.appId)
5631
5678
  });
5632
5679
  if (cond) tableConditions.set(join2.table.alias, cond);
5633
5680
  }
@@ -6168,6 +6215,15 @@ async function getOptionOrderMapByApp(appId, client, cacheContext) {
6168
6215
  setScopedCacheValue(optionOrderCache, cacheContext, appId, map);
6169
6216
  return map;
6170
6217
  }
6218
+ async function getFieldOptionSetMapByApp(appId, client, cacheContext) {
6219
+ const optionOrders = await getOptionOrderMapByApp(appId, client, cacheContext);
6220
+ return new Map(
6221
+ [...optionOrders.entries()].map(([fieldCode, order]) => [
6222
+ fieldCode,
6223
+ new Set(order.keys())
6224
+ ])
6225
+ );
6226
+ }
6171
6227
  async function getSortKindMapByApp(appId, client, cacheContext) {
6172
6228
  const cached = getScopedCacheValue(sortKindCache, cacheContext, appId);
6173
6229
  if (cached) return cached;
@@ -7127,12 +7183,12 @@ function buildSelectPlan(stmt, label) {
7127
7183
  const mainFields = selectToFetchAllFields(stmt, stmt.from);
7128
7184
  const mainAliasStr = stmt.from.alias ? ` AS ${stmt.from.alias}` : "";
7129
7185
  const mainPushDown = extractMainSafePushdown(stmt);
7130
- const mainCandidate = extractMainNumericPushdownCandidate(stmt);
7186
+ const mainCandidate = extractMainTypedPushdownCandidate(stmt);
7131
7187
  const mainQ = mainPushDown !== null ? whereToKintone(mainPushDown) : "(\u5168\u4EF6\u53D6\u5F97)";
7132
7188
  lines.push(` app: APP${stmt.from.appId}${mainAliasStr} (${stmt.from.appId})`);
7133
7189
  lines.push(` kintone query: ${mainQ}`);
7134
7190
  if (mainCandidate !== null) {
7135
- lines.push(` pushdown candidate: ${whereToKintone(mainCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u78BA\u8A8D\u5F85\u3061\uFF09`);
7191
+ lines.push(` pushdown candidate: ${whereToKintone(mainCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u30FB\u5B9F\u5728\u78BA\u8A8D\u5F85\u3061\uFF09`);
7136
7192
  }
7137
7193
  lines.push(` fields: ${mainFields.length === 0 ? "(\u5168\u30D5\u30A3\u30FC\u30EB\u30C9)" : mainFields.join(", ")}`);
7138
7194
  for (const join2 of stmt.joins) {
@@ -7140,12 +7196,12 @@ function buildSelectPlan(stmt, label) {
7140
7196
  const joinAliasStr = join2.table.alias ? ` AS ${join2.table.alias}` : "";
7141
7197
  const joinType = join2.type === "INNER" ? "JOIN" : `${join2.type} JOIN`;
7142
7198
  const joinPushDown = join2.table.alias && !join2.table.subtableCode && join2.table.cteName === null && stmt.where ? extractSafePushdownLeaves(stmt.where, { tableAlias: join2.table.alias }) : null;
7143
- const joinCandidate = join2.table.alias && !join2.table.subtableCode && join2.table.cteName === null && stmt.where ? extractNumericPushdownCandidates(stmt.where, { tableAlias: join2.table.alias }) : null;
7199
+ const joinCandidate = join2.table.alias && !join2.table.subtableCode && join2.table.cteName === null && stmt.where ? extractTypedPushdownCandidates(stmt.where, { tableAlias: join2.table.alias }) : null;
7144
7200
  const joinQ = joinPushDown !== null ? whereToKintone(joinPushDown) : "(\u5168\u4EF6\u53D6\u5F97)";
7145
7201
  lines.push(` ${joinType}: APP${join2.table.appId}${joinAliasStr} (${join2.table.appId})`);
7146
7202
  lines.push(` kintone query: ${joinQ}`);
7147
7203
  if (joinCandidate !== null) {
7148
- lines.push(` pushdown candidate: ${whereToKintone(joinCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u78BA\u8A8D\u5F85\u3061\uFF09`);
7204
+ lines.push(` pushdown candidate: ${whereToKintone(joinCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u30FB\u5B9F\u5728\u78BA\u8A8D\u5F85\u3061\uFF09`);
7149
7205
  }
7150
7206
  lines.push(` fields: ${joinFields.length === 0 ? "(\u5168\u30D5\u30A3\u30FC\u30EB\u30C9)" : joinFields.join(", ")}`);
7151
7207
  }
@@ -34482,10 +34482,12 @@ function typedInContains(leftStr, values, fieldType) {
34482
34482
  if (!Array.isArray(parsed) || !parsed.every((item) => typeof item === "string")) {
34483
34483
  return fallback();
34484
34484
  }
34485
+ if (parsed.length === 0 && values.has("")) return true;
34485
34486
  return parsed.some((item) => values.has(item));
34486
34487
  }
34487
34488
  if (OBJECT_ARRAY_FIELD_TYPES.has(fieldType)) {
34488
34489
  if (!Array.isArray(parsed) || !parsed.every(hasStringCode)) return fallback();
34490
+ if (parsed.length === 0 && values.has("")) return true;
34489
34491
  return parsed.some((item) => values.has(item.code));
34490
34492
  }
34491
34493
  if (!hasStringCode(parsed)) return fallback();
@@ -35098,8 +35100,11 @@ async function resolveDmlTargetIds(getRecords, app, query, options) {
35098
35100
  function extractSafePushdownLeaves(where, options = {}) {
35099
35101
  return extractAndLeaves(where, (expr) => isSafeComparison(expr, options));
35100
35102
  }
35101
- function extractNumericPushdownCandidates(where, options = {}) {
35102
- return extractAndLeaves(where, (expr) => isNumericCandidate(expr, options));
35103
+ function extractTypedPushdownCandidates(where, options = {}) {
35104
+ return extractAndLeaves(
35105
+ where,
35106
+ (expr) => isNumericCandidate(expr, options) || isSelectionInCandidate(expr, options)
35107
+ );
35103
35108
  }
35104
35109
  function extractAndLeaves(where, accept) {
35105
35110
  switch (where.type) {
@@ -35123,8 +35128,27 @@ function extractAndLeaves(where, accept) {
35123
35128
  }
35124
35129
  function isSafeComparison(expr, options) {
35125
35130
  if (isSafeIdComparison(expr, options)) return true;
35126
- if (!isNumericCandidate(expr, options)) return false;
35127
- return options.fieldTypes?.get(expr.left.field) === "NUMBER";
35131
+ if (isNumericCandidate(expr, options)) {
35132
+ return options.fieldTypes?.get(expr.left.field) === "NUMBER";
35133
+ }
35134
+ return isSelectionInComparison(expr, options);
35135
+ }
35136
+ var SELECTION_IN_FIELD_TYPES = /* @__PURE__ */ new Set([
35137
+ "DROP_DOWN",
35138
+ "RADIO_BUTTON",
35139
+ "CHECK_BOX",
35140
+ "MULTI_SELECT"
35141
+ ]);
35142
+ function isSelectionInComparison(expr, options) {
35143
+ if (!isSelectionInCandidate(expr, options)) return false;
35144
+ if (expr.left.type !== "FIELD" || expr.right.type !== "IN_LIST") return false;
35145
+ const fieldType = options.fieldTypes?.get(expr.left.field);
35146
+ if (fieldType === void 0 || !SELECTION_IN_FIELD_TYPES.has(fieldType)) return false;
35147
+ const validOptions = options.fieldOptions?.get(expr.left.field);
35148
+ if (validOptions === void 0) return false;
35149
+ return expr.right.values.every(
35150
+ (value) => value.type === "STRING" && value.value !== "" && validOptions.has(value.value)
35151
+ );
35128
35152
  }
35129
35153
  function isSafeIdComparison(expr, options) {
35130
35154
  if (!isTargetIdField(expr.left, options)) return false;
@@ -35144,6 +35168,13 @@ function isNumericCandidate(expr, options) {
35144
35168
  if (expr.op === "=") return true;
35145
35169
  return (expr.op === "<" || expr.op === ">") && Number.isSafeInteger(expr.right.value);
35146
35170
  }
35171
+ function isSelectionInCandidate(expr, options) {
35172
+ if (expr.left.type !== "FIELD" || expr.left.field === "$id") return false;
35173
+ if (!isTargetField(expr.left, options)) return false;
35174
+ if (expr.op !== "IN" && expr.op !== "NOT_IN") return false;
35175
+ if (expr.right.type !== "IN_LIST" || expr.right.values.length === 0) return false;
35176
+ return expr.right.values.every((value) => value.type === "STRING" && value.value !== "");
35177
+ }
35147
35178
  function isTargetField(field, options) {
35148
35179
  const targetAlias = options.tableAlias ?? null;
35149
35180
  if (field.tableAlias === targetAlias) return true;
@@ -35155,7 +35186,7 @@ function flatten(record2, alias) {
35155
35186
  const row = {};
35156
35187
  for (const [field, fv] of Object.entries(record2)) {
35157
35188
  const val = fv.value;
35158
- const strVal = typeof val === "string" ? val : JSON.stringify(val ?? "");
35189
+ const strVal = val == null ? "" : typeof val === "string" ? val : JSON.stringify(val);
35159
35190
  if (alias) {
35160
35191
  row[`${alias}.${field}`] = strVal;
35161
35192
  row[field] = strVal;
@@ -36365,43 +36396,57 @@ async function validateSelectFieldCodes(stmt, mode, client, cacheContext) {
36365
36396
  }
36366
36397
  }
36367
36398
  }
36368
- function extractMainSafePushdown(stmt, fieldTypes) {
36399
+ function extractMainSafePushdown(stmt, fieldTypes, fieldOptions) {
36369
36400
  if (stmt.where === null || stmt.from.subtableCode || stmt.from.cteName !== null) return null;
36370
36401
  if (stmt.joins.length === 0) {
36371
36402
  return extractSafePushdownLeaves(stmt.where, {
36372
36403
  tableAlias: stmt.from.alias ?? void 0,
36373
36404
  allowUnqualifiedFields: true,
36374
- fieldTypes
36405
+ fieldTypes,
36406
+ fieldOptions
36375
36407
  });
36376
36408
  }
36377
36409
  if (!stmt.from.alias) return null;
36378
- return extractSafePushdownLeaves(stmt.where, { tableAlias: stmt.from.alias, fieldTypes });
36410
+ return extractSafePushdownLeaves(stmt.where, {
36411
+ tableAlias: stmt.from.alias,
36412
+ fieldTypes,
36413
+ fieldOptions
36414
+ });
36379
36415
  }
36380
- function extractMainNumericPushdownCandidate(stmt) {
36416
+ function extractMainTypedPushdownCandidate(stmt) {
36381
36417
  if (stmt.where === null || stmt.from.subtableCode || stmt.from.cteName !== null) return null;
36382
36418
  if (stmt.joins.length === 0) {
36383
- return extractNumericPushdownCandidates(stmt.where, {
36419
+ return extractTypedPushdownCandidates(stmt.where, {
36384
36420
  tableAlias: stmt.from.alias ?? void 0,
36385
36421
  allowUnqualifiedFields: true
36386
36422
  });
36387
36423
  }
36388
36424
  if (!stmt.from.alias) return null;
36389
- return extractNumericPushdownCandidates(stmt.where, { tableAlias: stmt.from.alias });
36425
+ return extractTypedPushdownCandidates(stmt.where, { tableAlias: stmt.from.alias });
36390
36426
  }
36391
- async function loadNumericPushdownFieldTypes(stmt, client, cacheContext) {
36427
+ async function loadTypedPushdownMeta(stmt, client, cacheContext) {
36392
36428
  const appIds = /* @__PURE__ */ new Set();
36393
- if (extractMainNumericPushdownCandidate(stmt) !== null) appIds.add(stmt.from.appId);
36429
+ if (extractMainTypedPushdownCandidate(stmt) !== null) appIds.add(stmt.from.appId);
36394
36430
  if (stmt.where !== null) {
36395
36431
  for (const join of stmt.joins) {
36396
36432
  if (!join.table.alias || join.table.subtableCode || join.table.cteName !== null) continue;
36397
- const candidate = extractNumericPushdownCandidates(stmt.where, {
36433
+ const candidate = extractTypedPushdownCandidates(stmt.where, {
36398
36434
  tableAlias: join.table.alias
36399
36435
  });
36400
36436
  if (candidate !== null) appIds.add(join.table.appId);
36401
36437
  }
36402
36438
  }
36403
- const entries = await Promise.all([...appIds].map(async (appId) => [appId, await getFieldTypeMap(appId, client, cacheContext)]));
36404
- return new Map(entries);
36439
+ const entries = await Promise.all([...appIds].map(async (appId) => {
36440
+ const [fieldTypes, fieldOptions] = await Promise.all([
36441
+ getFieldTypeMap(appId, client, cacheContext),
36442
+ getFieldOptionSetMapByApp(appId, client, cacheContext)
36443
+ ]);
36444
+ return [appId, fieldTypes, fieldOptions];
36445
+ }));
36446
+ return {
36447
+ fieldTypesByApp: new Map(entries.map(([appId, fieldTypes]) => [appId, fieldTypes])),
36448
+ fieldOptionsByApp: new Map(entries.map(([appId, , fieldOptions]) => [appId, fieldOptions]))
36449
+ };
36405
36450
  }
36406
36451
  function collectTypedInFieldRefs(expr, out) {
36407
36452
  if (expr === null) return;
@@ -36513,14 +36558,15 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
36513
36558
  resolveSubqueries(stmt.where, client, options, cacheContext, cteCache),
36514
36559
  resolveSubqueries(stmt.having, client, options, cacheContext, cteCache)
36515
36560
  ]);
36516
- const [pushdownFieldTypes, typedInFieldTypes] = await Promise.all([
36517
- loadNumericPushdownFieldTypes(stmt, client, cacheContext),
36561
+ const [pushdownMeta, typedInFieldTypes] = await Promise.all([
36562
+ loadTypedPushdownMeta(stmt, client, cacheContext),
36518
36563
  loadTypedInFieldTypes(stmt, client, cacheContext)
36519
36564
  ]);
36520
36565
  const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
36521
36566
  const mainPushDown = extractMainSafePushdown(
36522
36567
  stmt,
36523
- pushdownFieldTypes.get(stmt.from.appId)
36568
+ pushdownMeta.fieldTypesByApp.get(stmt.from.appId),
36569
+ pushdownMeta.fieldOptionsByApp.get(stmt.from.appId)
36524
36570
  );
36525
36571
  const tableConditions = /* @__PURE__ */ new Map();
36526
36572
  if (stmt.where !== null) {
@@ -36528,7 +36574,8 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
36528
36574
  if (!join.table.alias || join.table.subtableCode || join.table.cteName !== null) continue;
36529
36575
  const cond = extractSafePushdownLeaves(stmt.where, {
36530
36576
  tableAlias: join.table.alias,
36531
- fieldTypes: pushdownFieldTypes.get(join.table.appId)
36577
+ fieldTypes: pushdownMeta.fieldTypesByApp.get(join.table.appId),
36578
+ fieldOptions: pushdownMeta.fieldOptionsByApp.get(join.table.appId)
36532
36579
  });
36533
36580
  if (cond) tableConditions.set(join.table.alias, cond);
36534
36581
  }
@@ -37069,6 +37116,15 @@ async function getOptionOrderMapByApp(appId, client, cacheContext) {
37069
37116
  setScopedCacheValue(optionOrderCache, cacheContext, appId, map2);
37070
37117
  return map2;
37071
37118
  }
37119
+ async function getFieldOptionSetMapByApp(appId, client, cacheContext) {
37120
+ const optionOrders = await getOptionOrderMapByApp(appId, client, cacheContext);
37121
+ return new Map(
37122
+ [...optionOrders.entries()].map(([fieldCode, order]) => [
37123
+ fieldCode,
37124
+ new Set(order.keys())
37125
+ ])
37126
+ );
37127
+ }
37072
37128
  async function getSortKindMapByApp(appId, client, cacheContext) {
37073
37129
  const cached2 = getScopedCacheValue(sortKindCache, cacheContext, appId);
37074
37130
  if (cached2) return cached2;
@@ -38028,12 +38084,12 @@ function buildSelectPlan(stmt, label) {
38028
38084
  const mainFields = selectToFetchAllFields(stmt, stmt.from);
38029
38085
  const mainAliasStr = stmt.from.alias ? ` AS ${stmt.from.alias}` : "";
38030
38086
  const mainPushDown = extractMainSafePushdown(stmt);
38031
- const mainCandidate = extractMainNumericPushdownCandidate(stmt);
38087
+ const mainCandidate = extractMainTypedPushdownCandidate(stmt);
38032
38088
  const mainQ = mainPushDown !== null ? whereToKintone(mainPushDown) : "(\u5168\u4EF6\u53D6\u5F97)";
38033
38089
  lines.push(` app: APP${stmt.from.appId}${mainAliasStr} (${stmt.from.appId})`);
38034
38090
  lines.push(` kintone query: ${mainQ}`);
38035
38091
  if (mainCandidate !== null) {
38036
- lines.push(` pushdown candidate: ${whereToKintone(mainCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u78BA\u8A8D\u5F85\u3061\uFF09`);
38092
+ lines.push(` pushdown candidate: ${whereToKintone(mainCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u30FB\u5B9F\u5728\u78BA\u8A8D\u5F85\u3061\uFF09`);
38037
38093
  }
38038
38094
  lines.push(` fields: ${mainFields.length === 0 ? "(\u5168\u30D5\u30A3\u30FC\u30EB\u30C9)" : mainFields.join(", ")}`);
38039
38095
  for (const join of stmt.joins) {
@@ -38041,12 +38097,12 @@ function buildSelectPlan(stmt, label) {
38041
38097
  const joinAliasStr = join.table.alias ? ` AS ${join.table.alias}` : "";
38042
38098
  const joinType = join.type === "INNER" ? "JOIN" : `${join.type} JOIN`;
38043
38099
  const joinPushDown = join.table.alias && !join.table.subtableCode && join.table.cteName === null && stmt.where ? extractSafePushdownLeaves(stmt.where, { tableAlias: join.table.alias }) : null;
38044
- const joinCandidate = join.table.alias && !join.table.subtableCode && join.table.cteName === null && stmt.where ? extractNumericPushdownCandidates(stmt.where, { tableAlias: join.table.alias }) : null;
38100
+ const joinCandidate = join.table.alias && !join.table.subtableCode && join.table.cteName === null && stmt.where ? extractTypedPushdownCandidates(stmt.where, { tableAlias: join.table.alias }) : null;
38045
38101
  const joinQ = joinPushDown !== null ? whereToKintone(joinPushDown) : "(\u5168\u4EF6\u53D6\u5F97)";
38046
38102
  lines.push(` ${joinType}: APP${join.table.appId}${joinAliasStr} (${join.table.appId})`);
38047
38103
  lines.push(` kintone query: ${joinQ}`);
38048
38104
  if (joinCandidate !== null) {
38049
- lines.push(` pushdown candidate: ${whereToKintone(joinCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u78BA\u8A8D\u5F85\u3061\uFF09`);
38105
+ lines.push(` pushdown candidate: ${whereToKintone(joinCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u30FB\u5B9F\u5728\u78BA\u8A8D\u5F85\u3061\uFF09`);
38050
38106
  }
38051
38107
  lines.push(` fields: ${joinFields.length === 0 ? "(\u5168\u30D5\u30A3\u30FC\u30EB\u30C9)" : joinFields.join(", ")}`);
38052
38108
  }
@@ -40395,7 +40451,7 @@ Options:
40395
40451
  -h, --help Show help
40396
40452
  `);
40397
40453
  }
40398
- var SERVER_VERSION = true ? "2.5.0" : "0.0.0-dev";
40454
+ var SERVER_VERSION = true ? "2.6.0" : "0.0.0-dev";
40399
40455
  function createServer(args) {
40400
40456
  const server = new McpServer({
40401
40457
  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.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "kintone SQL plugin, CLI, and MCP tools (ksql)",
5
5
  "publishConfig": {
6
6
  "access": "public"