@rex0220/kintone-sql-tools 3.39.0 → 3.40.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 +282 -33
- package/dist-engine/index.cjs +12 -12
- package/dist-engine/index.mjs +12 -12
- package/dist-engine/ksql-engine.umd.js +12 -12
- package/dist-engine/meta/bundle-baseline.json +7 -7
- package/dist-engine/meta/cjs.json +5 -5
- package/dist-engine/meta/esm.json +5 -5
- package/dist-engine/meta/umd.json +5 -5
- package/dist-engine/publicTypes.d.ts +15 -0
- package/dist-mcp/ksql-mcp.js +284 -35
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -22768,6 +22768,10 @@ function serverFunctionClientEvaluationLabel(leaves) {
|
|
|
22768
22768
|
(leaf) => leaf.right.type === "KINTONE_FUNC" && isRelativeDateFunctionName(leaf.right.name)
|
|
22769
22769
|
) ? "relative date client evaluations" : "kintone function client evaluations";
|
|
22770
22770
|
}
|
|
22771
|
+
var EXPLAIN_FETCH_PLAN = /* @__PURE__ */ Symbol("ksql.explainFetchPlan");
|
|
22772
|
+
function setExplainFetchPlan(result, plan) {
|
|
22773
|
+
result[EXPLAIN_FETCH_PLAN] = plan;
|
|
22774
|
+
}
|
|
22771
22775
|
async function buildBatchExplainPlans(sql, client, injectedVariables, cacheContext = "batch-explain", maxRecords = 1e4, cursorMaxActive = 2, enableImport = false, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS) {
|
|
22772
22776
|
const invocationCacheContext = createInvocationCacheContext(cacheContext);
|
|
22773
22777
|
try {
|
|
@@ -22777,6 +22781,7 @@ async function buildBatchExplainPlans(sql, client, injectedVariables, cacheConte
|
|
|
22777
22781
|
const relativeDateVariables = prepareRelativeDateVariables(statements, normalizedInjectedVariables);
|
|
22778
22782
|
const variables = /* @__PURE__ */ new Map();
|
|
22779
22783
|
const plans = [];
|
|
22784
|
+
const fetchStatements = [];
|
|
22780
22785
|
for (let i = 0; i < statements.length; i++) {
|
|
22781
22786
|
const stmt = statements[i];
|
|
22782
22787
|
const planStmt = stmt.type === "SET_VARIABLE" ? stmt.expr.type === "SCALAR_SUBQUERY" ? { ...stmt, expr: resolveBatchVariableReferences(stmt.expr, variables) } : stmt : resolveBatchVariableReferences(stmt, variables);
|
|
@@ -22789,6 +22794,7 @@ async function buildBatchExplainPlans(sql, client, injectedVariables, cacheConte
|
|
|
22789
22794
|
maxRecords,
|
|
22790
22795
|
relativeDatePlan
|
|
22791
22796
|
);
|
|
22797
|
+
const fetchCollector = { sources: [] };
|
|
22792
22798
|
const statementPlan = relativeDatePlan.hasServerOnlyWhereFunction && !relativeDatePlan.allowed ? relativeDateExplainLines(relativeDatePlan) : [
|
|
22793
22799
|
...relativeDateExplainLines(relativeDatePlan),
|
|
22794
22800
|
...addCursorConcurrency(buildBatchStatementPlan(
|
|
@@ -22797,7 +22803,8 @@ async function buildBatchExplainPlans(sql, client, injectedVariables, cacheConte
|
|
|
22797
22803
|
whereAnalysis.capabilities,
|
|
22798
22804
|
whereAnalysis.orderPlans,
|
|
22799
22805
|
dmlMaxRows,
|
|
22800
|
-
dmlMaxSubtableRows
|
|
22806
|
+
dmlMaxSubtableRows,
|
|
22807
|
+
fetchCollector
|
|
22801
22808
|
), cursorMaxActive)
|
|
22802
22809
|
];
|
|
22803
22810
|
const metadataPlan = explainMetadataLines(whereAnalysis);
|
|
@@ -22806,22 +22813,36 @@ async function buildBatchExplainPlans(sql, client, injectedVariables, cacheConte
|
|
|
22806
22813
|
type: analysis.statements[i].statementType,
|
|
22807
22814
|
plan: statementPlan.length === 0 ? metadataPlan : [statementPlan[0], ...metadataPlan, ...statementPlan.slice(1)]
|
|
22808
22815
|
});
|
|
22816
|
+
fetchStatements.push({
|
|
22817
|
+
index: i,
|
|
22818
|
+
fetch: worstExplainFetch(fetchCollector.sources),
|
|
22819
|
+
sources: fetchCollector.sources
|
|
22820
|
+
});
|
|
22809
22821
|
if (stmt.type === "SET_VARIABLE" || stmt.type === "DECLARE_VARIABLE") {
|
|
22810
22822
|
variables.set(stmt.name, stmt.type === "DECLARE_VARIABLE" && stmt.annotation === "RELATIVE_DATE" ? { type: "relative-date", value: relativeDateVariables.get(stmt.name) } : stmt.type === "SET_VARIABLE" && stmt.expr.type === "ARRAY" ? { type: "array", elements: stmt.expr.elements.map((element) => ({ type: "string", value: element.value })) } : { type: "string", value: `@${stmt.name}`, placeholder: true });
|
|
22811
22823
|
}
|
|
22812
22824
|
}
|
|
22813
|
-
|
|
22825
|
+
const result = { statementCount: statements.length, statements: plans };
|
|
22826
|
+
setExplainFetchPlan(result, { statements: fetchStatements });
|
|
22827
|
+
return result;
|
|
22814
22828
|
} finally {
|
|
22815
22829
|
releaseMetadataCacheScope(invocationCacheContext);
|
|
22816
22830
|
}
|
|
22817
22831
|
}
|
|
22818
|
-
function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS) {
|
|
22832
|
+
function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, collector = { sources: [] }) {
|
|
22819
22833
|
if (stmt.type === "CREATE_TEMP_TABLE") {
|
|
22820
22834
|
return [
|
|
22821
22835
|
`CREATE TEMP TABLE ${stmt.name}`,
|
|
22822
22836
|
` scope: batch\uFF08\u30D0\u30C3\u30C1\u7D42\u4E86\u6642\u306B\u81EA\u52D5\u7834\u68C4\uFF09`,
|
|
22823
22837
|
` rows: \u5B9F\u4F53\u5316\u524D\u306E\u305F\u3081\u4E0D\u660E\uFF08\u65E2\u5B9A\u4E0A\u9650 ${TEMP_TABLE_MAX_ROWS} \u884C\u3001tempTableMaxRows \u3067\u5909\u66F4\u53EF\u3001\u8D85\u904E\u306F\u30A8\u30E9\u30FC\uFF09`,
|
|
22824
|
-
...buildPlanForBatchQuery(
|
|
22838
|
+
...buildPlanForBatchQuery(
|
|
22839
|
+
stmt.query,
|
|
22840
|
+
info,
|
|
22841
|
+
capabilities,
|
|
22842
|
+
orderPlans,
|
|
22843
|
+
collector,
|
|
22844
|
+
"main"
|
|
22845
|
+
).map((l) => ` ${l}`)
|
|
22825
22846
|
];
|
|
22826
22847
|
}
|
|
22827
22848
|
if (stmt.type === "DROP_TEMP_TABLE") {
|
|
@@ -22837,7 +22858,13 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, dmlMaxRow
|
|
|
22837
22858
|
`SET @${stmt.name} = (SELECT ...)`,
|
|
22838
22859
|
" value: \u30B5\u30D6\u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u6642\u306B1\u56DE\u8A55\u4FA1\uFF081\u884C1\u5217\u30FB\u30D0\u30C3\u30C1\u5185\u5B9A\u6570\u30FB\u7D50\u679C\u30E1\u30BF\u30C7\u30FC\u30BF\u306B\u306F\u975E\u516C\u958B\uFF09",
|
|
22839
22860
|
" subquery:",
|
|
22840
|
-
...buildPlanForBatchQuery(
|
|
22861
|
+
...buildPlanForBatchQuery(
|
|
22862
|
+
stmt.expr.query,
|
|
22863
|
+
subInfo,
|
|
22864
|
+
capabilities,
|
|
22865
|
+
orderPlans,
|
|
22866
|
+
collector
|
|
22867
|
+
).map((l) => ` ${l}`)
|
|
22841
22868
|
];
|
|
22842
22869
|
}
|
|
22843
22870
|
return [
|
|
@@ -22859,7 +22886,15 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, dmlMaxRow
|
|
|
22859
22886
|
}
|
|
22860
22887
|
if (stmt.type === "SHOW_APPS") return ["SHOW APPS\uFF08\u30A2\u30D7\u30EA\u4E00\u89A7\u306E\u53D6\u5F97\uFF09"];
|
|
22861
22888
|
if (stmt.type === "DESCRIBE") return [`DESCRIBE APP${stmt.appId}\uFF08\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u306E\u53D6\u5F97\uFF09`];
|
|
22862
|
-
if (stmt.type === "EXPLAIN")
|
|
22889
|
+
if (stmt.type === "EXPLAIN") {
|
|
22890
|
+
return buildPlanForBatchQuery(
|
|
22891
|
+
stmt.query,
|
|
22892
|
+
info,
|
|
22893
|
+
capabilities,
|
|
22894
|
+
orderPlans,
|
|
22895
|
+
collector
|
|
22896
|
+
);
|
|
22897
|
+
}
|
|
22863
22898
|
if (stmt.type === "ASSERT") {
|
|
22864
22899
|
const lines = [
|
|
22865
22900
|
`ASSERT ${stmt.text}`,
|
|
@@ -22871,14 +22906,20 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, dmlMaxRow
|
|
|
22871
22906
|
subqueries.forEach((sq, i) => {
|
|
22872
22907
|
lines.push(subqueries.length > 1 ? ` subquery[${i + 1}]:` : " subquery:");
|
|
22873
22908
|
const subInfo = hasTempTableRef(sq.query) ? info : { ...info, tempTablesReferenced: [] };
|
|
22874
|
-
lines.push(...buildPlanForBatchQuery(
|
|
22909
|
+
lines.push(...buildPlanForBatchQuery(
|
|
22910
|
+
sq.query,
|
|
22911
|
+
subInfo,
|
|
22912
|
+
capabilities,
|
|
22913
|
+
orderPlans,
|
|
22914
|
+
collector
|
|
22915
|
+
).map((l) => ` ${l}`));
|
|
22875
22916
|
});
|
|
22876
22917
|
return lines;
|
|
22877
22918
|
}
|
|
22878
22919
|
if (stmt.type === "UPDATE" && (stmt.applyBlocks?.length ?? 0) > 0) {
|
|
22879
22920
|
return buildExplainPlan(stmt, void 0, capabilities, orderPlans, dmlMaxRows, dmlMaxSubtableRows);
|
|
22880
22921
|
}
|
|
22881
|
-
return buildPlanForBatchQuery(stmt, info, capabilities, orderPlans);
|
|
22922
|
+
return buildPlanForBatchQuery(stmt, info, capabilities, orderPlans, collector);
|
|
22882
22923
|
}
|
|
22883
22924
|
function hasTempTableRef(node) {
|
|
22884
22925
|
if (Array.isArray(node)) return node.some(hasTempTableRef);
|
|
@@ -22890,9 +22931,21 @@ function hasTempTableRef(node) {
|
|
|
22890
22931
|
}
|
|
22891
22932
|
return false;
|
|
22892
22933
|
}
|
|
22893
|
-
function buildPlanForBatchQuery(query, info, capabilities, orderPlans) {
|
|
22934
|
+
function buildPlanForBatchQuery(query, info, capabilities, orderPlans, collector = { sources: [] }, sourceRole = "main") {
|
|
22894
22935
|
if (info.tempTablesReferenced.length === 0) {
|
|
22895
|
-
return buildExplainPlan(
|
|
22936
|
+
return buildExplainPlan(
|
|
22937
|
+
query,
|
|
22938
|
+
void 0,
|
|
22939
|
+
capabilities,
|
|
22940
|
+
orderPlans,
|
|
22941
|
+
100,
|
|
22942
|
+
DEFAULT_APPLY_MAX_SUBTABLE_ROWS,
|
|
22943
|
+
1e4,
|
|
22944
|
+
void 0,
|
|
22945
|
+
true,
|
|
22946
|
+
collector,
|
|
22947
|
+
sourceRole
|
|
22948
|
+
);
|
|
22896
22949
|
}
|
|
22897
22950
|
const lines = [];
|
|
22898
22951
|
if (query.type === "INSERT_SELECT") {
|
|
@@ -22926,8 +22979,9 @@ async function executeExplain(stmt, client, cacheContext, maxRecords, cursorMaxA
|
|
|
22926
22979
|
maxRecords,
|
|
22927
22980
|
sharedPlan
|
|
22928
22981
|
);
|
|
22982
|
+
const fetchCollector = { sources: [] };
|
|
22929
22983
|
const relativeLines = relativeDateExplainLines(sharedPlan);
|
|
22930
|
-
const
|
|
22984
|
+
const planLines = sharedPlan.hasServerOnlyWhereFunction && !sharedPlan.allowed ? [...explainMetadataLines(analysis), ...relativeLines] : [
|
|
22931
22985
|
...explainMetadataLines(analysis),
|
|
22932
22986
|
...relativeLines,
|
|
22933
22987
|
...addCursorConcurrency(
|
|
@@ -22939,17 +22993,28 @@ async function executeExplain(stmt, client, cacheContext, maxRecords, cursorMaxA
|
|
|
22939
22993
|
dmlMaxRows,
|
|
22940
22994
|
dmlMaxSubtableRows,
|
|
22941
22995
|
maxRecords,
|
|
22942
|
-
analysis.plainGroupByPlans
|
|
22996
|
+
analysis.plainGroupByPlans,
|
|
22997
|
+
true,
|
|
22998
|
+
fetchCollector
|
|
22943
22999
|
),
|
|
22944
23000
|
cursorMaxActive
|
|
22945
23001
|
)
|
|
22946
23002
|
];
|
|
22947
|
-
|
|
23003
|
+
const lines = addFetchSummary(planLines, fetchCollector.sources);
|
|
23004
|
+
const result = {
|
|
22948
23005
|
type: "SELECT",
|
|
22949
23006
|
columns: ["plan"],
|
|
22950
23007
|
rows: lines.map((line) => ({ plan: line })),
|
|
22951
23008
|
rowCount: lines.length
|
|
22952
23009
|
};
|
|
23010
|
+
setExplainFetchPlan(result, {
|
|
23011
|
+
statements: [{
|
|
23012
|
+
index: 0,
|
|
23013
|
+
fetch: worstExplainFetch(fetchCollector.sources),
|
|
23014
|
+
sources: fetchCollector.sources
|
|
23015
|
+
}]
|
|
23016
|
+
});
|
|
23017
|
+
return result;
|
|
22953
23018
|
}
|
|
22954
23019
|
function addCursorConcurrency(lines, cursorMaxActive) {
|
|
22955
23020
|
const result = [];
|
|
@@ -22962,9 +23027,28 @@ function addCursorConcurrency(lines, cursorMaxActive) {
|
|
|
22962
23027
|
}
|
|
22963
23028
|
return result;
|
|
22964
23029
|
}
|
|
22965
|
-
function buildExplainPlan(query, label, capabilities, orderPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, maxRecords = 1e4, plainGroupByPlans) {
|
|
22966
|
-
|
|
22967
|
-
if (query.type === "
|
|
23030
|
+
function buildExplainPlan(query, label, capabilities, orderPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, maxRecords = 1e4, plainGroupByPlans, includeFetchSummary = true, collector, sourceRole = "main") {
|
|
23031
|
+
const fetchCollector = collector ?? { sources: [] };
|
|
23032
|
+
if (query.type === "UNION") {
|
|
23033
|
+
const lines2 = buildUnionPlan(
|
|
23034
|
+
query,
|
|
23035
|
+
capabilities,
|
|
23036
|
+
orderPlans,
|
|
23037
|
+
plainGroupByPlans,
|
|
23038
|
+
fetchCollector
|
|
23039
|
+
);
|
|
23040
|
+
return includeFetchSummary ? addFetchSummary(lines2, fetchCollector.sources) : lines2;
|
|
23041
|
+
}
|
|
23042
|
+
if (query.type === "WITH") {
|
|
23043
|
+
const lines2 = buildWithPlan(
|
|
23044
|
+
query,
|
|
23045
|
+
capabilities,
|
|
23046
|
+
orderPlans,
|
|
23047
|
+
plainGroupByPlans,
|
|
23048
|
+
fetchCollector
|
|
23049
|
+
);
|
|
23050
|
+
return includeFetchSummary ? addFetchSummary(lines2, fetchCollector.sources) : lines2;
|
|
23051
|
+
}
|
|
22968
23052
|
if (query.type === "INSERT") return buildInsertPlan(query, label, dmlMaxRows, dmlMaxSubtableRows);
|
|
22969
23053
|
if (query.type === "INSERT_SELECT") return buildInsertSelectPlan(query, label, capabilities, orderPlans, plainGroupByPlans);
|
|
22970
23054
|
if (query.type === "UPSERT") return buildUpsertPlan(query, label, dmlMaxRows, dmlMaxSubtableRows);
|
|
@@ -23054,7 +23138,62 @@ function buildExplainPlan(query, label, capabilities, orderPlans, dmlMaxRows = 1
|
|
|
23054
23138
|
` duplicateKey: preflight before lookup/write (requires load)`
|
|
23055
23139
|
];
|
|
23056
23140
|
}
|
|
23057
|
-
|
|
23141
|
+
const lines = buildSelectPlan(
|
|
23142
|
+
query,
|
|
23143
|
+
label,
|
|
23144
|
+
capabilities,
|
|
23145
|
+
orderPlans,
|
|
23146
|
+
plainGroupByPlans,
|
|
23147
|
+
true,
|
|
23148
|
+
true,
|
|
23149
|
+
fetchCollector,
|
|
23150
|
+
sourceRole
|
|
23151
|
+
);
|
|
23152
|
+
return includeFetchSummary ? addFetchSummary(lines, fetchCollector.sources) : lines;
|
|
23153
|
+
}
|
|
23154
|
+
var EXPLAIN_FETCH_VALUE_RANK = {
|
|
23155
|
+
none: 0,
|
|
23156
|
+
exact: 1,
|
|
23157
|
+
prefiltered: 2,
|
|
23158
|
+
all: 3
|
|
23159
|
+
};
|
|
23160
|
+
function worstExplainFetch(sources) {
|
|
23161
|
+
return sources.reduce(
|
|
23162
|
+
(worst, source) => EXPLAIN_FETCH_VALUE_RANK[worst] >= EXPLAIN_FETCH_VALUE_RANK[source.fetch] ? worst : source.fetch,
|
|
23163
|
+
"none"
|
|
23164
|
+
);
|
|
23165
|
+
}
|
|
23166
|
+
function addFetchSummary(lines, sources) {
|
|
23167
|
+
const detailLines = lines.filter((line) => !line.startsWith("fetch summary:"));
|
|
23168
|
+
if (sources.length === 0) return detailLines;
|
|
23169
|
+
return [`fetch summary: ${worstExplainFetch(sources).toUpperCase()}`, ...detailLines];
|
|
23170
|
+
}
|
|
23171
|
+
function pushedQueryLimit(query) {
|
|
23172
|
+
const match = /(?:^|\s)limit\s+(\d+)(?:\s|$)/i.exec(query);
|
|
23173
|
+
return match ? Number(match[1]) : null;
|
|
23174
|
+
}
|
|
23175
|
+
function createExplainFetchSource(collector, app, alias, role, scope, query, pending = false) {
|
|
23176
|
+
const source = {
|
|
23177
|
+
app,
|
|
23178
|
+
alias,
|
|
23179
|
+
role,
|
|
23180
|
+
fetch: scope.toLowerCase(),
|
|
23181
|
+
pending,
|
|
23182
|
+
kintoneQuery: query === "(\u5168\u4EF6\u53D6\u5F97)" || query === "(\u306A\u3057)" || query === "" ? null : query,
|
|
23183
|
+
limit: pushedQueryLimit(query)
|
|
23184
|
+
};
|
|
23185
|
+
collector.sources.push(source);
|
|
23186
|
+
return source;
|
|
23187
|
+
}
|
|
23188
|
+
function formatFetchScope(source) {
|
|
23189
|
+
return [
|
|
23190
|
+
source.fetch.toUpperCase(),
|
|
23191
|
+
...source.limit === null ? [] : [`(limit ${source.limit})`],
|
|
23192
|
+
...source.pending ? ["(\u672A\u78BA\u5B9A)"] : []
|
|
23193
|
+
].join(" ");
|
|
23194
|
+
}
|
|
23195
|
+
function renderFetchScope(source) {
|
|
23196
|
+
return ` fetch: ${formatFetchScope(source)}`;
|
|
23058
23197
|
}
|
|
23059
23198
|
function buildValidatePlan(stmt, label) {
|
|
23060
23199
|
const info = validateExplainInfo.get(stmt);
|
|
@@ -23081,7 +23220,7 @@ function buildValidatePlan(stmt, label) {
|
|
|
23081
23220
|
lines.push(" records/mutation API during EXPLAIN: none; violation count unavailable");
|
|
23082
23221
|
return lines;
|
|
23083
23222
|
}
|
|
23084
|
-
function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlans, allowTotalCountPlan = true) {
|
|
23223
|
+
function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlans, allowTotalCountPlan = true, emitFetch = true, collector = { sources: [] }, sourceRole = "main") {
|
|
23085
23224
|
const whereCapability = capabilities?.get(stmt) ?? (capabilities ? [...capabilities].find(([candidate]) => JSON.stringify(candidate) === JSON.stringify(stmt))?.[1] : void 0);
|
|
23086
23225
|
const orderPlan = orderPlans?.get(stmt) ?? (orderPlans ? [...orderPlans].find(([candidate]) => JSON.stringify(candidate) === JSON.stringify(stmt))?.[1] : void 0);
|
|
23087
23226
|
const plainGroupByPlan = plainGroupByPlans?.get(stmt) ?? (plainGroupByPlans ? [...plainGroupByPlans].find(([candidate]) => JSON.stringify(candidate) === JSON.stringify(stmt))?.[1] : void 0);
|
|
@@ -23139,6 +23278,17 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlan
|
|
|
23139
23278
|
lines.push(
|
|
23140
23279
|
` kintone query: ${baseQuery}${baseQuery ? " " : ""}limit 1`
|
|
23141
23280
|
);
|
|
23281
|
+
if (emitFetch) {
|
|
23282
|
+
const source = createExplainFetchSource(
|
|
23283
|
+
collector,
|
|
23284
|
+
stmt.from.appId,
|
|
23285
|
+
stmt.from.alias,
|
|
23286
|
+
sourceRole,
|
|
23287
|
+
"NONE",
|
|
23288
|
+
`${baseQuery}${baseQuery ? " " : ""}limit 1`
|
|
23289
|
+
);
|
|
23290
|
+
lines.push(renderFetchScope(source));
|
|
23291
|
+
}
|
|
23142
23292
|
lines.push(" fields: $id");
|
|
23143
23293
|
lines.push(" fetch API: GET records.json (totalCount=true)");
|
|
23144
23294
|
lines.push(" REST execution: single GET");
|
|
@@ -23185,6 +23335,17 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlan
|
|
|
23185
23335
|
lines.push(` app: APP${stmt.from.appId} (${stmt.from.appId})`);
|
|
23186
23336
|
const displayedQuery = orderPlan?.kind === "KORDER_CURSOR" ? buildKorderCursorQuery(stmt) : params.query;
|
|
23187
23337
|
lines.push(` kintone query: ${displayedQuery || "(\u306A\u3057)"}`);
|
|
23338
|
+
if (emitFetch && stmt.from.cteName === null) {
|
|
23339
|
+
const fetchScope = displayedQuery ? "EXACT" : "ALL";
|
|
23340
|
+
lines.push(renderFetchScope(createExplainFetchSource(
|
|
23341
|
+
collector,
|
|
23342
|
+
stmt.from.appId,
|
|
23343
|
+
stmt.from.alias,
|
|
23344
|
+
sourceRole,
|
|
23345
|
+
fetchScope,
|
|
23346
|
+
displayedQuery
|
|
23347
|
+
)));
|
|
23348
|
+
}
|
|
23188
23349
|
lines.push(` fields: ${params.fields.length === 0 ? "(\u5168\u30D5\u30A3\u30FC\u30EB\u30C9)" : params.fields.join(", ")}`);
|
|
23189
23350
|
} else {
|
|
23190
23351
|
const runtimeJoinPlan = explainJoinPushdownPlans.get(stmt);
|
|
@@ -23234,6 +23395,19 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlan
|
|
|
23234
23395
|
const mainFunctionConsumption = runtimeJoinPlan?.joinPlan.serverFunctionConsumptions.find(
|
|
23235
23396
|
(consumption) => consumption.targetAlias === stmt.from.alias
|
|
23236
23397
|
);
|
|
23398
|
+
if (emitFetch && stmt.from.cteName === null) {
|
|
23399
|
+
const mainPending = !runtimeJoinPlan && mainCandidate !== null;
|
|
23400
|
+
const mainFetchScope = mainQ === "(\u5168\u4EF6\u53D6\u5F97)" ? "ALL" : mainPending ? "PREFILTERED" : mainJoinItem?.relation === "exact" || mainFunctionConsumption || exactOriginalWhere !== "" ? "EXACT" : "PREFILTERED";
|
|
23401
|
+
lines.push(renderFetchScope(createExplainFetchSource(
|
|
23402
|
+
collector,
|
|
23403
|
+
stmt.from.appId,
|
|
23404
|
+
stmt.from.alias,
|
|
23405
|
+
sourceRole,
|
|
23406
|
+
mainFetchScope,
|
|
23407
|
+
mainQ,
|
|
23408
|
+
mainPending
|
|
23409
|
+
)));
|
|
23410
|
+
}
|
|
23237
23411
|
if (mainJoinItem || mainFunctionConsumption) {
|
|
23238
23412
|
lines.push(` pushdown applied: ${mainBoundQuery}`);
|
|
23239
23413
|
lines.push(` relation: ${mainJoinItem?.relation ?? "exact"}`);
|
|
@@ -23257,6 +23431,19 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlan
|
|
|
23257
23431
|
const joinFunctionConsumption = runtimeJoinPlan?.joinPlan.serverFunctionConsumptions.find(
|
|
23258
23432
|
(consumption) => consumption.targetAlias === join2.table.alias
|
|
23259
23433
|
);
|
|
23434
|
+
if (emitFetch && join2.table.cteName === null) {
|
|
23435
|
+
const joinPending = !runtimeJoinPlan && joinCandidate !== null;
|
|
23436
|
+
const joinFetchScope = joinQ === "(\u5168\u4EF6\u53D6\u5F97)" ? "ALL" : joinPending ? "PREFILTERED" : joinPlanItem?.relation === "exact" || joinFunctionConsumption ? "EXACT" : "PREFILTERED";
|
|
23437
|
+
lines.push(renderFetchScope(createExplainFetchSource(
|
|
23438
|
+
collector,
|
|
23439
|
+
join2.table.appId,
|
|
23440
|
+
join2.table.alias,
|
|
23441
|
+
"join",
|
|
23442
|
+
joinFetchScope,
|
|
23443
|
+
joinQ,
|
|
23444
|
+
joinPending
|
|
23445
|
+
)));
|
|
23446
|
+
}
|
|
23260
23447
|
if (joinPlanItem || joinFunctionConsumption) {
|
|
23261
23448
|
lines.push(` pushdown applied: ${joinBoundQuery}`);
|
|
23262
23449
|
lines.push(` relation: ${joinPlanItem?.relation ?? "exact"}`);
|
|
@@ -23266,10 +23453,16 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlan
|
|
|
23266
23453
|
lines.push(` fields: ${joinFields.length === 0 ? "(\u5168\u30D5\u30A3\u30FC\u30EB\u30C9)" : joinFields.join(", ")}`);
|
|
23267
23454
|
}
|
|
23268
23455
|
}
|
|
23269
|
-
lines.push(...collectSubqueryPlans(
|
|
23456
|
+
lines.push(...collectSubqueryPlans(
|
|
23457
|
+
stmt,
|
|
23458
|
+
capabilities,
|
|
23459
|
+
orderPlans,
|
|
23460
|
+
plainGroupByPlans,
|
|
23461
|
+
collector
|
|
23462
|
+
));
|
|
23270
23463
|
return lines;
|
|
23271
23464
|
}
|
|
23272
|
-
function buildUnionPlan(stmt, capabilities, orderPlans, plainGroupByPlans) {
|
|
23465
|
+
function buildUnionPlan(stmt, capabilities, orderPlans, plainGroupByPlans, collector = { sources: [] }) {
|
|
23273
23466
|
const selects = [];
|
|
23274
23467
|
const collect = (u) => {
|
|
23275
23468
|
if (u.type === "SELECT") {
|
|
@@ -23283,15 +23476,35 @@ function buildUnionPlan(stmt, capabilities, orderPlans, plainGroupByPlans) {
|
|
|
23283
23476
|
const lines = [];
|
|
23284
23477
|
selects.forEach((sel, i) => {
|
|
23285
23478
|
if (i > 0) lines.push("");
|
|
23286
|
-
lines.push(...buildSelectPlan(
|
|
23479
|
+
lines.push(...buildSelectPlan(
|
|
23480
|
+
sel,
|
|
23481
|
+
`[union:${i + 1}]`,
|
|
23482
|
+
capabilities,
|
|
23483
|
+
orderPlans,
|
|
23484
|
+
plainGroupByPlans,
|
|
23485
|
+
true,
|
|
23486
|
+
true,
|
|
23487
|
+
collector,
|
|
23488
|
+
"union"
|
|
23489
|
+
));
|
|
23287
23490
|
});
|
|
23288
23491
|
return lines;
|
|
23289
23492
|
}
|
|
23290
|
-
function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans) {
|
|
23493
|
+
function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans, collector = { sources: [] }) {
|
|
23291
23494
|
const lines = [];
|
|
23292
23495
|
for (const cte of stmt.ctes) {
|
|
23293
23496
|
if (cte.query.type === "SELECT") {
|
|
23294
|
-
lines.push(...buildSelectPlan(
|
|
23497
|
+
lines.push(...buildSelectPlan(
|
|
23498
|
+
cte.query,
|
|
23499
|
+
`[cte: ${cte.name}]`,
|
|
23500
|
+
capabilities,
|
|
23501
|
+
orderPlans,
|
|
23502
|
+
plainGroupByPlans,
|
|
23503
|
+
false,
|
|
23504
|
+
true,
|
|
23505
|
+
collector,
|
|
23506
|
+
"cte"
|
|
23507
|
+
));
|
|
23295
23508
|
lines.push("");
|
|
23296
23509
|
}
|
|
23297
23510
|
}
|
|
@@ -23304,13 +23517,25 @@ function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans) {
|
|
|
23304
23517
|
100,
|
|
23305
23518
|
DEFAULT_APPLY_MAX_SUBTABLE_ROWS,
|
|
23306
23519
|
1e4,
|
|
23307
|
-
plainGroupByPlans
|
|
23520
|
+
plainGroupByPlans,
|
|
23521
|
+
false,
|
|
23522
|
+
collector
|
|
23308
23523
|
));
|
|
23309
23524
|
}
|
|
23310
23525
|
if (canInlineSingleCte(stmt)) {
|
|
23311
23526
|
lines.push("");
|
|
23312
23527
|
const inlined = buildInlinedQuery(stmt);
|
|
23313
|
-
lines.push(...buildSelectPlan(
|
|
23528
|
+
lines.push(...buildSelectPlan(
|
|
23529
|
+
inlined,
|
|
23530
|
+
"[effective: inlined CTE]",
|
|
23531
|
+
capabilities,
|
|
23532
|
+
orderPlans,
|
|
23533
|
+
plainGroupByPlans,
|
|
23534
|
+
false,
|
|
23535
|
+
true,
|
|
23536
|
+
collector,
|
|
23537
|
+
"cte"
|
|
23538
|
+
));
|
|
23314
23539
|
}
|
|
23315
23540
|
return lines;
|
|
23316
23541
|
}
|
|
@@ -23343,7 +23568,7 @@ function collectFullScanReasons(stmt) {
|
|
|
23343
23568
|
r.push("ORDER BY \u306B\u5F0F");
|
|
23344
23569
|
return r;
|
|
23345
23570
|
}
|
|
23346
|
-
function collectSubqueryPlans(stmt, capabilities, orderPlans, plainGroupByPlans) {
|
|
23571
|
+
function collectSubqueryPlans(stmt, capabilities, orderPlans, plainGroupByPlans, collector = { sources: [] }) {
|
|
23347
23572
|
const lines = [];
|
|
23348
23573
|
let idx = 1;
|
|
23349
23574
|
const visitWhere = (w) => {
|
|
@@ -23352,16 +23577,16 @@ function collectSubqueryPlans(stmt, capabilities, orderPlans, plainGroupByPlans)
|
|
|
23352
23577
|
case "BINARY":
|
|
23353
23578
|
if (w.right.type === "SCALAR_SUBQUERY") {
|
|
23354
23579
|
lines.push("");
|
|
23355
|
-
lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
|
|
23580
|
+
lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false, true, collector, "subquery"));
|
|
23356
23581
|
}
|
|
23357
23582
|
if (w.right.type === "SUBQUERY_IN_LIST") {
|
|
23358
23583
|
lines.push("");
|
|
23359
|
-
lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
|
|
23584
|
+
lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false, true, collector, "subquery"));
|
|
23360
23585
|
}
|
|
23361
23586
|
break;
|
|
23362
23587
|
case "EXISTS":
|
|
23363
23588
|
lines.push("");
|
|
23364
|
-
lines.push(...buildSelectPlan(w.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
|
|
23589
|
+
lines.push(...buildSelectPlan(w.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false, true, collector, "subquery"));
|
|
23365
23590
|
break;
|
|
23366
23591
|
case "LOGICAL":
|
|
23367
23592
|
visitWhere(w.left);
|
|
@@ -23381,7 +23606,7 @@ function collectSubqueryPlans(stmt, capabilities, orderPlans, plainGroupByPlans)
|
|
|
23381
23606
|
for (const col of stmt.columns) {
|
|
23382
23607
|
if (col.type === "SCALAR_SUBQUERY_COL") {
|
|
23383
23608
|
lines.push("");
|
|
23384
|
-
lines.push(...buildSelectPlan(col.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
|
|
23609
|
+
lines.push(...buildSelectPlan(col.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false, true, collector, "subquery"));
|
|
23385
23610
|
}
|
|
23386
23611
|
}
|
|
23387
23612
|
if (stmt.having) visitWhere(stmt.having);
|
|
@@ -23407,7 +23632,15 @@ function buildInsertSelectPlan(stmt, label, capabilities, orderPlans, plainGroup
|
|
|
23407
23632
|
lines.push(` fields: ${stmt.fields.join(", ")}`);
|
|
23408
23633
|
lines.push(` api: POST /k/v1/records.json\uFF08\u4EF6\u6570\u306F SELECT \u7D50\u679C\u306B\u4F9D\u5B58\u3001100 \u4EF6\u3054\u3068\u306B\u30D0\u30C3\u30C1\uFF09`);
|
|
23409
23634
|
lines.push("");
|
|
23410
|
-
lines.push(...buildSelectPlan(
|
|
23635
|
+
lines.push(...buildSelectPlan(
|
|
23636
|
+
stmt.select,
|
|
23637
|
+
"[source SELECT]",
|
|
23638
|
+
capabilities,
|
|
23639
|
+
orderPlans,
|
|
23640
|
+
plainGroupByPlans,
|
|
23641
|
+
false,
|
|
23642
|
+
false
|
|
23643
|
+
));
|
|
23411
23644
|
return lines;
|
|
23412
23645
|
}
|
|
23413
23646
|
function buildUpdatePlan(stmt, label, capabilities, orderPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, maxRecords = 1e4) {
|
|
@@ -23454,7 +23687,15 @@ function buildUpdatePlan(stmt, label, capabilities, orderPlans, dmlMaxRows = 100
|
|
|
23454
23687
|
for (const a of stmt.assignments) {
|
|
23455
23688
|
if (a.value.type === "SCALAR_SUBQUERY") {
|
|
23456
23689
|
lines.push("");
|
|
23457
|
-
lines.push(...buildSelectPlan(
|
|
23690
|
+
lines.push(...buildSelectPlan(
|
|
23691
|
+
a.value.query,
|
|
23692
|
+
`[subquery: ${a.field}]`,
|
|
23693
|
+
capabilities,
|
|
23694
|
+
orderPlans,
|
|
23695
|
+
void 0,
|
|
23696
|
+
false,
|
|
23697
|
+
false
|
|
23698
|
+
));
|
|
23458
23699
|
}
|
|
23459
23700
|
}
|
|
23460
23701
|
return lines;
|
|
@@ -23571,7 +23812,15 @@ function buildUpsertSelectPlan(stmt, label, capabilities, orderPlans, plainGroup
|
|
|
23571
23812
|
` api: GET /k/v1/records.json\uFF08\u91CD\u8907\u5224\u5B9A\uFF09\u2192 POST \u307E\u305F\u306F PUT /k/v1/records.json\uFF08100 \u4EF6\u3054\u3068\u306B\u30D0\u30C3\u30C1\uFF09`,
|
|
23572
23813
|
``
|
|
23573
23814
|
];
|
|
23574
|
-
lines.push(...buildSelectPlan(
|
|
23815
|
+
lines.push(...buildSelectPlan(
|
|
23816
|
+
stmt.select,
|
|
23817
|
+
"[source SELECT]",
|
|
23818
|
+
capabilities,
|
|
23819
|
+
orderPlans,
|
|
23820
|
+
plainGroupByPlans,
|
|
23821
|
+
false,
|
|
23822
|
+
false
|
|
23823
|
+
));
|
|
23575
23824
|
return lines;
|
|
23576
23825
|
}
|
|
23577
23826
|
function buildReorderPlan(stmt, label) {
|