@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 +80 -24
- package/dist-mcp/ksql-mcp.js +81 -25
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
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
|
|
4201
|
-
return extractAndLeaves(
|
|
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 (
|
|
4226
|
-
|
|
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, {
|
|
5509
|
+
return extractSafePushdownLeaves(stmt.where, {
|
|
5510
|
+
tableAlias: stmt.from.alias,
|
|
5511
|
+
fieldTypes,
|
|
5512
|
+
fieldOptions
|
|
5513
|
+
});
|
|
5478
5514
|
}
|
|
5479
|
-
function
|
|
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
|
|
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
|
|
5524
|
+
return extractTypedPushdownCandidates(stmt.where, { tableAlias: stmt.from.alias });
|
|
5489
5525
|
}
|
|
5490
|
-
async function
|
|
5526
|
+
async function loadTypedPushdownMeta(stmt, client, cacheContext) {
|
|
5491
5527
|
const appIds = /* @__PURE__ */ new Set();
|
|
5492
|
-
if (
|
|
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 =
|
|
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) =>
|
|
5503
|
-
|
|
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 [
|
|
5616
|
-
|
|
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
|
-
|
|
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:
|
|
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 =
|
|
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 ?
|
|
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
|
}
|
package/dist-mcp/ksql-mcp.js
CHANGED
|
@@ -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
|
|
35102
|
-
return extractAndLeaves(
|
|
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 (
|
|
35127
|
-
|
|
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, {
|
|
36410
|
+
return extractSafePushdownLeaves(stmt.where, {
|
|
36411
|
+
tableAlias: stmt.from.alias,
|
|
36412
|
+
fieldTypes,
|
|
36413
|
+
fieldOptions
|
|
36414
|
+
});
|
|
36379
36415
|
}
|
|
36380
|
-
function
|
|
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
|
|
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
|
|
36425
|
+
return extractTypedPushdownCandidates(stmt.where, { tableAlias: stmt.from.alias });
|
|
36390
36426
|
}
|
|
36391
|
-
async function
|
|
36427
|
+
async function loadTypedPushdownMeta(stmt, client, cacheContext) {
|
|
36392
36428
|
const appIds = /* @__PURE__ */ new Set();
|
|
36393
|
-
if (
|
|
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 =
|
|
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) =>
|
|
36404
|
-
|
|
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 [
|
|
36517
|
-
|
|
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
|
-
|
|
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:
|
|
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 =
|
|
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 ?
|
|
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.
|
|
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",
|
package/dist-mcpb/ksql-mcp.mcpb
CHANGED
|
Binary file
|