@rex0220/kintone-sql-tools 3.31.1 → 3.33.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 +179 -48
- package/dist-engine/index.cjs +11 -11
- package/dist-engine/index.mjs +11 -11
- package/dist-engine/ksql-engine.umd.js +9 -9
- package/dist-engine/meta/bundle-baseline.json +7 -7
- package/dist-engine/meta/cjs.json +15 -15
- package/dist-engine/meta/esm.json +15 -15
- package/dist-engine/meta/umd.json +15 -15
- package/dist-engine/publicTypes.d.ts +6 -0
- package/dist-mcp/ksql-mcp.js +181 -50
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +84 -84
package/dist-cli/ksql.js
CHANGED
|
@@ -4260,6 +4260,15 @@ function containsStatisticalAggregate(value, seen = /* @__PURE__ */ new Set()) {
|
|
|
4260
4260
|
if (record.type === "FIELD" && typeof record.field === "string" && /^(STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/i.test(record.field)) return true;
|
|
4261
4261
|
return Object.values(record).some((child) => Array.isArray(child) ? child.some((entry) => containsStatisticalAggregate(entry, seen)) : containsStatisticalAggregate(child, seen));
|
|
4262
4262
|
}
|
|
4263
|
+
function containsAggregate(value, seen = /* @__PURE__ */ new Set()) {
|
|
4264
|
+
if (value === null || typeof value !== "object") return false;
|
|
4265
|
+
if (seen.has(value)) return false;
|
|
4266
|
+
seen.add(value);
|
|
4267
|
+
const record = value;
|
|
4268
|
+
if ((record.type === "AGGREGATE" || record.type === "AGG_REF") && typeof record.func === "string" && !STATISTICAL_AGGREGATES.has(record.func)) return true;
|
|
4269
|
+
if (record.type === "FIELD" && typeof record.field === "string" && /^(COUNT|SUM|AVG|MIN|MAX|GROUP_CONCAT)\(/i.test(record.field)) return true;
|
|
4270
|
+
return Object.values(record).some((child) => Array.isArray(child) ? child.some((entry) => containsAggregate(entry, seen)) : containsAggregate(child, seen));
|
|
4271
|
+
}
|
|
4263
4272
|
function completeInputReasons(stmt) {
|
|
4264
4273
|
const reasons = /* @__PURE__ */ new Set();
|
|
4265
4274
|
if (isDmlType(stmt.type)) {
|
|
@@ -4289,6 +4298,7 @@ function completeInputReasons(stmt) {
|
|
|
4289
4298
|
break;
|
|
4290
4299
|
}
|
|
4291
4300
|
if (containsStatisticalAggregate(stmt)) reasons.add("STATISTICAL_AGGREGATE");
|
|
4301
|
+
if (containsAggregate(stmt)) reasons.add("AGGREGATE");
|
|
4292
4302
|
return reasons;
|
|
4293
4303
|
}
|
|
4294
4304
|
function requiresCompleteInput(stmt) {
|
|
@@ -4297,11 +4307,15 @@ function requiresCompleteInput(stmt) {
|
|
|
4297
4307
|
function unionCompleteInputReasons(stmt) {
|
|
4298
4308
|
const reasons = stmt.left.type === "SELECT" ? selectCompleteInputReasons(stmt.left) : unionCompleteInputReasons(stmt.left);
|
|
4299
4309
|
addReasons(reasons, selectCompleteInputReasons(stmt.right));
|
|
4310
|
+
if (!stmt.all) reasons.add("DISTINCT");
|
|
4300
4311
|
return reasons;
|
|
4301
4312
|
}
|
|
4302
4313
|
function selectCompleteInputReasons(stmt) {
|
|
4303
4314
|
const reasons = /* @__PURE__ */ new Set();
|
|
4304
|
-
|
|
4315
|
+
const grouping = normalizeGroupingSpec(stmt);
|
|
4316
|
+
if (grouping.type === "GROUPING_SETS") reasons.add("GROUPING_SETS");
|
|
4317
|
+
if (grouping.type === "PLAIN") reasons.add("GROUP_BY");
|
|
4318
|
+
if (stmt.distinct) reasons.add("DISTINCT");
|
|
4305
4319
|
if (stmt.orderBy.length > 0) reasons.add("LOCAL_ORDER");
|
|
4306
4320
|
for (const column of stmt.columns) {
|
|
4307
4321
|
if (column.type === "WINDOW_COL" && column.orderBy.length > 0) reasons.add("WINDOW_ORDER");
|
|
@@ -4313,6 +4327,7 @@ function selectCompleteInputReasons(stmt) {
|
|
|
4313
4327
|
addReasons(reasons, whereCompleteInputReasons(stmt.where));
|
|
4314
4328
|
addReasons(reasons, whereCompleteInputReasons(stmt.having));
|
|
4315
4329
|
if (containsStatisticalAggregate(stmt)) reasons.add("STATISTICAL_AGGREGATE");
|
|
4330
|
+
if (containsAggregate(stmt)) reasons.add("AGGREGATE");
|
|
4316
4331
|
return reasons;
|
|
4317
4332
|
}
|
|
4318
4333
|
function whereCompleteInputReasons(where) {
|
|
@@ -6505,19 +6520,19 @@ function collectNonAggregateFieldRefs(node, out) {
|
|
|
6505
6520
|
}
|
|
6506
6521
|
Object.values(value).forEach((item) => collectNonAggregateFieldRefs(item, out));
|
|
6507
6522
|
}
|
|
6508
|
-
function
|
|
6523
|
+
function containsAggregate2(node) {
|
|
6509
6524
|
if (node === null || typeof node !== "object") return false;
|
|
6510
|
-
if (Array.isArray(node)) return node.some(
|
|
6525
|
+
if (Array.isArray(node)) return node.some(containsAggregate2);
|
|
6511
6526
|
const value = node;
|
|
6512
6527
|
if (value["type"] === "AGG_REF" || value["type"] === "AGG_ARITH") return true;
|
|
6513
6528
|
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return false;
|
|
6514
|
-
return Object.values(value).some(
|
|
6529
|
+
return Object.values(value).some(containsAggregate2);
|
|
6515
6530
|
}
|
|
6516
6531
|
function isAggregateMaterializedAlias(column) {
|
|
6517
6532
|
if (!("alias" in column) || column.alias === null) return false;
|
|
6518
6533
|
if (column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL") return true;
|
|
6519
6534
|
if (column.type === "STRFUNC_COL" || column.type === "SCALAR_VALUE_COL") {
|
|
6520
|
-
return
|
|
6535
|
+
return containsAggregate2(column);
|
|
6521
6536
|
}
|
|
6522
6537
|
return false;
|
|
6523
6538
|
}
|
|
@@ -10893,8 +10908,9 @@ function getLastId(records) {
|
|
|
10893
10908
|
return Number.isFinite(id) ? id : 0;
|
|
10894
10909
|
}
|
|
10895
10910
|
var FetchAllLimitError = class extends Error {
|
|
10896
|
-
constructor(message) {
|
|
10911
|
+
constructor(message, completeInputWrapped = false) {
|
|
10897
10912
|
super(message);
|
|
10913
|
+
this.completeInputWrapped = completeInputWrapped;
|
|
10898
10914
|
this.name = "FetchAllLimitError";
|
|
10899
10915
|
}
|
|
10900
10916
|
};
|
|
@@ -12405,7 +12421,7 @@ function classifyPreGroupAlias(column) {
|
|
|
12405
12421
|
case "STRFUNC_COL":
|
|
12406
12422
|
case "SCALAR_VALUE_COL":
|
|
12407
12423
|
case "SCALAR_SUBQUERY_COL":
|
|
12408
|
-
return
|
|
12424
|
+
return containsAggregate2(column) || containsAggregateColumnNode(column) ? "AGGREGATE_DEPENDENT" : "SAFE";
|
|
12409
12425
|
}
|
|
12410
12426
|
}
|
|
12411
12427
|
var SUBTABLE_SYSTEM_COLUMNS = ["_pid", "_rid", "_idx"];
|
|
@@ -12530,11 +12546,11 @@ var EMPTY_WILDCARD_FIELD_TYPE_POLICY = {
|
|
|
12530
12546
|
UPDATED_TIME: "RECORD",
|
|
12531
12547
|
USER_SELECT: "RECORD"
|
|
12532
12548
|
};
|
|
12533
|
-
function fieldPolicy(fieldType) {
|
|
12549
|
+
function fieldPolicy(fieldType, fieldCode) {
|
|
12534
12550
|
const policy = EMPTY_WILDCARD_FIELD_TYPE_POLICY[fieldType];
|
|
12535
12551
|
if (policy === void 0) {
|
|
12536
12552
|
throw new Error(
|
|
12537
|
-
`
|
|
12553
|
+
`ArgumentError: getFields returned unknown fieldType "${fieldType}" for field "${fieldCode}". getFields must return only the fields from /k/v1/app/form/fields.json; $id and $revision are synthesized by the engine and must not be added.`
|
|
12538
12554
|
);
|
|
12539
12555
|
}
|
|
12540
12556
|
return policy;
|
|
@@ -12549,10 +12565,10 @@ async function deriveEmptyWildcardColumns(fields, subtableCode, loadProcessStatu
|
|
|
12549
12565
|
];
|
|
12550
12566
|
}
|
|
12551
12567
|
const topLevel = fields.filter((field) => !field.inSubtable);
|
|
12552
|
-
const needsProcessSettings = topLevel.some((field) => fieldPolicy(field.fieldType) === "PROCESS");
|
|
12568
|
+
const needsProcessSettings = topLevel.some((field) => fieldPolicy(field.fieldType, field.code) === "PROCESS");
|
|
12553
12569
|
const processEnabled = needsProcessSettings ? (await loadProcessStatuses()).enable : false;
|
|
12554
12570
|
const columns = topLevel.filter((field) => {
|
|
12555
|
-
const policy = fieldPolicy(field.fieldType);
|
|
12571
|
+
const policy = fieldPolicy(field.fieldType, field.code);
|
|
12556
12572
|
return policy === "RECORD" || policy === "PROCESS" && processEnabled;
|
|
12557
12573
|
}).map((field) => field.code);
|
|
12558
12574
|
return [...columns, "$revision", "$id"];
|
|
@@ -15448,11 +15464,21 @@ function createEmptyMetrics() {
|
|
|
15448
15464
|
cursorCreateOutcomeUnknown: 0,
|
|
15449
15465
|
cursorQuarantinedCurrent: 0,
|
|
15450
15466
|
fetchedRows: 0,
|
|
15467
|
+
limitReached: false,
|
|
15468
|
+
limitReachedApps: [],
|
|
15451
15469
|
elapsedMs: 0
|
|
15452
15470
|
};
|
|
15453
15471
|
}
|
|
15472
|
+
var LIMIT_METRICS_SINK = /* @__PURE__ */ Symbol("limitMetricsSink");
|
|
15473
|
+
function markLimitReached(client, appId) {
|
|
15474
|
+
const metrics = client[LIMIT_METRICS_SINK];
|
|
15475
|
+
if (!metrics) return;
|
|
15476
|
+
metrics.limitReached = true;
|
|
15477
|
+
if (!metrics.limitReachedApps.includes(appId)) metrics.limitReachedApps.push(appId);
|
|
15478
|
+
}
|
|
15454
15479
|
function wrapClientWithMetrics(client, metrics) {
|
|
15455
15480
|
return {
|
|
15481
|
+
[LIMIT_METRICS_SINK]: metrics,
|
|
15456
15482
|
getRecords: async (params) => {
|
|
15457
15483
|
metrics.getCalls += 1;
|
|
15458
15484
|
const res = await client.getRecords(params);
|
|
@@ -15652,7 +15678,7 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
|
15652
15678
|
return executeExistingRecordValidation(stmt, client, options, cacheContext);
|
|
15653
15679
|
case "SELECT":
|
|
15654
15680
|
return executeSelect(
|
|
15655
|
-
stmt,
|
|
15681
|
+
markCountTotalCountRoot(stmt),
|
|
15656
15682
|
client,
|
|
15657
15683
|
options,
|
|
15658
15684
|
cacheContext,
|
|
@@ -16788,7 +16814,7 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache, capt
|
|
|
16788
16814
|
cteCache
|
|
16789
16815
|
);
|
|
16790
16816
|
await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache);
|
|
16791
|
-
const whereCapability = await resolveSelectWhereCapability(stmt, client, cacheContext, cteCache);
|
|
16817
|
+
const whereCapability = rememberSelectWhereCapability(stmt, await resolveSelectWhereCapability(stmt, client, cacheContext, cteCache));
|
|
16792
16818
|
if (whereCapability.capability === "UNSUPPORTED") {
|
|
16793
16819
|
throw new Error(`ArgumentError: WHERE predicate is unsupported (${formatWhereCapabilityFailure(whereCapability)}).`);
|
|
16794
16820
|
}
|
|
@@ -17054,11 +17080,21 @@ async function validateSelectGroupingPlanning(stmt, client, cacheContext, materi
|
|
|
17054
17080
|
}
|
|
17055
17081
|
function completeInputErrorPrefix(reasons) {
|
|
17056
17082
|
const reasonList = [...reasons].join(", ");
|
|
17057
|
-
const
|
|
17083
|
+
const aggregateSubjects = [
|
|
17084
|
+
["GROUPING_SETS", "\u5C0F\u8A08\u30FB\u7DCF\u8A08\u306E\u6B63\u3057\u3044\u7D50\u679C"],
|
|
17085
|
+
["STATISTICAL_AGGREGATE", "\u7D71\u8A08\u96C6\u7D04\u306E\u6B63\u3057\u3044\u7D50\u679C"],
|
|
17086
|
+
["AGGREGATE", "\u96C6\u8A08\u306E\u6B63\u3057\u3044\u7D50\u679C"],
|
|
17087
|
+
["GROUP_BY", "\u30B0\u30EB\u30FC\u30D7\u96C6\u8A08\u306E\u6B63\u3057\u3044\u7D50\u679C"],
|
|
17088
|
+
["DISTINCT", "DISTINCT \u306E\u6B63\u3057\u3044\u7D50\u679C"]
|
|
17089
|
+
];
|
|
17090
|
+
const hasAggregateReason = aggregateSubjects.some(([reason]) => reasons.has(reason));
|
|
17091
|
+
const hasOrderReason = reasons.has("LOCAL_ORDER") || reasons.has("WINDOW_ORDER");
|
|
17092
|
+
const legacySubject = reasons.size === 1 && reasons.has("STATISTICAL_AGGREGATE") ? "\u7D71\u8A08\u96C6\u7D04\u306E\u6B63\u3057\u3044\u7D50\u679C" : reasons.size === 1 && reasons.has("GROUPING_SETS") ? "\u5C0F\u8A08\u30FB\u7DCF\u8A08\u306E\u6B63\u3057\u3044\u7D50\u679C" : reasons.size === 1 && reasons.has("AGGREGATE") ? "\u96C6\u8A08\u306E\u6B63\u3057\u3044\u7D50\u679C" : reasons.size === 1 && reasons.has("GROUP_BY") ? "\u30B0\u30EB\u30FC\u30D7\u96C6\u8A08\u306E\u6B63\u3057\u3044\u7D50\u679C" : reasons.size === 1 && reasons.has("DISTINCT") ? "DISTINCT \u306E\u6B63\u3057\u3044\u7D50\u679C" : reasons.has("GROUPING_SETS") ? "\u30AF\u30A8\u30EA\u306E\u6B63\u3057\u3044\u7D50\u679C" : "ORDER BY\u306E\u6B63\u3057\u3044\u7D50\u679C";
|
|
17093
|
+
const subject = reasons.has("DML") || reasons.has("VALIDATE") ? legacySubject : hasAggregateReason && hasOrderReason ? "\u30AF\u30A8\u30EA\u306E\u6B63\u3057\u3044\u7D50\u679C" : hasAggregateReason ? aggregateSubjects.find(([reason]) => reasons.has(reason))[1] : "ORDER BY\u306E\u6B63\u3057\u3044\u7D50\u679C";
|
|
17058
17094
|
return `${subject}\u306B\u306F\u5B8C\u5168\u306A\u5019\u88DC\u96C6\u5408\u304C\u5FC5\u8981\u3067\u3059\u3002complete input reason: ${reasonList}\u3002`;
|
|
17059
17095
|
}
|
|
17060
17096
|
function buildCompleteInputPolicy(stmt, options, orderPlan) {
|
|
17061
|
-
const reasons = orderPlan?.kind === "CANONICAL_REST_TOP_N" || orderPlan?.kind === "KORDER_NATIVE" || orderPlan?.kind === "KORDER_CURSOR" ? completeInputReasons({ ...stmt, orderBy: [] }) : completeInputReasons(stmt);
|
|
17097
|
+
const reasons = stmt.type === "SELECT" && (orderPlan?.kind === "CANONICAL_REST_TOP_N" || orderPlan?.kind === "KORDER_NATIVE" || orderPlan?.kind === "KORDER_CURSOR") ? completeInputReasons({ ...stmt, orderBy: [] }) : completeInputReasons(stmt);
|
|
17062
17098
|
const truncateWasDisabled = reasons.size > 0 && options.onLimitReached === "truncate";
|
|
17063
17099
|
return {
|
|
17064
17100
|
reasons,
|
|
@@ -17067,9 +17103,10 @@ function buildCompleteInputPolicy(stmt, options, orderPlan) {
|
|
|
17067
17103
|
};
|
|
17068
17104
|
}
|
|
17069
17105
|
function throwCompleteInputError(policy, error) {
|
|
17070
|
-
if (policy.reasons.size > 0 && error instanceof FetchAllLimitError) {
|
|
17106
|
+
if (policy.reasons.size > 0 && error instanceof FetchAllLimitError && !error.completeInputWrapped) {
|
|
17071
17107
|
throw new FetchAllLimitError(
|
|
17072
|
-
completeInputErrorPrefix(policy.reasons) + (policy.truncateWasDisabled ? "onLimit=truncate\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002" : "") + error.message
|
|
17108
|
+
completeInputErrorPrefix(policy.reasons) + (policy.truncateWasDisabled ? "onLimit=truncate\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002" : "") + error.message,
|
|
17109
|
+
true
|
|
17073
17110
|
);
|
|
17074
17111
|
}
|
|
17075
17112
|
throw error;
|
|
@@ -17214,6 +17251,7 @@ async function executeSimpleSelect(stmt, client, options, cacheContext, orderPla
|
|
|
17214
17251
|
onLimit,
|
|
17215
17252
|
onTruncate: (max) => {
|
|
17216
17253
|
warnings.add(`\u53D6\u5F97\u4E0A\u9650\uFF08${max} \u4EF6\uFF09\u306B\u9054\u3057\u305F\u305F\u3081\u3001${max} \u4EF6\u3067\u6253\u3061\u5207\u3063\u3066\u8868\u793A\u3057\u3066\u3044\u307E\u3059\u3002`);
|
|
17254
|
+
markLimitReached(client, stmt.from.appId);
|
|
17217
17255
|
}
|
|
17218
17256
|
}
|
|
17219
17257
|
);
|
|
@@ -18099,7 +18137,55 @@ function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
|
|
|
18099
18137
|
};
|
|
18100
18138
|
return { row, having };
|
|
18101
18139
|
}
|
|
18140
|
+
var countTotalCountRootSelects = /* @__PURE__ */ new WeakSet();
|
|
18141
|
+
var resolvedWhereCapabilities = /* @__PURE__ */ new WeakMap();
|
|
18142
|
+
function markCountTotalCountRoot(stmt) {
|
|
18143
|
+
countTotalCountRootSelects.add(stmt);
|
|
18144
|
+
return stmt;
|
|
18145
|
+
}
|
|
18146
|
+
function rememberSelectWhereCapability(stmt, capability) {
|
|
18147
|
+
resolvedWhereCapabilities.set(stmt, capability);
|
|
18148
|
+
return capability;
|
|
18149
|
+
}
|
|
18150
|
+
function isCountStarTotalCountEligible(stmt, whereCapability) {
|
|
18151
|
+
if (whereCapability.capability !== "EXACT_PUSHDOWN") return false;
|
|
18152
|
+
if (stmt.columns.length !== 1) return false;
|
|
18153
|
+
const column = stmt.columns[0];
|
|
18154
|
+
if (column?.type !== "AGGREGATE" || column.func !== "COUNT" || column.distinct || column.arg.type !== "WILDCARD") {
|
|
18155
|
+
return false;
|
|
18156
|
+
}
|
|
18157
|
+
return !stmt.distinct && normalizeGroupingSpec(stmt).type === "NONE" && stmt.having === null && stmt.joins.length === 0 && stmt.from.cteName === null && !stmt.from.subtableCode && stmt.limit === null && stmt.offset === null;
|
|
18158
|
+
}
|
|
18159
|
+
function isValidTotalCount(value) {
|
|
18160
|
+
return typeof value === "string" && /^(?:0|[1-9]\d*)$/.test(value);
|
|
18161
|
+
}
|
|
18162
|
+
async function tryCountStarWithTotalCount(stmt, client) {
|
|
18163
|
+
const countColumn = stmt.columns[0];
|
|
18164
|
+
if (countColumn?.type !== "AGGREGATE") return null;
|
|
18165
|
+
const baseQuery = stmt.where === null ? "" : whereToKintone(stmt.where);
|
|
18166
|
+
const response = await client.getRecords({
|
|
18167
|
+
app: stmt.from.appId,
|
|
18168
|
+
query: `${baseQuery}${baseQuery ? " " : ""}limit 1`,
|
|
18169
|
+
fields: ["$id"],
|
|
18170
|
+
totalCount: true
|
|
18171
|
+
});
|
|
18172
|
+
if (response.searchAborted) throw new SearchAbortedError();
|
|
18173
|
+
if (!isValidTotalCount(response.totalCount)) return null;
|
|
18174
|
+
const column = countColumn.alias ?? "COUNT(*)";
|
|
18175
|
+
return {
|
|
18176
|
+
type: "SELECT",
|
|
18177
|
+
rows: [{ [column]: response.totalCount }],
|
|
18178
|
+
columns: [column],
|
|
18179
|
+
rowCount: 1,
|
|
18180
|
+
warnings: []
|
|
18181
|
+
};
|
|
18182
|
+
}
|
|
18102
18183
|
async function executeFullScanSelect(stmt, client, options, cacheContext, cteCache, allowOriginalWherePushdown = true, preloadedOrderMeta, prefilterPlan, plainGroupByPlan) {
|
|
18184
|
+
const whereCapability = resolvedWhereCapabilities.get(stmt);
|
|
18185
|
+
if (countTotalCountRootSelects.has(stmt) && whereCapability !== void 0 && isCountStarTotalCountEligible(stmt, whereCapability)) {
|
|
18186
|
+
const totalCountResult = await tryCountStarWithTotalCount(stmt, client);
|
|
18187
|
+
if (totalCountResult !== null) return totalCountResult;
|
|
18188
|
+
}
|
|
18103
18189
|
const maxRecords = options.maxRecords ?? 1e4;
|
|
18104
18190
|
const warnings = /* @__PURE__ */ new Set();
|
|
18105
18191
|
const parallel = options.fetchParallel ?? 1;
|
|
@@ -18253,26 +18339,53 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
18253
18339
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
18254
18340
|
}
|
|
18255
18341
|
async function executeUnion(stmt, client, options, cacheContext, captureColumnMeta = false, forLibraryCapture = false) {
|
|
18256
|
-
const
|
|
18257
|
-
|
|
18258
|
-
|
|
18259
|
-
|
|
18260
|
-
|
|
18261
|
-
|
|
18262
|
-
|
|
18263
|
-
|
|
18264
|
-
|
|
18265
|
-
|
|
18342
|
+
const completePolicy = buildCompleteInputPolicy(stmt, options, null);
|
|
18343
|
+
return withCompleteInputPolicy(completePolicy, async () => {
|
|
18344
|
+
const effectiveOptions = completePolicy.effectiveOptions;
|
|
18345
|
+
const [leftResult, rightResult] = await Promise.all([
|
|
18346
|
+
stmt.left.type === "UNION" ? executeUnion(
|
|
18347
|
+
stmt.left,
|
|
18348
|
+
client,
|
|
18349
|
+
effectiveOptions,
|
|
18350
|
+
cacheContext,
|
|
18351
|
+
captureColumnMeta,
|
|
18352
|
+
forLibraryCapture
|
|
18353
|
+
) : executeSelect(
|
|
18354
|
+
stmt.left,
|
|
18355
|
+
client,
|
|
18356
|
+
effectiveOptions,
|
|
18357
|
+
cacheContext,
|
|
18358
|
+
void 0,
|
|
18359
|
+
captureColumnMeta,
|
|
18360
|
+
forLibraryCapture
|
|
18361
|
+
),
|
|
18362
|
+
executeSelect(
|
|
18363
|
+
stmt.right,
|
|
18364
|
+
client,
|
|
18365
|
+
effectiveOptions,
|
|
18366
|
+
cacheContext,
|
|
18367
|
+
void 0,
|
|
18368
|
+
captureColumnMeta,
|
|
18369
|
+
forLibraryCapture
|
|
18370
|
+
)
|
|
18371
|
+
]);
|
|
18372
|
+
const leftCols = leftResult.columns;
|
|
18373
|
+
const rightCols = rightResult.columns;
|
|
18374
|
+
const remappedRight = rightResult.rows.map((row) => {
|
|
18375
|
+
const mapped = {};
|
|
18376
|
+
leftCols.forEach((col, i) => {
|
|
18377
|
+
mapped[col] = row[rightCols[i] ?? col] ?? "";
|
|
18378
|
+
});
|
|
18379
|
+
return mapped;
|
|
18266
18380
|
});
|
|
18267
|
-
|
|
18381
|
+
const combined = [...leftResult.rows, ...remappedRight];
|
|
18382
|
+
const rows = stmt.all ? combined : deduplicateRows(combined, leftCols);
|
|
18383
|
+
const result = { type: "SELECT", rows, columns: leftCols, rowCount: rows.length };
|
|
18384
|
+
if (captureColumnMeta) {
|
|
18385
|
+
materializedMetaBySelectResult.set(result, mergeUnionColumnMeta(leftResult, rightResult));
|
|
18386
|
+
}
|
|
18387
|
+
return result;
|
|
18268
18388
|
});
|
|
18269
|
-
const combined = [...leftResult.rows, ...remappedRight];
|
|
18270
|
-
const rows = stmt.all ? combined : deduplicateRows(combined, leftCols);
|
|
18271
|
-
const result = { type: "SELECT", rows, columns: leftCols, rowCount: rows.length };
|
|
18272
|
-
if (captureColumnMeta) {
|
|
18273
|
-
materializedMetaBySelectResult.set(result, mergeUnionColumnMeta(leftResult, rightResult));
|
|
18274
|
-
}
|
|
18275
|
-
return result;
|
|
18276
18389
|
}
|
|
18277
18390
|
function deduplicateRows(rows, columns) {
|
|
18278
18391
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -18540,6 +18653,7 @@ async function fetchTableRecordsForFullScan(stmt, table, client, maxRecords, par
|
|
|
18540
18653
|
const fields = selectToFetchAllFields(stmt, table, plainGroupByPlan);
|
|
18541
18654
|
const onTruncate = (max) => {
|
|
18542
18655
|
warnings.add(`\u53D6\u5F97\u4E0A\u9650\uFF08${max} \u4EF6\uFF09\u306B\u9054\u3057\u305F\u305F\u3081\u3001${max} \u4EF6\u3067\u6253\u3061\u5207\u3063\u3066\u8868\u793A\u3057\u3066\u3044\u307E\u3059\u3002`);
|
|
18656
|
+
markLimitReached(client, table.appId);
|
|
18543
18657
|
};
|
|
18544
18658
|
if (!table.subtableCode) {
|
|
18545
18659
|
const baseQuery = isMainTable && allowOriginalWherePushdown ? selectToFetchAllParams(stmt, table.appId).query : "";
|
|
@@ -18695,6 +18809,7 @@ async function tryFetchJoinRecordsBySourceKeys(stmt, join2, tables, client, maxR
|
|
|
18695
18809
|
const fields = selectToFetchAllFields(stmt, join2.table, plainGroupByPlan);
|
|
18696
18810
|
const onTruncate = (max) => {
|
|
18697
18811
|
warnings.add(`\u53D6\u5F97\u4E0A\u9650\uFF08${max} \u4EF6\uFF09\u306B\u9054\u3057\u305F\u305F\u3081\u3001${max} \u4EF6\u3067\u6253\u3061\u5207\u3063\u3066\u8868\u793A\u3057\u3066\u3044\u307E\u3059\u3002`);
|
|
18812
|
+
markLimitReached(client, join2.table.appId);
|
|
18698
18813
|
};
|
|
18699
18814
|
const chunks = splitChunks(values, JOIN_IN_CHUNK_SIZE);
|
|
18700
18815
|
const merged = [];
|
|
@@ -22714,11 +22829,12 @@ function buildValidatePlan(stmt, label) {
|
|
|
22714
22829
|
lines.push(" records/mutation API during EXPLAIN: none; violation count unavailable");
|
|
22715
22830
|
return lines;
|
|
22716
22831
|
}
|
|
22717
|
-
function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlans) {
|
|
22832
|
+
function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlans, allowTotalCountPlan = true) {
|
|
22718
22833
|
const whereCapability = capabilities?.get(stmt) ?? (capabilities ? [...capabilities].find(([candidate]) => JSON.stringify(candidate) === JSON.stringify(stmt))?.[1] : void 0);
|
|
22719
22834
|
const orderPlan = orderPlans?.get(stmt) ?? (orderPlans ? [...orderPlans].find(([candidate]) => JSON.stringify(candidate) === JSON.stringify(stmt))?.[1] : void 0);
|
|
22720
22835
|
const plainGroupByPlan = plainGroupByPlans?.get(stmt) ?? (plainGroupByPlans ? [...plainGroupByPlans].find(([candidate]) => JSON.stringify(candidate) === JSON.stringify(stmt))?.[1] : void 0);
|
|
22721
|
-
const
|
|
22836
|
+
const totalCountPlan = allowTotalCountPlan && whereCapability !== void 0 && isCountStarTotalCountEligible(stmt, whereCapability);
|
|
22837
|
+
const mode = totalCountPlan ? "COUNT_TOTAL_COUNT" : orderPlan?.kind === "CANONICAL_LOCAL" ? "FULL_SCAN" : whereCapability && whereCapability.capability !== "EXACT_PUSHDOWN" ? "FULL_SCAN" : resolveSelectMode(stmt);
|
|
22722
22838
|
const reasons = collectFullScanReasons(stmt);
|
|
22723
22839
|
if (whereCapability && whereCapability.capability !== "EXACT_PUSHDOWN") {
|
|
22724
22840
|
reasons.push(...whereCapability.reasons.map((reason) => reason.code));
|
|
@@ -22765,6 +22881,20 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlan
|
|
|
22765
22881
|
}
|
|
22766
22882
|
}
|
|
22767
22883
|
}
|
|
22884
|
+
if (totalCountPlan) {
|
|
22885
|
+
const baseQuery = stmt.where === null ? "" : whereToKintone(stmt.where);
|
|
22886
|
+
lines.push(` app: APP${stmt.from.appId} (${stmt.from.appId})`);
|
|
22887
|
+
lines.push(
|
|
22888
|
+
` kintone query: ${baseQuery}${baseQuery ? " " : ""}limit 1`
|
|
22889
|
+
);
|
|
22890
|
+
lines.push(" fields: $id");
|
|
22891
|
+
lines.push(" fetch API: GET records.json (totalCount=true)");
|
|
22892
|
+
lines.push(" REST execution: single GET");
|
|
22893
|
+
lines.push(" record limit: maxRecords/onLimitReached not applied");
|
|
22894
|
+
lines.push(" fallback: full record scan when totalCount is missing or invalid");
|
|
22895
|
+
lines.push(" search abort: fail-closed (SearchAbortedError)");
|
|
22896
|
+
return lines;
|
|
22897
|
+
}
|
|
22768
22898
|
if (orderPlan) {
|
|
22769
22899
|
lines.push(` order plan: ${orderPlan.kind}`);
|
|
22770
22900
|
if (orderPlan.reasonCodes.length > 0) lines.push(` order reason: ${orderPlan.reasonCodes.join(", ")}`);
|
|
@@ -22901,7 +23031,7 @@ function buildUnionPlan(stmt, capabilities, orderPlans, plainGroupByPlans) {
|
|
|
22901
23031
|
const lines = [];
|
|
22902
23032
|
selects.forEach((sel, i) => {
|
|
22903
23033
|
if (i > 0) lines.push("");
|
|
22904
|
-
lines.push(...buildSelectPlan(sel, `[union:${i + 1}]`, capabilities, orderPlans, plainGroupByPlans));
|
|
23034
|
+
lines.push(...buildSelectPlan(sel, `[union:${i + 1}]`, capabilities, orderPlans, plainGroupByPlans, false));
|
|
22905
23035
|
});
|
|
22906
23036
|
return lines;
|
|
22907
23037
|
}
|
|
@@ -22909,7 +23039,7 @@ function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans) {
|
|
|
22909
23039
|
const lines = [];
|
|
22910
23040
|
for (const cte of stmt.ctes) {
|
|
22911
23041
|
if (cte.query.type === "SELECT") {
|
|
22912
|
-
lines.push(...buildSelectPlan(cte.query, `[cte: ${cte.name}]`, capabilities, orderPlans, plainGroupByPlans));
|
|
23042
|
+
lines.push(...buildSelectPlan(cte.query, `[cte: ${cte.name}]`, capabilities, orderPlans, plainGroupByPlans, false));
|
|
22913
23043
|
lines.push("");
|
|
22914
23044
|
}
|
|
22915
23045
|
}
|
|
@@ -22928,7 +23058,7 @@ function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans) {
|
|
|
22928
23058
|
if (canInlineSingleCte(stmt)) {
|
|
22929
23059
|
lines.push("");
|
|
22930
23060
|
const inlined = buildInlinedQuery(stmt);
|
|
22931
|
-
lines.push(...buildSelectPlan(inlined, "[effective: inlined CTE]", capabilities, orderPlans, plainGroupByPlans));
|
|
23061
|
+
lines.push(...buildSelectPlan(inlined, "[effective: inlined CTE]", capabilities, orderPlans, plainGroupByPlans, false));
|
|
22932
23062
|
}
|
|
22933
23063
|
return lines;
|
|
22934
23064
|
}
|
|
@@ -22970,16 +23100,16 @@ function collectSubqueryPlans(stmt, capabilities, orderPlans, plainGroupByPlans)
|
|
|
22970
23100
|
case "BINARY":
|
|
22971
23101
|
if (w.right.type === "SCALAR_SUBQUERY") {
|
|
22972
23102
|
lines.push("");
|
|
22973
|
-
lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans));
|
|
23103
|
+
lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
|
|
22974
23104
|
}
|
|
22975
23105
|
if (w.right.type === "SUBQUERY_IN_LIST") {
|
|
22976
23106
|
lines.push("");
|
|
22977
|
-
lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans));
|
|
23107
|
+
lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
|
|
22978
23108
|
}
|
|
22979
23109
|
break;
|
|
22980
23110
|
case "EXISTS":
|
|
22981
23111
|
lines.push("");
|
|
22982
|
-
lines.push(...buildSelectPlan(w.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans));
|
|
23112
|
+
lines.push(...buildSelectPlan(w.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
|
|
22983
23113
|
break;
|
|
22984
23114
|
case "LOGICAL":
|
|
22985
23115
|
visitWhere(w.left);
|
|
@@ -22999,7 +23129,7 @@ function collectSubqueryPlans(stmt, capabilities, orderPlans, plainGroupByPlans)
|
|
|
22999
23129
|
for (const col of stmt.columns) {
|
|
23000
23130
|
if (col.type === "SCALAR_SUBQUERY_COL") {
|
|
23001
23131
|
lines.push("");
|
|
23002
|
-
lines.push(...buildSelectPlan(col.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans));
|
|
23132
|
+
lines.push(...buildSelectPlan(col.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
|
|
23003
23133
|
}
|
|
23004
23134
|
}
|
|
23005
23135
|
if (stmt.having) visitWhere(stmt.having);
|
|
@@ -23025,7 +23155,7 @@ function buildInsertSelectPlan(stmt, label, capabilities, orderPlans, plainGroup
|
|
|
23025
23155
|
lines.push(` fields: ${stmt.fields.join(", ")}`);
|
|
23026
23156
|
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`);
|
|
23027
23157
|
lines.push("");
|
|
23028
|
-
lines.push(...buildSelectPlan(stmt.select, "[source SELECT]", capabilities, orderPlans, plainGroupByPlans));
|
|
23158
|
+
lines.push(...buildSelectPlan(stmt.select, "[source SELECT]", capabilities, orderPlans, plainGroupByPlans, false));
|
|
23029
23159
|
return lines;
|
|
23030
23160
|
}
|
|
23031
23161
|
function buildUpdatePlan(stmt, label, capabilities, orderPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, maxRecords = 1e4) {
|
|
@@ -23072,7 +23202,7 @@ function buildUpdatePlan(stmt, label, capabilities, orderPlans, dmlMaxRows = 100
|
|
|
23072
23202
|
for (const a of stmt.assignments) {
|
|
23073
23203
|
if (a.value.type === "SCALAR_SUBQUERY") {
|
|
23074
23204
|
lines.push("");
|
|
23075
|
-
lines.push(...buildSelectPlan(a.value.query, `[subquery: ${a.field}]`, capabilities, orderPlans));
|
|
23205
|
+
lines.push(...buildSelectPlan(a.value.query, `[subquery: ${a.field}]`, capabilities, orderPlans, void 0, false));
|
|
23076
23206
|
}
|
|
23077
23207
|
}
|
|
23078
23208
|
return lines;
|
|
@@ -23189,7 +23319,7 @@ function buildUpsertSelectPlan(stmt, label, capabilities, orderPlans, plainGroup
|
|
|
23189
23319
|
` 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`,
|
|
23190
23320
|
``
|
|
23191
23321
|
];
|
|
23192
|
-
lines.push(...buildSelectPlan(stmt.select, "[source SELECT]", capabilities, orderPlans, plainGroupByPlans));
|
|
23322
|
+
lines.push(...buildSelectPlan(stmt.select, "[source SELECT]", capabilities, orderPlans, plainGroupByPlans, false));
|
|
23193
23323
|
return lines;
|
|
23194
23324
|
}
|
|
23195
23325
|
function buildReorderPlan(stmt, label) {
|
|
@@ -24493,7 +24623,8 @@ function createNodeKintoneConnection(baseUrl, tokenResolver) {
|
|
|
24493
24623
|
const queryPart = `query=${encodeURIComponent(params.query)}`;
|
|
24494
24624
|
const appPart = `app=${encodeURIComponent(String(params.app))}`;
|
|
24495
24625
|
const fieldParts = params.fields.map((f) => `fields[]=${encodeURIComponent(f)}`);
|
|
24496
|
-
const
|
|
24626
|
+
const totalCountPart = params.totalCount === true ? ["totalCount=true"] : [];
|
|
24627
|
+
const qs = [appPart, queryPart, ...fieldParts, ...totalCountPart].join("&");
|
|
24497
24628
|
if (tokenResolver.debug) {
|
|
24498
24629
|
tokenResolver.log?.(
|
|
24499
24630
|
`[debug] getRecords app=${params.app} query="${params.query}" fields=${params.fields.length > 0 ? params.fields.join(",") : "(all)"} auth=${tokenResolver.auth.type}`
|