@rex0220/kintone-sql-tools 1.2.0 → 1.3.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/README.md +1 -0
- package/dist-cli/ksql.js +375 -162
- package/dist-mcp/ksql-mcp.js +377 -161
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +2 -2
package/dist-mcp/ksql-mcp.js
CHANGED
|
@@ -33722,23 +33722,31 @@ function resolveKintoneFunc(name) {
|
|
|
33722
33722
|
return "";
|
|
33723
33723
|
}
|
|
33724
33724
|
}
|
|
33725
|
+
var likeRegexCache = /* @__PURE__ */ new Map();
|
|
33726
|
+
var LIKE_REGEX_CACHE_MAX = 200;
|
|
33725
33727
|
function matchLike(value, pattern) {
|
|
33726
33728
|
if (!pattern.includes("%") && !pattern.includes("_")) {
|
|
33727
33729
|
return value.includes(pattern);
|
|
33728
33730
|
}
|
|
33729
|
-
let
|
|
33730
|
-
|
|
33731
|
-
|
|
33732
|
-
|
|
33733
|
-
|
|
33734
|
-
|
|
33735
|
-
|
|
33736
|
-
|
|
33737
|
-
|
|
33731
|
+
let regex = likeRegexCache.get(pattern);
|
|
33732
|
+
if (!regex) {
|
|
33733
|
+
let regexStr = "^";
|
|
33734
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
33735
|
+
const ch = pattern[i];
|
|
33736
|
+
if (ch === "%") {
|
|
33737
|
+
regexStr += ".*";
|
|
33738
|
+
} else if (ch === "_") {
|
|
33739
|
+
regexStr += ".";
|
|
33740
|
+
} else {
|
|
33741
|
+
regexStr += ch.replace(/[.+*?^${}()|[\]\\]/g, "\\$&");
|
|
33742
|
+
}
|
|
33738
33743
|
}
|
|
33744
|
+
regexStr += "$";
|
|
33745
|
+
regex = new RegExp(regexStr, "u");
|
|
33746
|
+
if (likeRegexCache.size >= LIKE_REGEX_CACHE_MAX) likeRegexCache.clear();
|
|
33747
|
+
likeRegexCache.set(pattern, regex);
|
|
33739
33748
|
}
|
|
33740
|
-
|
|
33741
|
-
return new RegExp(regexStr, "u").test(value);
|
|
33749
|
+
return regex.test(value);
|
|
33742
33750
|
}
|
|
33743
33751
|
|
|
33744
33752
|
// src/converter/dmlToKintone.ts
|
|
@@ -34166,10 +34174,12 @@ async function fetchPage(fetcher, app, query, fields, pageSize, offset) {
|
|
|
34166
34174
|
return fetcher({ app, query: pageQuery, fields });
|
|
34167
34175
|
}
|
|
34168
34176
|
function buildCursorQuery(baseQuery, cursorId) {
|
|
34169
|
-
if (cursorId <= 0) return baseQuery.trimEnd();
|
|
34170
|
-
const cursor = `$id > ${cursorId} order by $id asc`;
|
|
34171
34177
|
const base = baseQuery.trimEnd();
|
|
34172
|
-
|
|
34178
|
+
if (cursorId <= 0) {
|
|
34179
|
+
return base ? `${base} order by $id asc` : "order by $id asc";
|
|
34180
|
+
}
|
|
34181
|
+
const cursor = `$id > ${cursorId} order by $id asc`;
|
|
34182
|
+
return base ? `(${base}) and ${cursor}` : cursor;
|
|
34173
34183
|
}
|
|
34174
34184
|
function buildPageQuery(query, pageSize, offset) {
|
|
34175
34185
|
const base = query.trimEnd();
|
|
@@ -34322,6 +34332,8 @@ function applyJoin(leftRows, rightRows, join) {
|
|
|
34322
34332
|
else rightIndex.set(k, [rRow]);
|
|
34323
34333
|
}
|
|
34324
34334
|
const result = [];
|
|
34335
|
+
const emptyRight = {};
|
|
34336
|
+
for (const key of Object.keys(rightRows[0] ?? {})) emptyRight[key] = "";
|
|
34325
34337
|
for (const lRow of leftRows) {
|
|
34326
34338
|
const k = lRow[leftKey] ?? "";
|
|
34327
34339
|
const matched = rightIndex.get(k) ?? [];
|
|
@@ -34330,8 +34342,6 @@ function applyJoin(leftRows, rightRows, join) {
|
|
|
34330
34342
|
result.push({ ...lRow, ...rRow });
|
|
34331
34343
|
}
|
|
34332
34344
|
} else if (joinType === "LEFT") {
|
|
34333
|
-
const emptyRight = {};
|
|
34334
|
-
for (const key of Object.keys(rightRows[0] ?? {})) emptyRight[key] = "";
|
|
34335
34345
|
result.push({ ...lRow, ...emptyRight });
|
|
34336
34346
|
}
|
|
34337
34347
|
}
|
|
@@ -34407,12 +34417,23 @@ function evalAggregate(func, distinct, arg, rows) {
|
|
|
34407
34417
|
return nums.reduce((a, b) => a + b, 0);
|
|
34408
34418
|
case "AVG":
|
|
34409
34419
|
return nums.length === 0 ? 0 : nums.reduce((a, b) => a + b, 0) / nums.length;
|
|
34420
|
+
// Math.max(...nums) は要素数が多いと RangeError になるためループで求める
|
|
34410
34421
|
case "MAX":
|
|
34411
|
-
return nums.length === 0 ? 0 :
|
|
34422
|
+
return nums.length === 0 ? 0 : maxOf(nums);
|
|
34412
34423
|
case "MIN":
|
|
34413
|
-
return nums.length === 0 ? 0 :
|
|
34424
|
+
return nums.length === 0 ? 0 : minOf(nums);
|
|
34414
34425
|
}
|
|
34415
34426
|
}
|
|
34427
|
+
function maxOf(nums) {
|
|
34428
|
+
let m = nums[0];
|
|
34429
|
+
for (const n of nums) if (n > m) m = n;
|
|
34430
|
+
return m;
|
|
34431
|
+
}
|
|
34432
|
+
function minOf(nums) {
|
|
34433
|
+
let m = nums[0];
|
|
34434
|
+
for (const n of nums) if (n < m) m = n;
|
|
34435
|
+
return m;
|
|
34436
|
+
}
|
|
34416
34437
|
function evalAggArithExpr(node, rows) {
|
|
34417
34438
|
if (node.type === "NUMBER") return node.value;
|
|
34418
34439
|
if (node.type === "AGG_REF") return evalAggregate(node.func, node.distinct, node.arg, rows);
|
|
@@ -34449,43 +34470,89 @@ function applyHaving(rows, having) {
|
|
|
34449
34470
|
return rows.filter((row) => evalWhere(having, row));
|
|
34450
34471
|
}
|
|
34451
34472
|
function applyDistinct(rows, columns) {
|
|
34473
|
+
if (rows.length === 0) return rows;
|
|
34474
|
+
const keyFor = buildDistinctKeyBuilder(rows, columns);
|
|
34452
34475
|
const seen = /* @__PURE__ */ new Set();
|
|
34453
34476
|
return rows.filter((row) => {
|
|
34454
|
-
const key =
|
|
34477
|
+
const key = keyFor(row);
|
|
34455
34478
|
if (seen.has(key)) return false;
|
|
34456
34479
|
seen.add(key);
|
|
34457
34480
|
return true;
|
|
34458
34481
|
});
|
|
34459
34482
|
}
|
|
34460
|
-
function
|
|
34483
|
+
function buildDistinctKeyBuilder(rows, columns) {
|
|
34461
34484
|
if (columns.some((c) => c.type === "WILDCARD")) {
|
|
34462
|
-
|
|
34463
|
-
|
|
34464
|
-
|
|
34465
|
-
for (const col of columns) {
|
|
34466
|
-
if (col.type === "FIELD") {
|
|
34467
|
-
values.push(row[col.field] ?? "");
|
|
34468
|
-
continue;
|
|
34485
|
+
const allKeys = /* @__PURE__ */ new Set();
|
|
34486
|
+
for (const row of rows) {
|
|
34487
|
+
for (const k of Object.keys(row)) allKeys.add(k);
|
|
34469
34488
|
}
|
|
34470
|
-
|
|
34471
|
-
|
|
34472
|
-
|
|
34489
|
+
const keys = [...allKeys].sort();
|
|
34490
|
+
return (row) => JSON.stringify(keys.map((k) => row[k] !== void 0 ? row[k] : null));
|
|
34491
|
+
}
|
|
34492
|
+
let sortedParentKeys = [];
|
|
34493
|
+
if (columns.some((c) => c.type === "PARENT_WILDCARD")) {
|
|
34494
|
+
const parentKeys = /* @__PURE__ */ new Set();
|
|
34495
|
+
for (const row of rows) {
|
|
34496
|
+
for (const k of Object.keys(row)) {
|
|
34497
|
+
if (k.startsWith("_p.")) parentKeys.add(k);
|
|
34473
34498
|
}
|
|
34474
34499
|
}
|
|
34500
|
+
sortedParentKeys = [...parentKeys].sort();
|
|
34475
34501
|
}
|
|
34476
|
-
return
|
|
34502
|
+
return (row) => {
|
|
34503
|
+
const values = [];
|
|
34504
|
+
for (const col of columns) {
|
|
34505
|
+
if (col.type === "FIELD") {
|
|
34506
|
+
values.push(row[col.field] ?? "");
|
|
34507
|
+
continue;
|
|
34508
|
+
}
|
|
34509
|
+
if (col.type === "PARENT_WILDCARD") {
|
|
34510
|
+
for (const k of sortedParentKeys) {
|
|
34511
|
+
values.push(row[k] !== void 0 ? row[k] : null);
|
|
34512
|
+
}
|
|
34513
|
+
}
|
|
34514
|
+
}
|
|
34515
|
+
return JSON.stringify(values);
|
|
34516
|
+
};
|
|
34477
34517
|
}
|
|
34478
34518
|
function applyOrderBy(rows, orderBy, optionOrders, sortKinds) {
|
|
34479
34519
|
if (orderBy.length === 0) return rows;
|
|
34480
|
-
|
|
34481
|
-
|
|
34482
|
-
|
|
34483
|
-
|
|
34484
|
-
|
|
34485
|
-
|
|
34520
|
+
const keyMeta = orderBy.map(({ key }) => ({
|
|
34521
|
+
orderMap: key.type === "FIELD_NAME" ? optionOrders?.get(key.name) : void 0,
|
|
34522
|
+
sortKind: key.type === "FIELD_NAME" ? sortKinds?.get(key.name) : void 0
|
|
34523
|
+
}));
|
|
34524
|
+
const decorated = rows.map((row) => ({
|
|
34525
|
+
row,
|
|
34526
|
+
keys: orderBy.map(({ key }, i) => {
|
|
34527
|
+
const s = evalOrderKey(key, row);
|
|
34528
|
+
const n = Number(s);
|
|
34529
|
+
const orderMap = keyMeta[i].orderMap;
|
|
34530
|
+
return {
|
|
34531
|
+
s,
|
|
34532
|
+
n,
|
|
34533
|
+
isNum: !Number.isNaN(n),
|
|
34534
|
+
rank: orderMap ? minChoiceIndex(parseChoiceValues(s), orderMap) : 0
|
|
34535
|
+
};
|
|
34536
|
+
})
|
|
34537
|
+
}));
|
|
34538
|
+
decorated.sort((a, b) => {
|
|
34539
|
+
for (let i = 0; i < orderBy.length; i++) {
|
|
34540
|
+
const cmp = compareSortKeys(a.keys[i], b.keys[i], keyMeta[i]);
|
|
34541
|
+
if (cmp !== 0) return orderBy[i].direction === "ASC" ? cmp : -cmp;
|
|
34486
34542
|
}
|
|
34487
34543
|
return 0;
|
|
34488
34544
|
});
|
|
34545
|
+
return decorated.map((d) => d.row);
|
|
34546
|
+
}
|
|
34547
|
+
function compareSortKeys(a, b, meta3) {
|
|
34548
|
+
if (meta3.orderMap) {
|
|
34549
|
+
if (a.rank !== b.rank) return a.rank - b.rank;
|
|
34550
|
+
return a.s.localeCompare(b.s, "ja");
|
|
34551
|
+
}
|
|
34552
|
+
if (meta3.sortKind === "string") {
|
|
34553
|
+
return a.s.localeCompare(b.s, "ja");
|
|
34554
|
+
}
|
|
34555
|
+
return a.isNum && b.isNum ? a.n - b.n : a.s.localeCompare(b.s, "ja");
|
|
34489
34556
|
}
|
|
34490
34557
|
function evalOrderKey(key, row) {
|
|
34491
34558
|
switch (key.type) {
|
|
@@ -34497,32 +34564,6 @@ function evalOrderKey(key, row) {
|
|
|
34497
34564
|
return evalStringFunc(key.expr, row);
|
|
34498
34565
|
}
|
|
34499
34566
|
}
|
|
34500
|
-
function compareOrderValues(av, bv, key, optionOrders, sortKinds) {
|
|
34501
|
-
if (key.type === "FIELD_NAME") {
|
|
34502
|
-
const orderMap = optionOrders?.get(key.name);
|
|
34503
|
-
if (orderMap) {
|
|
34504
|
-
const ac = compareByChoiceOrder(av, bv, orderMap);
|
|
34505
|
-
if (ac !== 0) return ac;
|
|
34506
|
-
return av.localeCompare(bv, "ja");
|
|
34507
|
-
}
|
|
34508
|
-
const sortKind = sortKinds?.get(key.name);
|
|
34509
|
-
if (sortKind === "number") {
|
|
34510
|
-
return compareAsNumber(av, bv);
|
|
34511
|
-
}
|
|
34512
|
-
if (sortKind === "string") {
|
|
34513
|
-
return av.localeCompare(bv, "ja");
|
|
34514
|
-
}
|
|
34515
|
-
}
|
|
34516
|
-
return compareAuto(av, bv);
|
|
34517
|
-
}
|
|
34518
|
-
function compareByChoiceOrder(av, bv, orderMap) {
|
|
34519
|
-
const aValues = parseChoiceValues(av);
|
|
34520
|
-
const bValues = parseChoiceValues(bv);
|
|
34521
|
-
const aRank = minChoiceIndex(aValues, orderMap);
|
|
34522
|
-
const bRank = minChoiceIndex(bValues, orderMap);
|
|
34523
|
-
if (aRank !== bRank) return aRank - bRank;
|
|
34524
|
-
return 0;
|
|
34525
|
-
}
|
|
34526
34567
|
function parseChoiceValues(raw) {
|
|
34527
34568
|
const trimmed = raw.trim();
|
|
34528
34569
|
if (trimmed === "") return [""];
|
|
@@ -34546,18 +34587,6 @@ function minChoiceIndex(values, orderMap) {
|
|
|
34546
34587
|
}
|
|
34547
34588
|
return min;
|
|
34548
34589
|
}
|
|
34549
|
-
function compareAsNumber(av, bv) {
|
|
34550
|
-
const an = Number(av);
|
|
34551
|
-
const bn = Number(bv);
|
|
34552
|
-
const numeric = !Number.isNaN(an) && !Number.isNaN(bn);
|
|
34553
|
-
return numeric ? an - bn : av.localeCompare(bv, "ja");
|
|
34554
|
-
}
|
|
34555
|
-
function compareAuto(av, bv) {
|
|
34556
|
-
const an = Number(av);
|
|
34557
|
-
const bn = Number(bv);
|
|
34558
|
-
const numeric = !Number.isNaN(an) && !Number.isNaN(bn);
|
|
34559
|
-
return numeric ? an - bn : av.localeCompare(bv, "ja");
|
|
34560
|
-
}
|
|
34561
34590
|
function applyLimit(rows, limit, offset) {
|
|
34562
34591
|
const start = offset ?? 0;
|
|
34563
34592
|
if (limit === null) return rows.slice(start);
|
|
@@ -34802,6 +34831,56 @@ function toFlatString(value) {
|
|
|
34802
34831
|
|
|
34803
34832
|
// src/execute.ts
|
|
34804
34833
|
async function execute(sql, client, options = {}) {
|
|
34834
|
+
const metrics = createEmptyMetrics();
|
|
34835
|
+
const countedClient = wrapClientWithMetrics(client, metrics);
|
|
34836
|
+
const startedAt = Date.now();
|
|
34837
|
+
const result = await executeStatement(sql, countedClient, options);
|
|
34838
|
+
metrics.elapsedMs = Date.now() - startedAt;
|
|
34839
|
+
return { ...result, metrics };
|
|
34840
|
+
}
|
|
34841
|
+
function createEmptyMetrics() {
|
|
34842
|
+
return {
|
|
34843
|
+
getCalls: 0,
|
|
34844
|
+
postCalls: 0,
|
|
34845
|
+
putCalls: 0,
|
|
34846
|
+
deleteCalls: 0,
|
|
34847
|
+
fieldCalls: 0,
|
|
34848
|
+
appsCalls: 0,
|
|
34849
|
+
fetchedRows: 0,
|
|
34850
|
+
elapsedMs: 0
|
|
34851
|
+
};
|
|
34852
|
+
}
|
|
34853
|
+
function wrapClientWithMetrics(client, metrics) {
|
|
34854
|
+
return {
|
|
34855
|
+
getRecords: async (params) => {
|
|
34856
|
+
metrics.getCalls += 1;
|
|
34857
|
+
const res = await client.getRecords(params);
|
|
34858
|
+
metrics.fetchedRows += res.records.length;
|
|
34859
|
+
return res;
|
|
34860
|
+
},
|
|
34861
|
+
postRecords: (params) => {
|
|
34862
|
+
metrics.postCalls += 1;
|
|
34863
|
+
return client.postRecords(params);
|
|
34864
|
+
},
|
|
34865
|
+
putRecords: (params) => {
|
|
34866
|
+
metrics.putCalls += 1;
|
|
34867
|
+
return client.putRecords(params);
|
|
34868
|
+
},
|
|
34869
|
+
deleteRecords: (params) => {
|
|
34870
|
+
metrics.deleteCalls += 1;
|
|
34871
|
+
return client.deleteRecords(params);
|
|
34872
|
+
},
|
|
34873
|
+
getApps: () => {
|
|
34874
|
+
metrics.appsCalls += 1;
|
|
34875
|
+
return client.getApps();
|
|
34876
|
+
},
|
|
34877
|
+
getFields: (appId) => {
|
|
34878
|
+
metrics.fieldCalls += 1;
|
|
34879
|
+
return client.getFields(appId);
|
|
34880
|
+
}
|
|
34881
|
+
};
|
|
34882
|
+
}
|
|
34883
|
+
async function executeStatement(sql, client, options) {
|
|
34805
34884
|
const cacheContext = options.cacheContext ?? "default";
|
|
34806
34885
|
const stmt = parseSql(sql);
|
|
34807
34886
|
switch (stmt.type) {
|
|
@@ -34812,7 +34891,7 @@ async function execute(sql, client, options = {}) {
|
|
|
34812
34891
|
case "WITH":
|
|
34813
34892
|
return executeWith(stmt, client, options, cacheContext);
|
|
34814
34893
|
case "INSERT":
|
|
34815
|
-
return executeInsert(stmt, client, cacheContext);
|
|
34894
|
+
return executeInsert(stmt, client, options, cacheContext);
|
|
34816
34895
|
case "INSERT_SELECT":
|
|
34817
34896
|
return executeInsertSelect(stmt, client, options, cacheContext);
|
|
34818
34897
|
case "UPSERT":
|
|
@@ -34927,8 +35006,7 @@ async function executeSimpleSelect(stmt, client, options, cacheContext) {
|
|
|
34927
35006
|
}
|
|
34928
35007
|
let rows = records.map((r) => flatten(r, null));
|
|
34929
35008
|
if (!useSingleGet) {
|
|
34930
|
-
const optionOrders = await
|
|
34931
|
-
const sortKinds = await buildSortKindsForSelect(stmt, client, cacheContext);
|
|
35009
|
+
const { optionOrders, sortKinds } = await buildOrderByMetaForSelect(stmt, client, cacheContext);
|
|
34932
35010
|
rows = applyOrderBy(rows, stmt.orderBy, optionOrders, sortKinds);
|
|
34933
35011
|
rows = applyLimit(rows, stmt.limit, stmt.offset);
|
|
34934
35012
|
}
|
|
@@ -34956,11 +35034,12 @@ async function validateSelectFieldCodes(stmt, mode, client, cacheContext) {
|
|
|
34956
35034
|
}
|
|
34957
35035
|
}
|
|
34958
35036
|
for (const [appId, fields] of appToFields.entries()) {
|
|
34959
|
-
|
|
35037
|
+
const userFields = [...fields].filter((f) => !isSystemLikeFieldCode(f));
|
|
35038
|
+
if (userFields.length === 0) continue;
|
|
34960
35039
|
const defs = await getFieldsCached(appId, client, cacheContext);
|
|
34961
35040
|
if (defs.length === 0) continue;
|
|
34962
35041
|
const validCodes = new Set(defs.map((d) => d.code));
|
|
34963
|
-
const unknown2 =
|
|
35042
|
+
const unknown2 = userFields.filter((f) => !validCodes.has(f));
|
|
34964
35043
|
if (unknown2.length > 0) {
|
|
34965
35044
|
throw new Error(`ArgumentError: unknown field code(s): ${unknown2.join(", ")} (APP${appId})`);
|
|
34966
35045
|
}
|
|
@@ -34970,8 +35049,10 @@ async function executeFullScanSelect(stmt, client, options, cacheContext) {
|
|
|
34970
35049
|
const maxRecords2 = options.maxRecords ?? 1e4;
|
|
34971
35050
|
const warnings = /* @__PURE__ */ new Set();
|
|
34972
35051
|
const parallel = options.fetchParallel ?? 1;
|
|
34973
|
-
await
|
|
34974
|
-
|
|
35052
|
+
await Promise.all([
|
|
35053
|
+
resolveSubqueries(stmt.where, client, options, cacheContext),
|
|
35054
|
+
resolveSubqueries(stmt.having, client, options, cacheContext)
|
|
35055
|
+
]);
|
|
34975
35056
|
const tableConditions = /* @__PURE__ */ new Map();
|
|
34976
35057
|
if (stmt.where !== null) {
|
|
34977
35058
|
if (stmt.from.alias) {
|
|
@@ -35020,6 +35101,12 @@ async function executeFullScanSelect(stmt, client, options, cacheContext) {
|
|
|
35020
35101
|
onOptJoins.push(join);
|
|
35021
35102
|
}
|
|
35022
35103
|
}
|
|
35104
|
+
const scalarCachePromise = resolveScalarColumns(stmt.columns, client, options, cacheContext);
|
|
35105
|
+
const orderByMetaPromise = buildOrderByMetaForSelect(stmt, client, cacheContext);
|
|
35106
|
+
scalarCachePromise.catch(() => {
|
|
35107
|
+
});
|
|
35108
|
+
orderByMetaPromise.catch(() => {
|
|
35109
|
+
});
|
|
35023
35110
|
const mainRecords = await mainFetch;
|
|
35024
35111
|
const tables = /* @__PURE__ */ new Map();
|
|
35025
35112
|
tables.set(stmt.from.alias, mainRecords);
|
|
@@ -35051,15 +35138,16 @@ async function executeFullScanSelect(stmt, client, options, cacheContext) {
|
|
|
35051
35138
|
);
|
|
35052
35139
|
tables.set(join.table.alias, joinRecords);
|
|
35053
35140
|
}));
|
|
35054
|
-
const scalarCache = await
|
|
35055
|
-
const optionOrders = await
|
|
35056
|
-
const sortKinds = await buildSortKindsForSelect(stmt, client, cacheContext);
|
|
35141
|
+
const scalarCache = await scalarCachePromise;
|
|
35142
|
+
const { optionOrders, sortKinds } = await orderByMetaPromise;
|
|
35057
35143
|
const { rows, columns } = runFullScan({ tables, stmt, scalarCache, optionOrders, sortKinds });
|
|
35058
35144
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
35059
35145
|
}
|
|
35060
35146
|
async function executeUnion(stmt, client, options, cacheContext) {
|
|
35061
|
-
const leftResult =
|
|
35062
|
-
|
|
35147
|
+
const [leftResult, rightResult] = await Promise.all([
|
|
35148
|
+
stmt.left.type === "UNION" ? executeUnion(stmt.left, client, options, cacheContext) : executeSelect(stmt.left, client, options, cacheContext),
|
|
35149
|
+
executeSelect(stmt.right, client, options, cacheContext)
|
|
35150
|
+
]);
|
|
35063
35151
|
const leftCols = leftResult.columns;
|
|
35064
35152
|
const rightCols = rightResult.columns;
|
|
35065
35153
|
const remappedRight = rightResult.rows.map((row) => {
|
|
@@ -35076,7 +35164,7 @@ async function executeUnion(stmt, client, options, cacheContext) {
|
|
|
35076
35164
|
function deduplicateRows(rows, columns) {
|
|
35077
35165
|
const seen = /* @__PURE__ */ new Set();
|
|
35078
35166
|
return rows.filter((row) => {
|
|
35079
|
-
const key = columns.map((c) => row[c] ?? "")
|
|
35167
|
+
const key = JSON.stringify(columns.map((c) => row[c] ?? ""));
|
|
35080
35168
|
if (seen.has(key)) return false;
|
|
35081
35169
|
seen.add(key);
|
|
35082
35170
|
return true;
|
|
@@ -35179,8 +35267,10 @@ function stripCteAliasFromFieldValue(fv, alias) {
|
|
|
35179
35267
|
}
|
|
35180
35268
|
async function executeQueryWithCte(query, client, options, cteCache, cacheContext) {
|
|
35181
35269
|
if (query.type === "UNION") {
|
|
35182
|
-
const leftResult = await
|
|
35183
|
-
|
|
35270
|
+
const [leftResult, rightResult] = await Promise.all([
|
|
35271
|
+
executeQueryWithCte(query.left, client, options, cteCache, cacheContext),
|
|
35272
|
+
executeQueryWithCte(query.right, client, options, cteCache, cacheContext)
|
|
35273
|
+
]);
|
|
35184
35274
|
const leftCols = leftResult.columns;
|
|
35185
35275
|
const rightCols = rightResult.columns;
|
|
35186
35276
|
const remapped = rightResult.rows.map((row) => {
|
|
@@ -35204,8 +35294,16 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
35204
35294
|
const maxRecords2 = options.maxRecords ?? 1e4;
|
|
35205
35295
|
const warnings = /* @__PURE__ */ new Set();
|
|
35206
35296
|
const parallel = options.fetchParallel ?? 1;
|
|
35207
|
-
await
|
|
35208
|
-
|
|
35297
|
+
await Promise.all([
|
|
35298
|
+
resolveSubqueries(stmt.where, client, options, cacheContext),
|
|
35299
|
+
resolveSubqueries(stmt.having, client, options, cacheContext)
|
|
35300
|
+
]);
|
|
35301
|
+
const scalarCachePromise = resolveScalarColumns(stmt.columns, client, options, cacheContext);
|
|
35302
|
+
const orderByMetaPromise = buildOrderByMetaForSelect(stmt, client, cacheContext);
|
|
35303
|
+
scalarCachePromise.catch(() => {
|
|
35304
|
+
});
|
|
35305
|
+
orderByMetaPromise.catch(() => {
|
|
35306
|
+
});
|
|
35209
35307
|
const tables = /* @__PURE__ */ new Map();
|
|
35210
35308
|
if (stmt.from.cteName != null) {
|
|
35211
35309
|
const rows2 = cteCache.get(stmt.from.cteName) ?? [];
|
|
@@ -35252,9 +35350,8 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
35252
35350
|
}
|
|
35253
35351
|
});
|
|
35254
35352
|
await Promise.all(joinFetches);
|
|
35255
|
-
const scalarCache = await
|
|
35256
|
-
const optionOrders = await
|
|
35257
|
-
const sortKinds = await buildSortKindsForSelect(stmt, client, cacheContext);
|
|
35353
|
+
const scalarCache = await scalarCachePromise;
|
|
35354
|
+
const { optionOrders, sortKinds } = await orderByMetaPromise;
|
|
35258
35355
|
const { rows, columns } = runFullScan({ tables, stmt, scalarCache, optionOrders, sortKinds });
|
|
35259
35356
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
35260
35357
|
}
|
|
@@ -35290,6 +35387,78 @@ async function fetchTableRecordsForFullScan(stmt, table, client, maxRecords2, pa
|
|
|
35290
35387
|
const parentRecords = parentResolved.records;
|
|
35291
35388
|
return expandSubtableRecords(parentRecords, table.subtableCode);
|
|
35292
35389
|
}
|
|
35390
|
+
var UPSERT_IN_CHUNK_SIZE = 50;
|
|
35391
|
+
function normalizeKeyPart(v) {
|
|
35392
|
+
const t = v.trim();
|
|
35393
|
+
if (t !== "" && !Number.isNaN(Number(t))) return String(Number(t));
|
|
35394
|
+
return v;
|
|
35395
|
+
}
|
|
35396
|
+
function upsertCompositeKey(parts) {
|
|
35397
|
+
return JSON.stringify(parts);
|
|
35398
|
+
}
|
|
35399
|
+
function upsertNormalizedKey(parts, numericKey) {
|
|
35400
|
+
return JSON.stringify(parts.map((p, i) => numericKey[i] ? normalizeKeyPart(p) : p));
|
|
35401
|
+
}
|
|
35402
|
+
function lookupUpsertTarget(index, keyParts) {
|
|
35403
|
+
const exact = index.raw.get(upsertCompositeKey(keyParts));
|
|
35404
|
+
if (exact !== void 0) return exact;
|
|
35405
|
+
if (!index.numericKey.some(Boolean)) return void 0;
|
|
35406
|
+
return index.normalized.get(upsertNormalizedKey(keyParts, index.numericKey));
|
|
35407
|
+
}
|
|
35408
|
+
async function resolveUpsertTargets(appId, keyFields, rowKeyValues, client, options, fieldTypes) {
|
|
35409
|
+
const maxRecords2 = options.maxRecords ?? 1e4;
|
|
35410
|
+
const parallel = options.fetchParallel ?? 1;
|
|
35411
|
+
const numericKey = keyFields.map((f) => fieldTypes.get(f) === "NUMBER");
|
|
35412
|
+
const index = { raw: /* @__PURE__ */ new Map(), normalized: /* @__PURE__ */ new Map(), numericKey };
|
|
35413
|
+
const setMax = (map2, key, id) => {
|
|
35414
|
+
const cur = map2.get(key);
|
|
35415
|
+
if (cur === void 0 || id > cur) map2.set(key, id);
|
|
35416
|
+
};
|
|
35417
|
+
const addRecordToIndex = (parts, id) => {
|
|
35418
|
+
setMax(index.raw, upsertCompositeKey(parts), id);
|
|
35419
|
+
if (numericKey.some(Boolean)) {
|
|
35420
|
+
setMax(index.normalized, upsertNormalizedKey(parts, numericKey), id);
|
|
35421
|
+
}
|
|
35422
|
+
};
|
|
35423
|
+
const batchFirstKeys = /* @__PURE__ */ new Set();
|
|
35424
|
+
const perRowKeys = [];
|
|
35425
|
+
const seen = /* @__PURE__ */ new Set();
|
|
35426
|
+
for (const parts of rowKeyValues) {
|
|
35427
|
+
const composite = upsertCompositeKey(parts);
|
|
35428
|
+
if (seen.has(composite)) continue;
|
|
35429
|
+
seen.add(composite);
|
|
35430
|
+
if (parts.some((p) => p === "")) perRowKeys.push(parts);
|
|
35431
|
+
else batchFirstKeys.add(parts[0]);
|
|
35432
|
+
}
|
|
35433
|
+
const fields = ["$id", ...keyFields];
|
|
35434
|
+
for (const chunk2 of splitChunks([...batchFirstKeys], UPSERT_IN_CHUNK_SIZE)) {
|
|
35435
|
+
const query = `${keyFields[0]} in (${chunk2.map(sqlQuote).join(",")})`;
|
|
35436
|
+
const records = await fetchAll(client.getRecords, appId, query, fields, { maxRecords: maxRecords2, parallel });
|
|
35437
|
+
for (const rec of records) {
|
|
35438
|
+
const id = Number(rec["$id"]?.value);
|
|
35439
|
+
if (!Number.isFinite(id)) continue;
|
|
35440
|
+
addRecordToIndex(keyFields.map((f) => toScalarText(rec[f]?.value)), id);
|
|
35441
|
+
}
|
|
35442
|
+
}
|
|
35443
|
+
for (const parts of perRowKeys) {
|
|
35444
|
+
const query = keyFields.map((f, i) => `${f} = ${sqlQuote(parts[i])}`).join(" and ");
|
|
35445
|
+
const existing = await fetchAll(client.getRecords, appId, query, ["$id"], { maxRecords: maxRecords2, parallel });
|
|
35446
|
+
if (existing.length === 0) continue;
|
|
35447
|
+
addRecordToIndex(parts, maxRecordId(existing));
|
|
35448
|
+
}
|
|
35449
|
+
return index;
|
|
35450
|
+
}
|
|
35451
|
+
function maxRecordId(records) {
|
|
35452
|
+
let max = Number.NEGATIVE_INFINITY;
|
|
35453
|
+
for (const r of records) {
|
|
35454
|
+
const n = Number(r["$id"]?.value);
|
|
35455
|
+
if (Number.isFinite(n) && n > max) max = n;
|
|
35456
|
+
}
|
|
35457
|
+
if (!Number.isFinite(max)) {
|
|
35458
|
+
throw new Error("\u30EC\u30B3\u30FC\u30C9\u306B\u6570\u5024\u306E $id \u304C\u542B\u307E\u308C\u3066\u3044\u307E\u305B\u3093\u3002");
|
|
35459
|
+
}
|
|
35460
|
+
return max;
|
|
35461
|
+
}
|
|
35293
35462
|
function toScalarText(value) {
|
|
35294
35463
|
if (typeof value === "string") return value;
|
|
35295
35464
|
if (value === null || value === void 0) return "";
|
|
@@ -35427,6 +35596,16 @@ async function getSortKindMapByApp(appId, client, cacheContext) {
|
|
|
35427
35596
|
setScopedCacheValue(sortKindCache, cacheContext, appId, map2);
|
|
35428
35597
|
return map2;
|
|
35429
35598
|
}
|
|
35599
|
+
async function buildOrderByMetaForSelect(stmt, client, cacheContext) {
|
|
35600
|
+
if (stmt.orderBy.length === 0) {
|
|
35601
|
+
return { optionOrders: /* @__PURE__ */ new Map(), sortKinds: /* @__PURE__ */ new Map() };
|
|
35602
|
+
}
|
|
35603
|
+
const [optionOrders, sortKinds] = await Promise.all([
|
|
35604
|
+
buildOptionOrdersForSelect(stmt, client, cacheContext),
|
|
35605
|
+
buildSortKindsForSelect(stmt, client, cacheContext)
|
|
35606
|
+
]);
|
|
35607
|
+
return { optionOrders, sortKinds };
|
|
35608
|
+
}
|
|
35430
35609
|
async function buildOptionOrdersForSelect(stmt, client, cacheContext) {
|
|
35431
35610
|
const optionOrders = /* @__PURE__ */ new Map();
|
|
35432
35611
|
const tables = [stmt.from, ...stmt.joins.map((j) => j.table)];
|
|
@@ -35500,9 +35679,9 @@ function convertProcessRowValue(raw, dstFieldType) {
|
|
|
35500
35679
|
}
|
|
35501
35680
|
return raw;
|
|
35502
35681
|
}
|
|
35503
|
-
async function executeInsert(stmt, client, cacheContext) {
|
|
35682
|
+
async function executeInsert(stmt, client, options, cacheContext) {
|
|
35504
35683
|
if (stmt.subtableCode) {
|
|
35505
|
-
return executeInsertSubtable(stmt, client, cacheContext);
|
|
35684
|
+
return executeInsertSubtable(stmt, client, options, cacheContext);
|
|
35506
35685
|
}
|
|
35507
35686
|
const fieldTypes = await getFieldTypeMap(stmt.appId, client, cacheContext);
|
|
35508
35687
|
const batches = insertToPostBatches(stmt, fieldTypes);
|
|
@@ -35617,26 +35796,19 @@ async function executeDelete(stmt, client, options, cacheContext) {
|
|
|
35617
35796
|
return { type: "DELETE", deletedCount: ids.length };
|
|
35618
35797
|
}
|
|
35619
35798
|
async function executeUpsert(stmt, client, options, cacheContext) {
|
|
35620
|
-
const maxRecords2 = options.maxRecords ?? 1e4;
|
|
35621
35799
|
const toInsert = [];
|
|
35622
35800
|
const toUpdate = [];
|
|
35623
35801
|
const fieldTypes = await getFieldTypeMap(stmt.appId, client, cacheContext);
|
|
35624
|
-
|
|
35625
|
-
|
|
35802
|
+
const rowKeyValues = stmt.values.map(
|
|
35803
|
+
(row) => stmt.keyFields.map((key) => {
|
|
35626
35804
|
const idx = stmt.fields.indexOf(key);
|
|
35627
35805
|
if (idx === -1) throw new Error(`ON DUPLICATE \u306E\u30AD\u30FC\u300C${key}\u300D\u304C INSERT \u30D5\u30A3\u30FC\u30EB\u30C9\u306B\u542B\u307E\u308C\u3066\u3044\u307E\u305B\u3093`);
|
|
35628
35806
|
const val = row[idx];
|
|
35629
|
-
|
|
35630
|
-
|
|
35631
|
-
|
|
35632
|
-
|
|
35633
|
-
|
|
35634
|
-
client.getRecords,
|
|
35635
|
-
stmt.appId,
|
|
35636
|
-
query,
|
|
35637
|
-
["$id"],
|
|
35638
|
-
{ maxRecords: maxRecords2, parallel: options.fetchParallel ?? 1 }
|
|
35639
|
-
);
|
|
35807
|
+
return val.type === "STRING" ? val.value : val.type === "NUMBER" ? String(val.value) : val.type === "CASE_VALUE" ? evalCaseWhen(val.expr, {}) : val.elements.map((e) => e.value).join(",");
|
|
35808
|
+
})
|
|
35809
|
+
);
|
|
35810
|
+
const targetIndex = await resolveUpsertTargets(stmt.appId, stmt.keyFields, rowKeyValues, client, options, fieldTypes);
|
|
35811
|
+
stmt.values.forEach((row, rowIdx) => {
|
|
35640
35812
|
const record2 = {};
|
|
35641
35813
|
stmt.fields.forEach((field, i) => {
|
|
35642
35814
|
const val = row[i];
|
|
@@ -35646,13 +35818,13 @@ async function executeUpsert(stmt, client, options, cacheContext) {
|
|
|
35646
35818
|
record2[field] = { value: toKintoneValue(val, fieldTypes.get(field)) };
|
|
35647
35819
|
}
|
|
35648
35820
|
});
|
|
35649
|
-
|
|
35650
|
-
|
|
35821
|
+
const id = lookupUpsertTarget(targetIndex, rowKeyValues[rowIdx]);
|
|
35822
|
+
if (id !== void 0) {
|
|
35651
35823
|
toUpdate.push({ id, record: record2 });
|
|
35652
35824
|
} else {
|
|
35653
35825
|
toInsert.push(record2);
|
|
35654
35826
|
}
|
|
35655
|
-
}
|
|
35827
|
+
});
|
|
35656
35828
|
if (options.confirm && toInsert.length + toUpdate.length > 0) {
|
|
35657
35829
|
const total = toInsert.length + toUpdate.length;
|
|
35658
35830
|
const ok = await options.confirm(total, "UPDATE");
|
|
@@ -35672,18 +35844,17 @@ async function executeUpsert(stmt, client, options, cacheContext) {
|
|
|
35672
35844
|
updatedCount: toUpdate.length
|
|
35673
35845
|
};
|
|
35674
35846
|
}
|
|
35675
|
-
async function executeInsertSubtable(stmt, client, _cacheContext) {
|
|
35847
|
+
async function executeInsertSubtable(stmt, client, options, _cacheContext) {
|
|
35676
35848
|
const subtableCode = stmt.subtableCode;
|
|
35677
35849
|
const pidIndex = stmt.fields.indexOf("_pid");
|
|
35678
35850
|
if (pidIndex < 0) {
|
|
35679
35851
|
throw new Error("\u30B5\u30D6\u30C6\u30FC\u30D6\u30EB INSERT \u306B\u306F _pid \u304C\u5FC5\u9808\u3067\u3059");
|
|
35680
35852
|
}
|
|
35681
|
-
const parents = await fetchAll(client.getRecords, stmt.appId, "", [], {
|
|
35682
|
-
|
|
35683
|
-
|
|
35684
|
-
|
|
35685
|
-
|
|
35686
|
-
}
|
|
35853
|
+
const parents = await fetchAll(client.getRecords, stmt.appId, "", [], {
|
|
35854
|
+
maxRecords: options.maxRecords ?? 1e4,
|
|
35855
|
+
parallel: options.fetchParallel ?? 1
|
|
35856
|
+
});
|
|
35857
|
+
const parentMap = buildParentIdMap(parents);
|
|
35687
35858
|
const insertsByParent = /* @__PURE__ */ new Map();
|
|
35688
35859
|
for (const rowValues of stmt.values) {
|
|
35689
35860
|
const pid = valueToString(rowValues[pidIndex]);
|
|
@@ -35750,8 +35921,9 @@ async function executeUpdateSubtable(stmt, client, options, _cacheContext) {
|
|
|
35750
35921
|
}
|
|
35751
35922
|
byRid.set(t.rowId, updates);
|
|
35752
35923
|
}
|
|
35924
|
+
const parentById = buildParentIdMap(parents);
|
|
35753
35925
|
for (const [pid, updateMap] of updatesByParent.entries()) {
|
|
35754
|
-
const parent =
|
|
35926
|
+
const parent = parentById.get(pid);
|
|
35755
35927
|
if (!parent) continue;
|
|
35756
35928
|
const currentRows = getMutableTableRows(parent, subtableCode);
|
|
35757
35929
|
const payloadRows = currentRows.map((row) => {
|
|
@@ -35791,8 +35963,9 @@ async function executeDeleteSubtable(stmt, client, options, _cacheContext) {
|
|
|
35791
35963
|
if (bucket) bucket.push(t.rowIndex);
|
|
35792
35964
|
else byParent.set(t.parentId, [t.rowIndex]);
|
|
35793
35965
|
}
|
|
35966
|
+
const parentById = buildParentIdMap(parents);
|
|
35794
35967
|
for (const [pid, idxs] of byParent.entries()) {
|
|
35795
|
-
const parent =
|
|
35968
|
+
const parent = parentById.get(pid);
|
|
35796
35969
|
if (!parent) continue;
|
|
35797
35970
|
const rows = getMutableTableRows(parent, subtableCode);
|
|
35798
35971
|
const rm = new Set(idxs);
|
|
@@ -35801,6 +35974,14 @@ async function executeDeleteSubtable(stmt, client, options, _cacheContext) {
|
|
|
35801
35974
|
}
|
|
35802
35975
|
return { type: "DELETE", deletedCount: targets.length };
|
|
35803
35976
|
}
|
|
35977
|
+
function buildParentIdMap(parents) {
|
|
35978
|
+
const map2 = /* @__PURE__ */ new Map();
|
|
35979
|
+
for (const p of parents) {
|
|
35980
|
+
const pid = String(p["$id"]?.value ?? "");
|
|
35981
|
+
if (pid) map2.set(pid, p);
|
|
35982
|
+
}
|
|
35983
|
+
return map2;
|
|
35984
|
+
}
|
|
35804
35985
|
function expandRowsForSubtableDml(parents, subtableCode) {
|
|
35805
35986
|
const out = [];
|
|
35806
35987
|
for (const parent of parents) {
|
|
@@ -35936,8 +36117,9 @@ async function executeReorder(stmt, client, options, _cacheContext) {
|
|
|
35936
36117
|
const ok = await options.confirm(targetParentIds.size, "UPDATE");
|
|
35937
36118
|
if (!ok) throw new OperationCancelledError("UPDATE", targetParentIds.size);
|
|
35938
36119
|
}
|
|
36120
|
+
const parentById = buildParentIdMap(parents);
|
|
35939
36121
|
for (const pid of targetParentIds) {
|
|
35940
|
-
const parent =
|
|
36122
|
+
const parent = parentById.get(pid);
|
|
35941
36123
|
if (!parent) continue;
|
|
35942
36124
|
const rows = getMutableTableRows(parent, stmt.subtableCode);
|
|
35943
36125
|
const sortable = rows.map((row, i) => ({ row, i, flat: buildFlatRowForSort(parent, stmt.subtableCode, row, i) }));
|
|
@@ -35985,7 +36167,6 @@ function evalOrderKeyForRow(key, row) {
|
|
|
35985
36167
|
}
|
|
35986
36168
|
}
|
|
35987
36169
|
async function executeUpsertSelect(stmt, client, options, cacheContext) {
|
|
35988
|
-
const maxRecords2 = options.maxRecords ?? 1e4;
|
|
35989
36170
|
const selectResult = await executeSelect(stmt.select, client, options, cacheContext);
|
|
35990
36171
|
const { rows, columns } = selectResult;
|
|
35991
36172
|
if (columns.length !== stmt.fields.length) {
|
|
@@ -36000,29 +36181,26 @@ async function executeUpsertSelect(stmt, client, options, cacheContext) {
|
|
|
36000
36181
|
}
|
|
36001
36182
|
const toInsert = [];
|
|
36002
36183
|
const toUpdate = [];
|
|
36003
|
-
|
|
36184
|
+
const records = rows.map((row) => {
|
|
36004
36185
|
const record2 = {};
|
|
36005
36186
|
stmt.fields.forEach((field, i) => {
|
|
36006
36187
|
record2[field] = { value: row[columns[i]] ?? "" };
|
|
36007
36188
|
});
|
|
36008
|
-
|
|
36009
|
-
|
|
36010
|
-
|
|
36011
|
-
|
|
36012
|
-
|
|
36013
|
-
|
|
36014
|
-
|
|
36015
|
-
|
|
36016
|
-
|
|
36017
|
-
|
|
36018
|
-
{
|
|
36019
|
-
);
|
|
36020
|
-
if (existing.length > 0) {
|
|
36021
|
-
toUpdate.push({ id: Number(existing[0]["$id"].value), record: record2 });
|
|
36189
|
+
return record2;
|
|
36190
|
+
});
|
|
36191
|
+
const fieldTypes = await getFieldTypeMap(stmt.appId, client, cacheContext);
|
|
36192
|
+
const rowKeyValues = records.map(
|
|
36193
|
+
(record2) => stmt.keyFields.map((key) => String(record2[key]?.value ?? ""))
|
|
36194
|
+
);
|
|
36195
|
+
const targetIndex = await resolveUpsertTargets(stmt.appId, stmt.keyFields, rowKeyValues, client, options, fieldTypes);
|
|
36196
|
+
records.forEach((record2, rowIdx) => {
|
|
36197
|
+
const id = lookupUpsertTarget(targetIndex, rowKeyValues[rowIdx]);
|
|
36198
|
+
if (id !== void 0) {
|
|
36199
|
+
toUpdate.push({ id, record: record2 });
|
|
36022
36200
|
} else {
|
|
36023
36201
|
toInsert.push(record2);
|
|
36024
36202
|
}
|
|
36025
|
-
}
|
|
36203
|
+
});
|
|
36026
36204
|
if (options.confirm && toInsert.length + toUpdate.length > 0) {
|
|
36027
36205
|
const total = toInsert.length + toUpdate.length;
|
|
36028
36206
|
const ok = await options.confirm(total, "UPDATE");
|
|
@@ -36074,36 +36252,44 @@ function parseSql(sql) {
|
|
|
36074
36252
|
}
|
|
36075
36253
|
}
|
|
36076
36254
|
async function resolveSubqueries(where, client, options, cacheContext) {
|
|
36255
|
+
const tasks = [];
|
|
36256
|
+
collectSubqueryTasks(where, client, options, cacheContext, tasks);
|
|
36257
|
+
await Promise.all(tasks);
|
|
36258
|
+
}
|
|
36259
|
+
function collectSubqueryTasks(where, client, options, cacheContext, tasks) {
|
|
36077
36260
|
if (where === null) return;
|
|
36078
36261
|
switch (where.type) {
|
|
36079
36262
|
case "BINARY": {
|
|
36080
36263
|
const right = where.right;
|
|
36081
36264
|
if (right.type === "SUBQUERY_IN_LIST") {
|
|
36082
|
-
|
|
36083
|
-
|
|
36084
|
-
|
|
36085
|
-
|
|
36265
|
+
tasks.push(executeSelect(right.query, client, options, cacheContext).then((result) => {
|
|
36266
|
+
const col = right.column ?? (result.columns[0] ?? "");
|
|
36267
|
+
right.resolved = new Set(result.rows.map((r) => r[col] ?? ""));
|
|
36268
|
+
}));
|
|
36086
36269
|
}
|
|
36087
36270
|
if (right.type === "SCALAR_SUBQUERY") {
|
|
36088
|
-
|
|
36089
|
-
|
|
36090
|
-
|
|
36091
|
-
|
|
36092
|
-
|
|
36271
|
+
tasks.push(executeSelect(right.query, client, options, cacheContext).then((result) => {
|
|
36272
|
+
if (result.rowCount === 0) throw new Error("\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u304C\u5024\u3092\u8FD4\u3057\u307E\u305B\u3093\u3067\u3057\u305F");
|
|
36273
|
+
if (result.rowCount > 1) throw new Error("\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u304C\u8907\u6570\u884C\u3092\u8FD4\u3057\u307E\u3057\u305F\uFF081\u884C\u306E\u307F\u8A31\u53EF\uFF09");
|
|
36274
|
+
const col = result.columns[0] ?? "";
|
|
36275
|
+
right.resolved = result.rows[0]?.[col] ?? "";
|
|
36276
|
+
}));
|
|
36093
36277
|
}
|
|
36094
36278
|
break;
|
|
36095
36279
|
}
|
|
36096
36280
|
case "LOGICAL":
|
|
36097
|
-
|
|
36098
|
-
|
|
36281
|
+
collectSubqueryTasks(where.left, client, options, cacheContext, tasks);
|
|
36282
|
+
collectSubqueryTasks(where.right, client, options, cacheContext, tasks);
|
|
36099
36283
|
break;
|
|
36100
36284
|
case "NOT":
|
|
36101
36285
|
case "GROUP":
|
|
36102
|
-
|
|
36286
|
+
collectSubqueryTasks(where.expr, client, options, cacheContext, tasks);
|
|
36103
36287
|
break;
|
|
36104
36288
|
case "EXISTS": {
|
|
36105
|
-
const
|
|
36106
|
-
|
|
36289
|
+
const node = where;
|
|
36290
|
+
tasks.push(executeSelect(node.query, client, options, cacheContext).then((result) => {
|
|
36291
|
+
node.resolved = result.rowCount > 0;
|
|
36292
|
+
}));
|
|
36107
36293
|
break;
|
|
36108
36294
|
}
|
|
36109
36295
|
}
|
|
@@ -36120,16 +36306,27 @@ async function resolveSetSubqueries(assignments, client, options, cacheContext)
|
|
|
36120
36306
|
}
|
|
36121
36307
|
}
|
|
36122
36308
|
async function resolveScalarColumns(columns, client, options, cacheContext) {
|
|
36123
|
-
const
|
|
36309
|
+
const byQuery = /* @__PURE__ */ new Map();
|
|
36310
|
+
const pending = [];
|
|
36124
36311
|
for (let i = 0; i < columns.length; i++) {
|
|
36125
36312
|
const col = columns[i];
|
|
36126
36313
|
if (col.type !== "SCALAR_SUBQUERY_COL") continue;
|
|
36127
|
-
const
|
|
36128
|
-
|
|
36129
|
-
if (
|
|
36130
|
-
|
|
36131
|
-
|
|
36314
|
+
const key = JSON.stringify(col.query);
|
|
36315
|
+
let promise2 = byQuery.get(key);
|
|
36316
|
+
if (!promise2) {
|
|
36317
|
+
promise2 = executeSelect(col.query, client, options, cacheContext).then((result) => {
|
|
36318
|
+
if (result.rowCount === 0) throw new Error("\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u304C\u5024\u3092\u8FD4\u3057\u307E\u305B\u3093\u3067\u3057\u305F");
|
|
36319
|
+
if (result.rowCount > 1) throw new Error("\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u304C\u8907\u6570\u884C\u3092\u8FD4\u3057\u307E\u3057\u305F\uFF081\u884C\u306E\u307F\u8A31\u53EF\uFF09");
|
|
36320
|
+
const firstCol = result.columns[0] ?? "";
|
|
36321
|
+
return result.rows[0]?.[firstCol] ?? "";
|
|
36322
|
+
});
|
|
36323
|
+
byQuery.set(key, promise2);
|
|
36324
|
+
}
|
|
36325
|
+
pending.push([i, promise2]);
|
|
36132
36326
|
}
|
|
36327
|
+
const values = await Promise.all(pending.map(([, promise2]) => promise2));
|
|
36328
|
+
const cache = /* @__PURE__ */ new Map();
|
|
36329
|
+
pending.forEach(([i], idx) => cache.set(i, values[idx]));
|
|
36133
36330
|
return cache;
|
|
36134
36331
|
}
|
|
36135
36332
|
function executeExplain(stmt) {
|
|
@@ -36920,6 +37117,10 @@ async function createKsqlRuntime(serverOptions, input) {
|
|
|
36920
37117
|
const normalized = normalizeSqlAppProfiles(input.sql, profileName);
|
|
36921
37118
|
const sql = normalized.normalizedSql;
|
|
36922
37119
|
const maxRecords2 = input.maxRecords ?? envInt("KSQL_MAX_RECORDS") ?? profile2.query?.maxRecords ?? 500;
|
|
37120
|
+
const fetchParallel2 = input.fetchParallel ?? envInt("KSQL_FETCH_PARALLEL") ?? profile2.query?.fetchParallel ?? 3;
|
|
37121
|
+
if (!Number.isInteger(fetchParallel2) || fetchParallel2 < 1 || fetchParallel2 > 10) {
|
|
37122
|
+
throw new Error("ArgumentError: fetchParallel must be an integer between 1 and 10.");
|
|
37123
|
+
}
|
|
36923
37124
|
const onLimit2 = input.onLimit ?? envOnLimit("KSQL_ON_LIMIT") ?? profile2.query?.onLimit ?? "error";
|
|
36924
37125
|
const timeout2 = input.timeout ?? envInt("KSQL_TIMEOUT") ?? profile2.query?.timeout ?? 3e4;
|
|
36925
37126
|
const appIds = extractAppIds(sql);
|
|
@@ -37051,6 +37252,7 @@ async function createKsqlRuntime(serverOptions, input) {
|
|
|
37051
37252
|
client: routedClient,
|
|
37052
37253
|
cacheContext: buildCacheContext(profileName, normalized.appBindingByMappedApp),
|
|
37053
37254
|
maxRecords: maxRecords2,
|
|
37255
|
+
fetchParallel: fetchParallel2,
|
|
37054
37256
|
onLimit: onLimit2,
|
|
37055
37257
|
timeout: timeout2
|
|
37056
37258
|
};
|
|
@@ -37434,11 +37636,13 @@ function createKsqlMcpTools(serverOptions, deps = {}) {
|
|
|
37434
37636
|
sql: input.sql,
|
|
37435
37637
|
profile: input.profile,
|
|
37436
37638
|
maxRecords: input.maxRecords,
|
|
37639
|
+
fetchParallel: input.fetchParallel,
|
|
37437
37640
|
onLimit: input.onLimit,
|
|
37438
37641
|
timeout: input.timeout
|
|
37439
37642
|
});
|
|
37440
37643
|
const result = await executeSql(runtime.sql, runtime.client, {
|
|
37441
37644
|
maxRecords: runtime.maxRecords,
|
|
37645
|
+
fetchParallel: runtime.fetchParallel,
|
|
37442
37646
|
onLimitReached: runtime.onLimit,
|
|
37443
37647
|
cacheContext: runtime.cacheContext
|
|
37444
37648
|
});
|
|
@@ -37466,11 +37670,13 @@ function createKsqlMcpTools(serverOptions, deps = {}) {
|
|
|
37466
37670
|
sql: input.sql,
|
|
37467
37671
|
profile: input.profile,
|
|
37468
37672
|
maxRecords: dmlMaxRows2 + 1,
|
|
37673
|
+
fetchParallel: input.fetchParallel,
|
|
37469
37674
|
onLimit: DEFAULT_ON_LIMIT,
|
|
37470
37675
|
timeout: input.timeout
|
|
37471
37676
|
});
|
|
37472
37677
|
const result = await executeSql(runtime.sql, runtime.client, {
|
|
37473
37678
|
maxRecords: runtime.maxRecords,
|
|
37679
|
+
fetchParallel: runtime.fetchParallel,
|
|
37474
37680
|
onLimitReached: runtime.onLimit,
|
|
37475
37681
|
cacheContext: runtime.cacheContext,
|
|
37476
37682
|
confirm: async (count, operation) => {
|
|
@@ -37490,6 +37696,7 @@ function createKsqlMcpTools(serverOptions, deps = {}) {
|
|
|
37490
37696
|
sql: `DESCRIBE APP${input.app}`,
|
|
37491
37697
|
profile: input.profile,
|
|
37492
37698
|
maxRecords: input.maxRecords,
|
|
37699
|
+
fetchParallel: input.fetchParallel,
|
|
37493
37700
|
onLimit: input.onLimit,
|
|
37494
37701
|
timeout: input.timeout
|
|
37495
37702
|
});
|
|
@@ -37499,6 +37706,7 @@ function createKsqlMcpTools(serverOptions, deps = {}) {
|
|
|
37499
37706
|
sql: "SHOW APPS",
|
|
37500
37707
|
profile: input.profile,
|
|
37501
37708
|
maxRecords: input.maxRecords,
|
|
37709
|
+
fetchParallel: input.fetchParallel,
|
|
37502
37710
|
onLimit: input.onLimit,
|
|
37503
37711
|
timeout: input.timeout
|
|
37504
37712
|
});
|
|
@@ -37564,6 +37772,7 @@ function createKsqlMcpTools(serverOptions, deps = {}) {
|
|
|
37564
37772
|
sql: saved.sql,
|
|
37565
37773
|
profile: profile2,
|
|
37566
37774
|
maxRecords: input.maxRecords,
|
|
37775
|
+
fetchParallel: input.fetchParallel,
|
|
37567
37776
|
onLimit: input.onLimit,
|
|
37568
37777
|
timeout: input.timeout
|
|
37569
37778
|
});
|
|
@@ -37580,6 +37789,7 @@ function createKsqlMcpTools(serverOptions, deps = {}) {
|
|
|
37580
37789
|
allowDml: true,
|
|
37581
37790
|
confirmText: "yes",
|
|
37582
37791
|
dmlMaxRows: dmlMaxRows2,
|
|
37792
|
+
fetchParallel: input.fetchParallel,
|
|
37583
37793
|
timeout: input.timeout
|
|
37584
37794
|
});
|
|
37585
37795
|
return {
|
|
@@ -37628,6 +37838,7 @@ function createKsqlMcpTools(serverOptions, deps = {}) {
|
|
|
37628
37838
|
// src/mcp/schemas.ts
|
|
37629
37839
|
var profile = external_exports.string().min(1).optional();
|
|
37630
37840
|
var maxRecords = external_exports.number().int().positive().optional();
|
|
37841
|
+
var fetchParallel = external_exports.number().int().min(1).max(10).optional();
|
|
37631
37842
|
var onLimit = external_exports.enum(["error", "truncate"]).optional();
|
|
37632
37843
|
var timeout = external_exports.number().int().positive().optional();
|
|
37633
37844
|
var dmlMaxRows = external_exports.number().int().positive();
|
|
@@ -37645,6 +37856,7 @@ var queryInputSchema = external_exports.object({
|
|
|
37645
37856
|
sql: external_exports.string().min(1),
|
|
37646
37857
|
profile,
|
|
37647
37858
|
maxRecords,
|
|
37859
|
+
fetchParallel,
|
|
37648
37860
|
onLimit,
|
|
37649
37861
|
timeout
|
|
37650
37862
|
});
|
|
@@ -37654,18 +37866,21 @@ var mutateInputSchema = external_exports.object({
|
|
|
37654
37866
|
allowDml: external_exports.literal(true),
|
|
37655
37867
|
confirmText: external_exports.literal("yes"),
|
|
37656
37868
|
dmlMaxRows,
|
|
37869
|
+
fetchParallel,
|
|
37657
37870
|
timeout
|
|
37658
37871
|
});
|
|
37659
37872
|
var describeAppInputSchema = external_exports.object({
|
|
37660
37873
|
app: external_exports.number().int().positive(),
|
|
37661
37874
|
profile,
|
|
37662
37875
|
maxRecords,
|
|
37876
|
+
fetchParallel,
|
|
37663
37877
|
onLimit,
|
|
37664
37878
|
timeout
|
|
37665
37879
|
});
|
|
37666
37880
|
var showAppsInputSchema = external_exports.object({
|
|
37667
37881
|
profile,
|
|
37668
37882
|
maxRecords,
|
|
37883
|
+
fetchParallel,
|
|
37669
37884
|
onLimit,
|
|
37670
37885
|
timeout
|
|
37671
37886
|
});
|
|
@@ -37687,6 +37902,7 @@ var runSavedQueryInputSchema = external_exports.object({
|
|
|
37687
37902
|
name: savedQueryName,
|
|
37688
37903
|
profile,
|
|
37689
37904
|
maxRecords,
|
|
37905
|
+
fetchParallel,
|
|
37690
37906
|
onLimit,
|
|
37691
37907
|
timeout,
|
|
37692
37908
|
allowDml: external_exports.literal(true).optional(),
|