@rex0220/kintone-sql-tools 2.8.0 → 2.9.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 +294 -253
- package/dist-mcp/ksql-mcp.js +295 -254
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-mcp/ksql-mcp.js
CHANGED
|
@@ -34017,6 +34017,235 @@ function isAggregateSyntheticName(name) {
|
|
|
34017
34017
|
return /^(COUNT|SUM|AVG|MAX|MIN)\(/i.test(name);
|
|
34018
34018
|
}
|
|
34019
34019
|
|
|
34020
|
+
// src/core/cteInlining.ts
|
|
34021
|
+
function canInlineSingleCte(stmt) {
|
|
34022
|
+
if (stmt.ctes.length !== 1) return false;
|
|
34023
|
+
const cteDef = stmt.ctes[0];
|
|
34024
|
+
if (cteDef.query.type !== "SELECT" || resolveSelectMode(cteDef.query) !== "SIMPLE") return false;
|
|
34025
|
+
const finalQuery = stmt.query;
|
|
34026
|
+
if (finalQuery.type !== "SELECT") return false;
|
|
34027
|
+
if (finalQuery.from.cteName !== cteDef.name || finalQuery.joins.length > 0) return false;
|
|
34028
|
+
if (finalQuery.groupBy.length > 0 || finalQuery.distinct) return false;
|
|
34029
|
+
return !finalQuery.columns.some(
|
|
34030
|
+
(column) => column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL"
|
|
34031
|
+
);
|
|
34032
|
+
}
|
|
34033
|
+
function buildInlinedQuery(stmt) {
|
|
34034
|
+
const cteBody = stmt.ctes[0].query;
|
|
34035
|
+
const final = stmt.query;
|
|
34036
|
+
const finalWhere = stripCteAlias(final.where, final.from.alias);
|
|
34037
|
+
const where = cteBody.where === null ? finalWhere : finalWhere === null ? cteBody.where : { type: "LOGICAL", op: "AND", left: cteBody.where, right: finalWhere };
|
|
34038
|
+
const columns = final.columns.every((column) => column.type === "WILDCARD") ? cteBody.columns : final.columns;
|
|
34039
|
+
return {
|
|
34040
|
+
type: "SELECT",
|
|
34041
|
+
from: cteBody.from,
|
|
34042
|
+
joins: [],
|
|
34043
|
+
columns,
|
|
34044
|
+
where,
|
|
34045
|
+
groupBy: [],
|
|
34046
|
+
having: null,
|
|
34047
|
+
orderBy: final.orderBy.length > 0 ? final.orderBy : cteBody.orderBy,
|
|
34048
|
+
limit: final.limit ?? cteBody.limit,
|
|
34049
|
+
offset: final.offset ?? cteBody.offset,
|
|
34050
|
+
distinct: false
|
|
34051
|
+
};
|
|
34052
|
+
}
|
|
34053
|
+
function stripCteAlias(where, alias) {
|
|
34054
|
+
if (where === null || alias === null) return where;
|
|
34055
|
+
switch (where.type) {
|
|
34056
|
+
case "BINARY":
|
|
34057
|
+
return { ...where, left: stripCteAliasFromFieldValue(where.left, alias) };
|
|
34058
|
+
case "NULL_CHECK":
|
|
34059
|
+
return { ...where, field: stripCteAliasFromFieldValue(where.field, alias) };
|
|
34060
|
+
case "LOGICAL":
|
|
34061
|
+
return {
|
|
34062
|
+
...where,
|
|
34063
|
+
left: stripCteAlias(where.left, alias),
|
|
34064
|
+
right: stripCteAlias(where.right, alias)
|
|
34065
|
+
};
|
|
34066
|
+
case "NOT":
|
|
34067
|
+
case "GROUP":
|
|
34068
|
+
return { ...where, expr: stripCteAlias(where.expr, alias) };
|
|
34069
|
+
case "EXISTS":
|
|
34070
|
+
return where;
|
|
34071
|
+
}
|
|
34072
|
+
}
|
|
34073
|
+
function stripCteAliasFromFieldValue(value, alias) {
|
|
34074
|
+
if (value.type === "FIELD" && value.tableAlias === alias) {
|
|
34075
|
+
return { ...value, tableAlias: null };
|
|
34076
|
+
}
|
|
34077
|
+
return value;
|
|
34078
|
+
}
|
|
34079
|
+
|
|
34080
|
+
// src/core/optimization/wherePredicatePushdown.ts
|
|
34081
|
+
function extractSafePushdownLeaves(where, options = {}) {
|
|
34082
|
+
return extractAndLeaves(where, (expr) => isSafeComparison(expr, options));
|
|
34083
|
+
}
|
|
34084
|
+
function extractTypedPushdownCandidates(where, options = {}) {
|
|
34085
|
+
return extractAndLeaves(
|
|
34086
|
+
where,
|
|
34087
|
+
(expr) => isNumericCandidate(expr, options) || isSelectionInCandidate(expr, options)
|
|
34088
|
+
);
|
|
34089
|
+
}
|
|
34090
|
+
function extractAndLeaves(where, accept) {
|
|
34091
|
+
switch (where.type) {
|
|
34092
|
+
case "BINARY":
|
|
34093
|
+
return accept(where) ? where : null;
|
|
34094
|
+
case "LOGICAL":
|
|
34095
|
+
if (where.op !== "AND") return null;
|
|
34096
|
+
{
|
|
34097
|
+
const left = extractAndLeaves(where.left, accept);
|
|
34098
|
+
const right = extractAndLeaves(where.right, accept);
|
|
34099
|
+
if (left && right) return { ...where, left, right };
|
|
34100
|
+
return left ?? right ?? null;
|
|
34101
|
+
}
|
|
34102
|
+
case "GROUP":
|
|
34103
|
+
return extractAndLeaves(where.expr, accept);
|
|
34104
|
+
case "NULL_CHECK":
|
|
34105
|
+
case "NOT":
|
|
34106
|
+
case "EXISTS":
|
|
34107
|
+
return null;
|
|
34108
|
+
}
|
|
34109
|
+
}
|
|
34110
|
+
function isSafeComparison(expr, options) {
|
|
34111
|
+
if (isKlikeComparison(expr, options)) return true;
|
|
34112
|
+
if (isSafeIdComparison(expr, options)) return true;
|
|
34113
|
+
if (isNumericCandidate(expr, options)) {
|
|
34114
|
+
return options.fieldTypes?.get(expr.left.field) === "NUMBER";
|
|
34115
|
+
}
|
|
34116
|
+
return isSelectionInComparison(expr, options);
|
|
34117
|
+
}
|
|
34118
|
+
function isKlikeComparison(expr, options) {
|
|
34119
|
+
if (options.allowKlike === false) return false;
|
|
34120
|
+
if (expr.op !== "KLIKE" && expr.op !== "NOT_KLIKE") return false;
|
|
34121
|
+
if (expr.left.type !== "FIELD" || !isTargetField(expr.left, options)) return false;
|
|
34122
|
+
return expr.right.type === "STRING" || options.allowUnresolvedKlikeVariables === true && expr.right.type === "VARIABLE";
|
|
34123
|
+
}
|
|
34124
|
+
var SELECTION_IN_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
34125
|
+
"DROP_DOWN",
|
|
34126
|
+
"RADIO_BUTTON",
|
|
34127
|
+
"CHECK_BOX",
|
|
34128
|
+
"MULTI_SELECT",
|
|
34129
|
+
"STATUS"
|
|
34130
|
+
]);
|
|
34131
|
+
function isSelectionInComparison(expr, options) {
|
|
34132
|
+
if (!isSelectionInCandidate(expr, options)) return false;
|
|
34133
|
+
if (expr.left.type !== "FIELD" || expr.right.type !== "IN_LIST") return false;
|
|
34134
|
+
const fieldType = options.fieldTypes?.get(expr.left.field);
|
|
34135
|
+
if (fieldType === void 0 || !SELECTION_IN_FIELD_TYPES.has(fieldType)) return false;
|
|
34136
|
+
const validOptions = options.fieldOptions?.get(expr.left.field);
|
|
34137
|
+
if (validOptions === void 0) return false;
|
|
34138
|
+
return expr.right.values.every(
|
|
34139
|
+
(value) => value.type === "STRING" && value.value !== "" && validOptions.has(value.value)
|
|
34140
|
+
);
|
|
34141
|
+
}
|
|
34142
|
+
function isSafeIdComparison(expr, options) {
|
|
34143
|
+
if (!isTargetIdField(expr.left, options)) return false;
|
|
34144
|
+
if (expr.right.type !== "NUMBER") return false;
|
|
34145
|
+
return expr.op === "=" || expr.op === ">" || expr.op === "<" || expr.op === ">=" || expr.op === "<=";
|
|
34146
|
+
}
|
|
34147
|
+
function isTargetIdField(field, options) {
|
|
34148
|
+
if (field.type !== "FIELD" || field.field !== "$id") return false;
|
|
34149
|
+
const targetAlias = options.tableAlias ?? null;
|
|
34150
|
+
if (field.tableAlias === targetAlias) return true;
|
|
34151
|
+
return options.allowUnqualifiedFields === true && field.tableAlias === null;
|
|
34152
|
+
}
|
|
34153
|
+
function isNumericCandidate(expr, options) {
|
|
34154
|
+
if (expr.left.type !== "FIELD" || expr.left.field === "$id") return false;
|
|
34155
|
+
if (!isTargetField(expr.left, options)) return false;
|
|
34156
|
+
if (expr.right.type !== "NUMBER") return false;
|
|
34157
|
+
if (expr.op === "=") return true;
|
|
34158
|
+
return (expr.op === "<" || expr.op === ">") && Number.isSafeInteger(expr.right.value);
|
|
34159
|
+
}
|
|
34160
|
+
function isSelectionInCandidate(expr, options) {
|
|
34161
|
+
if (expr.left.type !== "FIELD" || expr.left.field === "$id") return false;
|
|
34162
|
+
if (!isTargetField(expr.left, options)) return false;
|
|
34163
|
+
if (expr.op !== "IN" && expr.op !== "NOT_IN") return false;
|
|
34164
|
+
if (expr.right.type !== "IN_LIST" || expr.right.values.length === 0) return false;
|
|
34165
|
+
return expr.right.values.every((value) => value.type === "STRING" && value.value !== "");
|
|
34166
|
+
}
|
|
34167
|
+
function isTargetField(field, options) {
|
|
34168
|
+
const targetAlias = options.tableAlias ?? null;
|
|
34169
|
+
if (field.tableAlias === targetAlias) return true;
|
|
34170
|
+
return options.allowUnqualifiedFields === true && field.tableAlias === null;
|
|
34171
|
+
}
|
|
34172
|
+
|
|
34173
|
+
// src/core/optimization/klikePushdownPlan.ts
|
|
34174
|
+
function buildKlikePushdownPlan(stmt, options = {}) {
|
|
34175
|
+
const joinsAreSafeForKlike = stmt.joins.every((join) => join.type === "INNER");
|
|
34176
|
+
const common = {
|
|
34177
|
+
allowKlike: joinsAreSafeForKlike,
|
|
34178
|
+
allowUnresolvedKlikeVariables: options.allowUnresolvedVariables
|
|
34179
|
+
};
|
|
34180
|
+
let mainCondition = null;
|
|
34181
|
+
if (stmt.where !== null && !stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
34182
|
+
if (stmt.joins.length === 0) {
|
|
34183
|
+
mainCondition = extractSafePushdownLeaves(stmt.where, {
|
|
34184
|
+
...common,
|
|
34185
|
+
tableAlias: stmt.from.alias ?? void 0,
|
|
34186
|
+
allowUnqualifiedFields: true,
|
|
34187
|
+
fieldTypes: options.fieldTypesByApp?.get(stmt.from.appId),
|
|
34188
|
+
fieldOptions: options.fieldOptionsByApp?.get(stmt.from.appId)
|
|
34189
|
+
});
|
|
34190
|
+
} else if (stmt.from.alias) {
|
|
34191
|
+
mainCondition = extractSafePushdownLeaves(stmt.where, {
|
|
34192
|
+
...common,
|
|
34193
|
+
tableAlias: stmt.from.alias,
|
|
34194
|
+
fieldTypes: options.fieldTypesByApp?.get(stmt.from.appId),
|
|
34195
|
+
fieldOptions: options.fieldOptionsByApp?.get(stmt.from.appId)
|
|
34196
|
+
});
|
|
34197
|
+
}
|
|
34198
|
+
}
|
|
34199
|
+
const joinConditions = /* @__PURE__ */ new Map();
|
|
34200
|
+
if (stmt.where !== null) {
|
|
34201
|
+
for (const join of stmt.joins) {
|
|
34202
|
+
if (!join.table.alias || join.table.subtableCode || join.table.cteName !== null) continue;
|
|
34203
|
+
const condition = extractSafePushdownLeaves(stmt.where, {
|
|
34204
|
+
...common,
|
|
34205
|
+
tableAlias: join.table.alias,
|
|
34206
|
+
fieldTypes: options.fieldTypesByApp?.get(join.table.appId),
|
|
34207
|
+
fieldOptions: options.fieldOptionsByApp?.get(join.table.appId)
|
|
34208
|
+
});
|
|
34209
|
+
if (condition !== null) joinConditions.set(join.table.alias, condition);
|
|
34210
|
+
}
|
|
34211
|
+
}
|
|
34212
|
+
const appliedKlikes = /* @__PURE__ */ new Set();
|
|
34213
|
+
collectKlikes(mainCondition, appliedKlikes);
|
|
34214
|
+
for (const condition of joinConditions.values()) collectKlikes(condition, appliedKlikes);
|
|
34215
|
+
const allKlikes = /* @__PURE__ */ new Set();
|
|
34216
|
+
collectKlikes(stmt.where, allKlikes);
|
|
34217
|
+
return {
|
|
34218
|
+
mainCondition,
|
|
34219
|
+
joinConditions,
|
|
34220
|
+
appliedKlikes,
|
|
34221
|
+
allKlikes: [...allKlikes]
|
|
34222
|
+
};
|
|
34223
|
+
}
|
|
34224
|
+
function unappliedKlikes(plan) {
|
|
34225
|
+
return plan.allKlikes.filter((expr) => !plan.appliedKlikes.has(expr));
|
|
34226
|
+
}
|
|
34227
|
+
function collectKlikes(where, out) {
|
|
34228
|
+
if (where === null) return;
|
|
34229
|
+
if (isKlike(where)) {
|
|
34230
|
+
out.add(where);
|
|
34231
|
+
return;
|
|
34232
|
+
}
|
|
34233
|
+
switch (where.type) {
|
|
34234
|
+
case "LOGICAL":
|
|
34235
|
+
collectKlikes(where.left, out);
|
|
34236
|
+
collectKlikes(where.right, out);
|
|
34237
|
+
return;
|
|
34238
|
+
case "NOT":
|
|
34239
|
+
case "GROUP":
|
|
34240
|
+
collectKlikes(where.expr, out);
|
|
34241
|
+
return;
|
|
34242
|
+
case "BINARY":
|
|
34243
|
+
case "NULL_CHECK":
|
|
34244
|
+
case "EXISTS":
|
|
34245
|
+
return;
|
|
34246
|
+
}
|
|
34247
|
+
}
|
|
34248
|
+
|
|
34020
34249
|
// src/core/klikeValidation.ts
|
|
34021
34250
|
var KlikeValidationError = class extends Error {
|
|
34022
34251
|
constructor(message) {
|
|
@@ -34027,6 +34256,13 @@ var KlikeValidationError = class extends Error {
|
|
|
34027
34256
|
function validateKlikeStatement(stmt) {
|
|
34028
34257
|
validateStatement(stmt);
|
|
34029
34258
|
}
|
|
34259
|
+
function validateKlikePushdownPlan(plan) {
|
|
34260
|
+
if (unappliedKlikes(plan).length > 0) {
|
|
34261
|
+
throw new KlikeValidationError(
|
|
34262
|
+
"FULL_SCAN \u306E KLIKE / NOT KLIKE \u3092\u5B89\u5168\u306B\u62BC\u3057\u4E0B\u3052\u3089\u308C\u307E\u305B\u3093\u3002OR / NOT \u914D\u4E0B\u3001CTE\u30FB\u4E00\u6642\u30C6\u30FC\u30D6\u30EB\u3001LEFT / RIGHT JOIN \u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
34263
|
+
);
|
|
34264
|
+
}
|
|
34265
|
+
}
|
|
34030
34266
|
function validateStatement(stmt) {
|
|
34031
34267
|
switch (stmt.type) {
|
|
34032
34268
|
case "SELECT":
|
|
@@ -34058,7 +34294,7 @@ function validateStatement(stmt) {
|
|
|
34058
34294
|
case "REORDER":
|
|
34059
34295
|
if (containsKlike(stmt)) {
|
|
34060
34296
|
throw new KlikeValidationError(
|
|
34061
|
-
"KLIKE / NOT KLIKE \u306F
|
|
34297
|
+
"KLIKE / NOT KLIKE \u306F\u5168 DML\uFF08UPDATE / DELETE / INSERT / UPSERT / REORDER\uFF09\u3067\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093"
|
|
34062
34298
|
);
|
|
34063
34299
|
}
|
|
34064
34300
|
return;
|
|
@@ -34078,9 +34314,8 @@ function validateUnion(stmt) {
|
|
|
34078
34314
|
validateSelect(stmt.right);
|
|
34079
34315
|
}
|
|
34080
34316
|
function validateWith(stmt) {
|
|
34081
|
-
|
|
34082
|
-
|
|
34083
|
-
validateSelect(inlined);
|
|
34317
|
+
if (canInlineSingleCte(stmt)) {
|
|
34318
|
+
validateSelect(buildInlinedQuery(stmt));
|
|
34084
34319
|
return;
|
|
34085
34320
|
}
|
|
34086
34321
|
for (const cte of stmt.ctes) {
|
|
@@ -34092,10 +34327,15 @@ function validateWith(stmt) {
|
|
|
34092
34327
|
function validateSelect(stmt) {
|
|
34093
34328
|
validateOwnKlikeExpressions(stmt);
|
|
34094
34329
|
if (whereHasKlike(stmt.where)) {
|
|
34095
|
-
const
|
|
34096
|
-
if (
|
|
34330
|
+
const directKintoneSimple = resolveSelectMode(stmt) === "SIMPLE" && stmt.from.cteName === null && stmt.joins.every((join) => join.table.cteName === null);
|
|
34331
|
+
if (!directKintoneSimple) {
|
|
34332
|
+
const plan = buildKlikePushdownPlan(stmt, { allowUnresolvedVariables: true });
|
|
34333
|
+
if (unappliedKlikes(plan).length === 0) {
|
|
34334
|
+
validateNestedSelects(stmt);
|
|
34335
|
+
return;
|
|
34336
|
+
}
|
|
34097
34337
|
throw new KlikeValidationError(
|
|
34098
|
-
"KLIKE / NOT KLIKE \u306F
|
|
34338
|
+
"FULL_SCAN \u306E KLIKE / NOT KLIKE \u306F\u3001\u7269\u7406\u30C6\u30FC\u30D6\u30EB\u306B\u5BFE\u3059\u308B AND \u30EA\u30FC\u30D5\u3068\u3057\u3066\u5FC5\u305A\u62BC\u3057\u4E0B\u3052\u3089\u308C\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002OR / NOT \u914D\u4E0B\u3001CTE\u30FB\u4E00\u6642\u30C6\u30FC\u30D6\u30EB\u3001LEFT / RIGHT JOIN \u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093"
|
|
34099
34339
|
);
|
|
34100
34340
|
}
|
|
34101
34341
|
}
|
|
@@ -34125,33 +34365,6 @@ function validateNestedSelects(node) {
|
|
|
34125
34365
|
if (obj.type === "SELECT") validateSelect(obj);
|
|
34126
34366
|
}, true);
|
|
34127
34367
|
}
|
|
34128
|
-
function buildEffectiveInlineSelect(stmt) {
|
|
34129
|
-
if (stmt.ctes.length !== 1) return null;
|
|
34130
|
-
const cte = stmt.ctes[0];
|
|
34131
|
-
if (cte.query.type !== "SELECT" || resolveSelectMode(cte.query) !== "SIMPLE") return null;
|
|
34132
|
-
if (stmt.query.type !== "SELECT") return null;
|
|
34133
|
-
const final = stmt.query;
|
|
34134
|
-
if (final.from.cteName !== cte.name || final.joins.length > 0) return null;
|
|
34135
|
-
if (final.groupBy.length > 0 || final.distinct) return null;
|
|
34136
|
-
if (final.columns.some(
|
|
34137
|
-
(column) => column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL"
|
|
34138
|
-
)) return null;
|
|
34139
|
-
const where = cte.query.where === null ? final.where : final.where === null ? cte.query.where : { type: "LOGICAL", op: "AND", left: cte.query.where, right: final.where };
|
|
34140
|
-
const columns = final.columns.every((column) => column.type === "WILDCARD") ? cte.query.columns : final.columns;
|
|
34141
|
-
return {
|
|
34142
|
-
type: "SELECT",
|
|
34143
|
-
from: cte.query.from,
|
|
34144
|
-
joins: [],
|
|
34145
|
-
columns,
|
|
34146
|
-
where,
|
|
34147
|
-
groupBy: [],
|
|
34148
|
-
having: null,
|
|
34149
|
-
orderBy: final.orderBy.length > 0 ? final.orderBy : cte.query.orderBy,
|
|
34150
|
-
limit: final.limit ?? cte.query.limit,
|
|
34151
|
-
offset: final.offset ?? cte.query.offset,
|
|
34152
|
-
distinct: false
|
|
34153
|
-
};
|
|
34154
|
-
}
|
|
34155
34368
|
function containsKlike(node) {
|
|
34156
34369
|
let found = false;
|
|
34157
34370
|
walkObjects(node, (obj) => {
|
|
@@ -34656,25 +34869,29 @@ function resolveFieldRef(row, field) {
|
|
|
34656
34869
|
}
|
|
34657
34870
|
|
|
34658
34871
|
// src/engine/evalWhere.ts
|
|
34659
|
-
function evalWhere(expr, row, resolveFieldType) {
|
|
34872
|
+
function evalWhere(expr, row, resolveFieldType, appliedKlikes) {
|
|
34660
34873
|
switch (expr.type) {
|
|
34661
34874
|
case "BINARY":
|
|
34662
|
-
return evalBinary(expr, row, resolveFieldType);
|
|
34875
|
+
return evalBinary(expr, row, resolveFieldType, appliedKlikes);
|
|
34663
34876
|
case "NULL_CHECK":
|
|
34664
34877
|
return evalNullCheck(expr, row);
|
|
34665
34878
|
case "LOGICAL":
|
|
34666
|
-
return evalLogical(expr, row, resolveFieldType);
|
|
34879
|
+
return evalLogical(expr, row, resolveFieldType, appliedKlikes);
|
|
34667
34880
|
case "NOT":
|
|
34668
|
-
return !evalWhere(expr.expr, row, resolveFieldType);
|
|
34881
|
+
return !evalWhere(expr.expr, row, resolveFieldType, appliedKlikes);
|
|
34669
34882
|
case "GROUP":
|
|
34670
|
-
return evalWhere(expr.expr, row, resolveFieldType);
|
|
34883
|
+
return evalWhere(expr.expr, row, resolveFieldType, appliedKlikes);
|
|
34671
34884
|
case "EXISTS": {
|
|
34672
34885
|
const exists = expr.resolved;
|
|
34673
34886
|
return expr.not ? !exists : exists;
|
|
34674
34887
|
}
|
|
34675
34888
|
}
|
|
34676
34889
|
}
|
|
34677
|
-
function evalBinary(expr, row, resolveFieldType) {
|
|
34890
|
+
function evalBinary(expr, row, resolveFieldType, appliedKlikes) {
|
|
34891
|
+
if (expr.op === "KLIKE" || expr.op === "NOT_KLIKE") {
|
|
34892
|
+
if (appliedKlikes?.has(expr)) return true;
|
|
34893
|
+
throw new Error("KLIKE / NOT KLIKE \u306F\u62BC\u3057\u4E0B\u3052\u6E08\u307F\u96C6\u5408\u306B\u542B\u307E\u308C\u306A\u3044\u305F\u3081 JavaScript \u5074\u3067\u306F\u8A55\u4FA1\u3067\u304D\u307E\u305B\u3093");
|
|
34894
|
+
}
|
|
34678
34895
|
const left = resolveField(expr.left, row, resolveFieldType);
|
|
34679
34896
|
const fieldType = expr.left.type === "FIELD" ? resolveFieldType?.(expr.left) : void 0;
|
|
34680
34897
|
return evalOp(expr.op, left, expr.right, row, fieldType, resolveFieldType);
|
|
@@ -34756,11 +34973,11 @@ function evalNullCheck(expr, row) {
|
|
|
34756
34973
|
const val = resolveField(expr.field, row);
|
|
34757
34974
|
return expr.not ? val !== "" : val === "";
|
|
34758
34975
|
}
|
|
34759
|
-
function evalLogical(expr, row, resolveFieldType) {
|
|
34976
|
+
function evalLogical(expr, row, resolveFieldType, appliedKlikes) {
|
|
34760
34977
|
if (expr.op === "AND") {
|
|
34761
|
-
return evalWhere(expr.left, row, resolveFieldType) && evalWhere(expr.right, row, resolveFieldType);
|
|
34978
|
+
return evalWhere(expr.left, row, resolveFieldType, appliedKlikes) && evalWhere(expr.right, row, resolveFieldType, appliedKlikes);
|
|
34762
34979
|
}
|
|
34763
|
-
return evalWhere(expr.left, row, resolveFieldType) || evalWhere(expr.right, row, resolveFieldType);
|
|
34980
|
+
return evalWhere(expr.left, row, resolveFieldType, appliedKlikes) || evalWhere(expr.right, row, resolveFieldType, appliedKlikes);
|
|
34764
34981
|
}
|
|
34765
34982
|
function resolveField(field, row, resolveFieldType) {
|
|
34766
34983
|
if (field.type === "FUNC_FIELD") return evalStringFunc(field.expr, row);
|
|
@@ -34861,7 +35078,7 @@ function matchLike(value, pattern) {
|
|
|
34861
35078
|
function assertDmlWhereIsSafe(where) {
|
|
34862
35079
|
if (whereHasKlike(where)) {
|
|
34863
35080
|
throw new DmlConvertError(
|
|
34864
|
-
"UPDATE / DELETE \u306E WHERE \u306B KLIKE / NOT KLIKE \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002kintone \u30AD\u30FC\u30EF\u30FC\u30C9\u691C\u7D22\u306E\u6253\u3061\u5207\u308A\u3092\u691C\u51FA\u3067\u304D\u306A\u3044\u305F\u3081\
|
|
35081
|
+
"UPDATE / DELETE \u306E WHERE \u306B KLIKE / NOT KLIKE \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002kintone \u30AD\u30FC\u30EF\u30FC\u30C9\u691C\u7D22\u306E\u6253\u3061\u5207\u308A\u3092\u691C\u51FA\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u5168 DML \u3067\u5B89\u5168\u4E0A\u62D2\u5426\u3057\u3066\u3044\u307E\u3059\u3002"
|
|
34865
35082
|
);
|
|
34866
35083
|
}
|
|
34867
35084
|
if (!whereHasLike(where)) return;
|
|
@@ -35351,92 +35568,6 @@ async function resolveDmlTargetIds(getRecords, app, query, options) {
|
|
|
35351
35568
|
};
|
|
35352
35569
|
}
|
|
35353
35570
|
|
|
35354
|
-
// src/core/optimization/wherePredicatePushdown.ts
|
|
35355
|
-
function extractSafePushdownLeaves(where, options = {}) {
|
|
35356
|
-
return extractAndLeaves(where, (expr) => isSafeComparison(expr, options));
|
|
35357
|
-
}
|
|
35358
|
-
function extractTypedPushdownCandidates(where, options = {}) {
|
|
35359
|
-
return extractAndLeaves(
|
|
35360
|
-
where,
|
|
35361
|
-
(expr) => isNumericCandidate(expr, options) || isSelectionInCandidate(expr, options)
|
|
35362
|
-
);
|
|
35363
|
-
}
|
|
35364
|
-
function extractAndLeaves(where, accept) {
|
|
35365
|
-
switch (where.type) {
|
|
35366
|
-
case "BINARY":
|
|
35367
|
-
return accept(where) ? where : null;
|
|
35368
|
-
case "LOGICAL":
|
|
35369
|
-
if (where.op !== "AND") return null;
|
|
35370
|
-
{
|
|
35371
|
-
const left = extractAndLeaves(where.left, accept);
|
|
35372
|
-
const right = extractAndLeaves(where.right, accept);
|
|
35373
|
-
if (left && right) return { ...where, left, right };
|
|
35374
|
-
return left ?? right ?? null;
|
|
35375
|
-
}
|
|
35376
|
-
case "GROUP":
|
|
35377
|
-
return extractAndLeaves(where.expr, accept);
|
|
35378
|
-
case "NULL_CHECK":
|
|
35379
|
-
case "NOT":
|
|
35380
|
-
case "EXISTS":
|
|
35381
|
-
return null;
|
|
35382
|
-
}
|
|
35383
|
-
}
|
|
35384
|
-
function isSafeComparison(expr, options) {
|
|
35385
|
-
if (isSafeIdComparison(expr, options)) return true;
|
|
35386
|
-
if (isNumericCandidate(expr, options)) {
|
|
35387
|
-
return options.fieldTypes?.get(expr.left.field) === "NUMBER";
|
|
35388
|
-
}
|
|
35389
|
-
return isSelectionInComparison(expr, options);
|
|
35390
|
-
}
|
|
35391
|
-
var SELECTION_IN_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
35392
|
-
"DROP_DOWN",
|
|
35393
|
-
"RADIO_BUTTON",
|
|
35394
|
-
"CHECK_BOX",
|
|
35395
|
-
"MULTI_SELECT",
|
|
35396
|
-
"STATUS"
|
|
35397
|
-
]);
|
|
35398
|
-
function isSelectionInComparison(expr, options) {
|
|
35399
|
-
if (!isSelectionInCandidate(expr, options)) return false;
|
|
35400
|
-
if (expr.left.type !== "FIELD" || expr.right.type !== "IN_LIST") return false;
|
|
35401
|
-
const fieldType = options.fieldTypes?.get(expr.left.field);
|
|
35402
|
-
if (fieldType === void 0 || !SELECTION_IN_FIELD_TYPES.has(fieldType)) return false;
|
|
35403
|
-
const validOptions = options.fieldOptions?.get(expr.left.field);
|
|
35404
|
-
if (validOptions === void 0) return false;
|
|
35405
|
-
return expr.right.values.every(
|
|
35406
|
-
(value) => value.type === "STRING" && value.value !== "" && validOptions.has(value.value)
|
|
35407
|
-
);
|
|
35408
|
-
}
|
|
35409
|
-
function isSafeIdComparison(expr, options) {
|
|
35410
|
-
if (!isTargetIdField(expr.left, options)) return false;
|
|
35411
|
-
if (expr.right.type !== "NUMBER") return false;
|
|
35412
|
-
return expr.op === "=" || expr.op === ">" || expr.op === "<" || expr.op === ">=" || expr.op === "<=";
|
|
35413
|
-
}
|
|
35414
|
-
function isTargetIdField(field, options) {
|
|
35415
|
-
if (field.type !== "FIELD" || field.field !== "$id") return false;
|
|
35416
|
-
const targetAlias = options.tableAlias ?? null;
|
|
35417
|
-
if (field.tableAlias === targetAlias) return true;
|
|
35418
|
-
return options.allowUnqualifiedFields === true && field.tableAlias === null;
|
|
35419
|
-
}
|
|
35420
|
-
function isNumericCandidate(expr, options) {
|
|
35421
|
-
if (expr.left.type !== "FIELD" || expr.left.field === "$id") return false;
|
|
35422
|
-
if (!isTargetField(expr.left, options)) return false;
|
|
35423
|
-
if (expr.right.type !== "NUMBER") return false;
|
|
35424
|
-
if (expr.op === "=") return true;
|
|
35425
|
-
return (expr.op === "<" || expr.op === ">") && Number.isSafeInteger(expr.right.value);
|
|
35426
|
-
}
|
|
35427
|
-
function isSelectionInCandidate(expr, options) {
|
|
35428
|
-
if (expr.left.type !== "FIELD" || expr.left.field === "$id") return false;
|
|
35429
|
-
if (!isTargetField(expr.left, options)) return false;
|
|
35430
|
-
if (expr.op !== "IN" && expr.op !== "NOT_IN") return false;
|
|
35431
|
-
if (expr.right.type !== "IN_LIST" || expr.right.values.length === 0) return false;
|
|
35432
|
-
return expr.right.values.every((value) => value.type === "STRING" && value.value !== "");
|
|
35433
|
-
}
|
|
35434
|
-
function isTargetField(field, options) {
|
|
35435
|
-
const targetAlias = options.tableAlias ?? null;
|
|
35436
|
-
if (field.tableAlias === targetAlias) return true;
|
|
35437
|
-
return options.allowUnqualifiedFields === true && field.tableAlias === null;
|
|
35438
|
-
}
|
|
35439
|
-
|
|
35440
35571
|
// src/engine/process.ts
|
|
35441
35572
|
function flatten(record2, alias) {
|
|
35442
35573
|
const row = {};
|
|
@@ -35501,9 +35632,9 @@ function applyJoin(leftRows, rightRows, join) {
|
|
|
35501
35632
|
}
|
|
35502
35633
|
return result;
|
|
35503
35634
|
}
|
|
35504
|
-
function applyFilter(rows, where, resolveFieldType) {
|
|
35635
|
+
function applyFilter(rows, where, resolveFieldType, appliedKlikes) {
|
|
35505
35636
|
if (where === null) return rows;
|
|
35506
|
-
return rows.filter((row) => evalWhere(where, row, resolveFieldType));
|
|
35637
|
+
return rows.filter((row) => evalWhere(where, row, resolveFieldType, appliedKlikes));
|
|
35507
35638
|
}
|
|
35508
35639
|
function hasAggregateColumns(columns) {
|
|
35509
35640
|
return columns.some(
|
|
@@ -35960,7 +36091,8 @@ function runFullScan(input) {
|
|
|
35960
36091
|
optionOrders,
|
|
35961
36092
|
sortKinds,
|
|
35962
36093
|
fieldTypeResolver,
|
|
35963
|
-
havingFieldTypeResolver
|
|
36094
|
+
havingFieldTypeResolver,
|
|
36095
|
+
appliedKlikes
|
|
35964
36096
|
} = input;
|
|
35965
36097
|
let rows = [];
|
|
35966
36098
|
const mainAlias = stmt.from.alias;
|
|
@@ -35972,7 +36104,7 @@ function runFullScan(input) {
|
|
|
35972
36104
|
const rightRows = rightRecords.map((r) => flatten(r, rightAlias));
|
|
35973
36105
|
rows = applyJoin(rows, rightRows, join);
|
|
35974
36106
|
}
|
|
35975
|
-
rows = applyFilter(rows, stmt.where, fieldTypeResolver);
|
|
36107
|
+
rows = applyFilter(rows, stmt.where, fieldTypeResolver, appliedKlikes);
|
|
35976
36108
|
if (stmt.groupBy.length > 0 || hasAggregateColumns(stmt.columns)) {
|
|
35977
36109
|
rows = applyGroupBy(rows, stmt.groupBy, stmt.columns);
|
|
35978
36110
|
}
|
|
@@ -36660,23 +36792,6 @@ async function validateSelectFieldCodes(stmt, mode, client, cacheContext) {
|
|
|
36660
36792
|
}
|
|
36661
36793
|
}
|
|
36662
36794
|
}
|
|
36663
|
-
function extractMainSafePushdown(stmt, fieldTypes, fieldOptions) {
|
|
36664
|
-
if (stmt.where === null || stmt.from.subtableCode || stmt.from.cteName !== null) return null;
|
|
36665
|
-
if (stmt.joins.length === 0) {
|
|
36666
|
-
return extractSafePushdownLeaves(stmt.where, {
|
|
36667
|
-
tableAlias: stmt.from.alias ?? void 0,
|
|
36668
|
-
allowUnqualifiedFields: true,
|
|
36669
|
-
fieldTypes,
|
|
36670
|
-
fieldOptions
|
|
36671
|
-
});
|
|
36672
|
-
}
|
|
36673
|
-
if (!stmt.from.alias) return null;
|
|
36674
|
-
return extractSafePushdownLeaves(stmt.where, {
|
|
36675
|
-
tableAlias: stmt.from.alias,
|
|
36676
|
-
fieldTypes,
|
|
36677
|
-
fieldOptions
|
|
36678
|
-
});
|
|
36679
|
-
}
|
|
36680
36795
|
function extractMainTypedPushdownCandidate(stmt) {
|
|
36681
36796
|
if (stmt.where === null || stmt.from.subtableCode || stmt.from.cteName !== null) return null;
|
|
36682
36797
|
if (stmt.joins.length === 0) {
|
|
@@ -36858,23 +36973,10 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
36858
36973
|
loadTypedInFieldTypes(stmt, client, cacheContext)
|
|
36859
36974
|
]);
|
|
36860
36975
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
36861
|
-
const
|
|
36862
|
-
|
|
36863
|
-
|
|
36864
|
-
|
|
36865
|
-
);
|
|
36866
|
-
const tableConditions = /* @__PURE__ */ new Map();
|
|
36867
|
-
if (stmt.where !== null) {
|
|
36868
|
-
for (const join of stmt.joins) {
|
|
36869
|
-
if (!join.table.alias || join.table.subtableCode || join.table.cteName !== null) continue;
|
|
36870
|
-
const cond = extractSafePushdownLeaves(stmt.where, {
|
|
36871
|
-
tableAlias: join.table.alias,
|
|
36872
|
-
fieldTypes: pushdownMeta.fieldTypesByApp.get(join.table.appId),
|
|
36873
|
-
fieldOptions: pushdownMeta.fieldOptionsByApp.get(join.table.appId)
|
|
36874
|
-
});
|
|
36875
|
-
if (cond) tableConditions.set(join.table.alias, cond);
|
|
36876
|
-
}
|
|
36877
|
-
}
|
|
36976
|
+
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
36977
|
+
validateKlikePushdownPlan(pushdownPlan);
|
|
36978
|
+
const mainPushDown = pushdownPlan.mainCondition;
|
|
36979
|
+
const tableConditions = pushdownPlan.joinConditions;
|
|
36878
36980
|
const mainFetch = fetchTableRecordsForFullScan(
|
|
36879
36981
|
stmt,
|
|
36880
36982
|
stmt.from,
|
|
@@ -36955,7 +37057,8 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
36955
37057
|
optionOrders,
|
|
36956
37058
|
sortKinds,
|
|
36957
37059
|
fieldTypeResolver: fieldTypeResolvers.row,
|
|
36958
|
-
havingFieldTypeResolver: fieldTypeResolvers.having
|
|
37060
|
+
havingFieldTypeResolver: fieldTypeResolvers.having,
|
|
37061
|
+
appliedKlikes: pushdownPlan.appliedKlikes
|
|
36959
37062
|
});
|
|
36960
37063
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
36961
37064
|
}
|
|
@@ -37004,83 +37107,6 @@ async function executeWith(stmt, client, options, cacheContext, seed) {
|
|
|
37004
37107
|
}
|
|
37005
37108
|
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext);
|
|
37006
37109
|
}
|
|
37007
|
-
function canInlineSingleCte(stmt) {
|
|
37008
|
-
if (stmt.ctes.length !== 1) return false;
|
|
37009
|
-
const cteDef = stmt.ctes[0];
|
|
37010
|
-
if (cteDef.query.type !== "SELECT") return false;
|
|
37011
|
-
if (resolveSelectMode(cteDef.query) !== "SIMPLE") return false;
|
|
37012
|
-
const finalQuery = stmt.query;
|
|
37013
|
-
if (finalQuery.type !== "SELECT") return false;
|
|
37014
|
-
if (finalQuery.from.cteName !== cteDef.name) return false;
|
|
37015
|
-
if (finalQuery.joins.length > 0) return false;
|
|
37016
|
-
if (finalQuery.groupBy.length > 0) return false;
|
|
37017
|
-
if (finalQuery.distinct) return false;
|
|
37018
|
-
if (finalQuery.columns.some(
|
|
37019
|
-
(c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL"
|
|
37020
|
-
)) return false;
|
|
37021
|
-
return true;
|
|
37022
|
-
}
|
|
37023
|
-
function buildInlinedQuery(stmt) {
|
|
37024
|
-
const cteBody = stmt.ctes[0].query;
|
|
37025
|
-
const final = stmt.query;
|
|
37026
|
-
const cteAlias = final.from.alias;
|
|
37027
|
-
const finalWhere = stripCteAlias(final.where, cteAlias);
|
|
37028
|
-
let mergedWhere;
|
|
37029
|
-
if (cteBody.where === null) mergedWhere = finalWhere;
|
|
37030
|
-
else if (finalWhere === null) mergedWhere = cteBody.where;
|
|
37031
|
-
else mergedWhere = { type: "LOGICAL", op: "AND", left: cteBody.where, right: finalWhere };
|
|
37032
|
-
const columns = final.columns.every((c) => c.type === "WILDCARD") ? cteBody.columns : final.columns;
|
|
37033
|
-
return {
|
|
37034
|
-
type: "SELECT",
|
|
37035
|
-
from: cteBody.from,
|
|
37036
|
-
joins: [],
|
|
37037
|
-
columns,
|
|
37038
|
-
where: mergedWhere,
|
|
37039
|
-
groupBy: [],
|
|
37040
|
-
having: null,
|
|
37041
|
-
orderBy: final.orderBy.length > 0 ? final.orderBy : cteBody.orderBy,
|
|
37042
|
-
limit: final.limit ?? cteBody.limit,
|
|
37043
|
-
offset: final.offset ?? cteBody.offset,
|
|
37044
|
-
distinct: false
|
|
37045
|
-
};
|
|
37046
|
-
}
|
|
37047
|
-
function stripCteAlias(where, alias) {
|
|
37048
|
-
if (where === null || alias === null) return where;
|
|
37049
|
-
switch (where.type) {
|
|
37050
|
-
case "BINARY":
|
|
37051
|
-
return {
|
|
37052
|
-
type: "BINARY",
|
|
37053
|
-
op: where.op,
|
|
37054
|
-
left: stripCteAliasFromFieldValue(where.left, alias),
|
|
37055
|
-
right: where.right
|
|
37056
|
-
};
|
|
37057
|
-
case "NULL_CHECK":
|
|
37058
|
-
return {
|
|
37059
|
-
type: "NULL_CHECK",
|
|
37060
|
-
not: where.not,
|
|
37061
|
-
field: stripCteAliasFromFieldValue(where.field, alias)
|
|
37062
|
-
};
|
|
37063
|
-
case "LOGICAL":
|
|
37064
|
-
return {
|
|
37065
|
-
type: "LOGICAL",
|
|
37066
|
-
op: where.op,
|
|
37067
|
-
left: stripCteAlias(where.left, alias),
|
|
37068
|
-
right: stripCteAlias(where.right, alias)
|
|
37069
|
-
};
|
|
37070
|
-
case "NOT":
|
|
37071
|
-
return { type: "NOT", expr: stripCteAlias(where.expr, alias) };
|
|
37072
|
-
case "GROUP":
|
|
37073
|
-
return { type: "GROUP", expr: stripCteAlias(where.expr, alias) };
|
|
37074
|
-
case "EXISTS":
|
|
37075
|
-
return where;
|
|
37076
|
-
}
|
|
37077
|
-
}
|
|
37078
|
-
function stripCteAliasFromFieldValue(fv, alias) {
|
|
37079
|
-
if (fv.type === "FIELD" && fv.tableAlias === alias) {
|
|
37080
|
-
return { type: "FIELD", field: fv.field, tableAlias: null };
|
|
37081
|
-
}
|
|
37082
|
-
return fv;
|
|
37083
|
-
}
|
|
37084
37110
|
async function executeQueryWithCte(query, client, options, cteCache, cacheContext) {
|
|
37085
37111
|
if (query.type === "UNION") {
|
|
37086
37112
|
const [leftResult, rightResult] = await Promise.all([
|
|
@@ -37115,8 +37141,13 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
37115
37141
|
resolveSubqueries(stmt.having, client, options, cacheContext, cteCache),
|
|
37116
37142
|
resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache)
|
|
37117
37143
|
]);
|
|
37118
|
-
const typedInFieldTypes = await
|
|
37144
|
+
const [pushdownMeta, typedInFieldTypes] = await Promise.all([
|
|
37145
|
+
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
37146
|
+
loadTypedInFieldTypes(stmt, client, cacheContext)
|
|
37147
|
+
]);
|
|
37119
37148
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
37149
|
+
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
37150
|
+
validateKlikePushdownPlan(pushdownPlan);
|
|
37120
37151
|
const scalarCachePromise = resolveScalarColumns(stmt.columns, client, options, cacheContext, cteCache);
|
|
37121
37152
|
const orderByMetaPromise = buildOrderByMetaForSelect(stmt, client, cacheContext);
|
|
37122
37153
|
scalarCachePromise.catch(() => {
|
|
@@ -37136,7 +37167,8 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
37136
37167
|
parallel,
|
|
37137
37168
|
true,
|
|
37138
37169
|
options.onLimitReached ?? "error",
|
|
37139
|
-
warnings
|
|
37170
|
+
warnings,
|
|
37171
|
+
pushdownPlan.mainCondition
|
|
37140
37172
|
);
|
|
37141
37173
|
tables.set(stmt.from.alias, mainRecords);
|
|
37142
37174
|
}
|
|
@@ -37145,6 +37177,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
37145
37177
|
const rows2 = cteCache.get(join.table.cteName) ?? [];
|
|
37146
37178
|
tables.set(join.table.alias, rows2.map(processRowToKintoneRecord));
|
|
37147
37179
|
} else {
|
|
37180
|
+
const pushDownCond = join.table.alias ? pushdownPlan.joinConditions.get(join.table.alias) ?? null : null;
|
|
37148
37181
|
const optimized = await tryFetchJoinRecordsBySourceKeys(
|
|
37149
37182
|
stmt,
|
|
37150
37183
|
join,
|
|
@@ -37153,7 +37186,8 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
37153
37186
|
maxRecords2,
|
|
37154
37187
|
parallel,
|
|
37155
37188
|
options.onLimitReached ?? "error",
|
|
37156
|
-
warnings
|
|
37189
|
+
warnings,
|
|
37190
|
+
pushDownCond
|
|
37157
37191
|
);
|
|
37158
37192
|
const joinRecords = optimized ?? await fetchTableRecordsForFullScan(
|
|
37159
37193
|
stmt,
|
|
@@ -37163,7 +37197,8 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
37163
37197
|
parallel,
|
|
37164
37198
|
false,
|
|
37165
37199
|
options.onLimitReached ?? "error",
|
|
37166
|
-
warnings
|
|
37200
|
+
warnings,
|
|
37201
|
+
pushDownCond
|
|
37167
37202
|
);
|
|
37168
37203
|
tables.set(join.table.alias, joinRecords);
|
|
37169
37204
|
}
|
|
@@ -37178,7 +37213,8 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
37178
37213
|
optionOrders,
|
|
37179
37214
|
sortKinds,
|
|
37180
37215
|
fieldTypeResolver: fieldTypeResolvers.row,
|
|
37181
|
-
havingFieldTypeResolver: fieldTypeResolvers.having
|
|
37216
|
+
havingFieldTypeResolver: fieldTypeResolvers.having,
|
|
37217
|
+
appliedKlikes: pushdownPlan.appliedKlikes
|
|
37182
37218
|
});
|
|
37183
37219
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
37184
37220
|
}
|
|
@@ -38387,9 +38423,10 @@ function buildSelectPlan(stmt, label) {
|
|
|
38387
38423
|
lines.push(` kintone query: ${params.query || "(\u306A\u3057)"}`);
|
|
38388
38424
|
lines.push(` fields: ${params.fields.length === 0 ? "(\u5168\u30D5\u30A3\u30FC\u30EB\u30C9)" : params.fields.join(", ")}`);
|
|
38389
38425
|
} else {
|
|
38426
|
+
const pushdownPlan = buildKlikePushdownPlan(stmt);
|
|
38390
38427
|
const mainFields = selectToFetchAllFields(stmt, stmt.from);
|
|
38391
38428
|
const mainAliasStr = stmt.from.alias ? ` AS ${stmt.from.alias}` : "";
|
|
38392
|
-
const mainPushDown =
|
|
38429
|
+
const mainPushDown = pushdownPlan.mainCondition;
|
|
38393
38430
|
const mainCandidate = extractMainTypedPushdownCandidate(stmt);
|
|
38394
38431
|
const mainQ = mainPushDown !== null ? whereToKintone(mainPushDown) : "(\u5168\u4EF6\u53D6\u5F97)";
|
|
38395
38432
|
lines.push(` app: APP${stmt.from.appId}${mainAliasStr} (${stmt.from.appId})`);
|
|
@@ -38402,7 +38439,7 @@ function buildSelectPlan(stmt, label) {
|
|
|
38402
38439
|
const joinFields = selectToFetchAllFields(stmt, join.table);
|
|
38403
38440
|
const joinAliasStr = join.table.alias ? ` AS ${join.table.alias}` : "";
|
|
38404
38441
|
const joinType = join.type === "INNER" ? "JOIN" : `${join.type} JOIN`;
|
|
38405
|
-
const joinPushDown = join.table.alias
|
|
38442
|
+
const joinPushDown = join.table.alias ? pushdownPlan.joinConditions.get(join.table.alias) ?? null : null;
|
|
38406
38443
|
const joinCandidate = join.table.alias && !join.table.subtableCode && join.table.cteName === null && stmt.where ? extractTypedPushdownCandidates(stmt.where, { tableAlias: join.table.alias }) : null;
|
|
38407
38444
|
const joinQ = joinPushDown !== null ? whereToKintone(joinPushDown) : "(\u5168\u4EF6\u53D6\u5F97)";
|
|
38408
38445
|
lines.push(` ${joinType}: APP${join.table.appId}${joinAliasStr} (${join.table.appId})`);
|
|
@@ -38445,6 +38482,10 @@ function buildWithPlan(stmt) {
|
|
|
38445
38482
|
if (stmt.query.type === "SELECT" || stmt.query.type === "UNION") {
|
|
38446
38483
|
lines.push(...buildExplainPlan(stmt.query, "[main]"));
|
|
38447
38484
|
}
|
|
38485
|
+
if (canInlineSingleCte(stmt)) {
|
|
38486
|
+
lines.push("");
|
|
38487
|
+
lines.push(...buildSelectPlan(buildInlinedQuery(stmt), "[effective: inlined CTE]"));
|
|
38488
|
+
}
|
|
38448
38489
|
return lines;
|
|
38449
38490
|
}
|
|
38450
38491
|
function collectFullScanReasons(stmt) {
|
|
@@ -40781,7 +40822,7 @@ Options:
|
|
|
40781
40822
|
-h, --help Show help
|
|
40782
40823
|
`);
|
|
40783
40824
|
}
|
|
40784
|
-
var SERVER_VERSION = true ? "2.
|
|
40825
|
+
var SERVER_VERSION = true ? "2.9.0" : "0.0.0-dev";
|
|
40785
40826
|
function createServer(args) {
|
|
40786
40827
|
const server = new McpServer({
|
|
40787
40828
|
name: "ksql-mcp",
|