@rex0220/kintone-sql-tools 2.14.1 → 2.15.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 +237 -42
- package/dist-mcp/ksql-mcp.js +238 -43
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -87,6 +87,7 @@ var KEYWORDS = /* @__PURE__ */ new Map([
|
|
|
87
87
|
["AVG", "AVG" /* AVG */],
|
|
88
88
|
["MAX", "MAX" /* MAX */],
|
|
89
89
|
["MIN", "MIN" /* MIN */],
|
|
90
|
+
["GROUP_CONCAT", "GROUP_CONCAT" /* GROUP_CONCAT */],
|
|
90
91
|
["ASSERT", "ASSERT" /* ASSERT */],
|
|
91
92
|
["AND", "AND" /* AND */],
|
|
92
93
|
["OR", "OR" /* OR */],
|
|
@@ -1079,6 +1080,7 @@ var Parser = class {
|
|
|
1079
1080
|
func: ref.func,
|
|
1080
1081
|
distinct: ref.distinct,
|
|
1081
1082
|
arg: ref.arg,
|
|
1083
|
+
...ref.separator !== void 0 ? { separator: ref.separator } : {},
|
|
1082
1084
|
alias: alias2
|
|
1083
1085
|
};
|
|
1084
1086
|
}
|
|
@@ -1450,7 +1452,8 @@ var Parser = class {
|
|
|
1450
1452
|
["SUM" /* SUM */]: "SUM",
|
|
1451
1453
|
["AVG" /* AVG */]: "AVG",
|
|
1452
1454
|
["MAX" /* MAX */]: "MAX",
|
|
1453
|
-
["MIN" /* MIN */]: "MIN"
|
|
1455
|
+
["MIN" /* MIN */]: "MIN",
|
|
1456
|
+
["GROUP_CONCAT" /* GROUP_CONCAT */]: "GROUP_CONCAT"
|
|
1454
1457
|
};
|
|
1455
1458
|
const kind = this.peek().kind;
|
|
1456
1459
|
return map[kind] ?? null;
|
|
@@ -1462,12 +1465,29 @@ var Parser = class {
|
|
|
1462
1465
|
const distinct = this.consume("DISTINCT" /* DISTINCT */);
|
|
1463
1466
|
let arg;
|
|
1464
1467
|
if (this.consume("*" /* STAR */)) {
|
|
1468
|
+
if (func === "GROUP_CONCAT") {
|
|
1469
|
+
throw new ParseError("GROUP_CONCAT(*) \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u30D5\u30A3\u30FC\u30EB\u30C9\u307E\u305F\u306F\u5F0F\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044", this.prev());
|
|
1470
|
+
}
|
|
1465
1471
|
arg = { type: "WILDCARD" };
|
|
1466
1472
|
} else {
|
|
1467
1473
|
arg = this.parseArithAddSub();
|
|
1468
1474
|
}
|
|
1475
|
+
let separator;
|
|
1476
|
+
if (this.isSoftKeyword("SEPARATOR")) {
|
|
1477
|
+
const separatorToken = this.advance();
|
|
1478
|
+
if (func !== "GROUP_CONCAT") {
|
|
1479
|
+
throw new ParseError("SEPARATOR \u306F GROUP_CONCAT \u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059", separatorToken);
|
|
1480
|
+
}
|
|
1481
|
+
separator = this.expect("STRING" /* STRING */, "SEPARATOR \u306E\u5F8C\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059").value;
|
|
1482
|
+
}
|
|
1469
1483
|
this.expect(")" /* RPAREN */);
|
|
1470
|
-
return {
|
|
1484
|
+
return {
|
|
1485
|
+
type: "AGG_REF",
|
|
1486
|
+
func,
|
|
1487
|
+
distinct,
|
|
1488
|
+
arg,
|
|
1489
|
+
...separator !== void 0 ? { separator } : {}
|
|
1490
|
+
};
|
|
1471
1491
|
}
|
|
1472
1492
|
// ----------------------------------------------------------
|
|
1473
1493
|
// FROM / JOIN
|
|
@@ -1745,10 +1765,20 @@ var Parser = class {
|
|
|
1745
1765
|
const distinct = this.consume("DISTINCT" /* DISTINCT */);
|
|
1746
1766
|
let argStr;
|
|
1747
1767
|
if (this.consume("*" /* STAR */)) {
|
|
1768
|
+
if (aggFunc === "GROUP_CONCAT") {
|
|
1769
|
+
throw new ParseError("GROUP_CONCAT(*) \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u30D5\u30A3\u30FC\u30EB\u30C9\u307E\u305F\u306F\u5F0F\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044", this.prev());
|
|
1770
|
+
}
|
|
1748
1771
|
argStr = "*";
|
|
1749
1772
|
} else {
|
|
1750
1773
|
argStr = this.parseIdentifier();
|
|
1751
1774
|
}
|
|
1775
|
+
if (this.isSoftKeyword("SEPARATOR")) {
|
|
1776
|
+
const separatorToken = this.advance();
|
|
1777
|
+
if (aggFunc !== "GROUP_CONCAT") {
|
|
1778
|
+
throw new ParseError("SEPARATOR \u306F GROUP_CONCAT \u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059", separatorToken);
|
|
1779
|
+
}
|
|
1780
|
+
this.expect("STRING" /* STRING */, "SEPARATOR \u306E\u5F8C\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059");
|
|
1781
|
+
}
|
|
1752
1782
|
this.expect(")" /* RPAREN */);
|
|
1753
1783
|
const syntheticName = distinct ? `${aggFunc}(DISTINCT ${argStr})` : `${aggFunc}(${argStr})`;
|
|
1754
1784
|
return { type: "FIELD", tableAlias: null, field: syntheticName };
|
|
@@ -3357,7 +3387,7 @@ function stringFuncLabel(expr) {
|
|
|
3357
3387
|
return `${expr.func}(${args.join(",")})`;
|
|
3358
3388
|
}
|
|
3359
3389
|
function isAggregateSyntheticName(name) {
|
|
3360
|
-
return /^(COUNT|SUM|AVG|MAX|MIN)\(/i.test(name);
|
|
3390
|
+
return /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT)\(/i.test(name);
|
|
3361
3391
|
}
|
|
3362
3392
|
|
|
3363
3393
|
// src/core/cteInlining.ts
|
|
@@ -5123,7 +5153,7 @@ function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
|
|
|
5123
5153
|
for (const col of columns) {
|
|
5124
5154
|
if (col.type === "AGGREGATE") {
|
|
5125
5155
|
const syntheticKey = aggregateSyntheticName2(col.func, col.distinct, col.arg);
|
|
5126
|
-
const value = String(evalAggregate(col.func, col.distinct, col.arg, groupRows, resolveAggSortKind));
|
|
5156
|
+
const value = String(evalAggregate(col.func, col.distinct, col.arg, col.separator, groupRows, resolveAggSortKind));
|
|
5127
5157
|
outRow[col.alias ?? syntheticKey] = value;
|
|
5128
5158
|
if (col.alias) outRow[syntheticKey] = value;
|
|
5129
5159
|
} else if (col.type === "ARITH_AGG_COL") {
|
|
@@ -5144,7 +5174,7 @@ function evalGroupByKey(key, row) {
|
|
|
5144
5174
|
if (key.type === "FUNC_KEY") return evalStringFunc(key.expr, row);
|
|
5145
5175
|
return String(evalArithExpr(key.expr, row));
|
|
5146
5176
|
}
|
|
5147
|
-
function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
5177
|
+
function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind) {
|
|
5148
5178
|
if (arg.type === "WILDCARD") {
|
|
5149
5179
|
return func === "COUNT" ? rows.length : 0;
|
|
5150
5180
|
}
|
|
@@ -5164,6 +5194,7 @@ function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
|
5164
5194
|
}
|
|
5165
5195
|
const eff = distinct ? [...new Set(strValues)] : strValues;
|
|
5166
5196
|
if (func === "COUNT") return eff.length;
|
|
5197
|
+
if (func === "GROUP_CONCAT") return eff.join(separator ?? ",");
|
|
5167
5198
|
const sortKind = (func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" ? resolveAggSortKind?.(toAggregateFieldRef(arg.field)) : void 0;
|
|
5168
5199
|
if (sortKind === "string") {
|
|
5169
5200
|
if (eff.length === 0) return "";
|
|
@@ -5208,7 +5239,7 @@ function minOf(nums) {
|
|
|
5208
5239
|
}
|
|
5209
5240
|
function evalAggArithExpr(node, rows, resolveAggSortKind) {
|
|
5210
5241
|
if (node.type === "NUMBER") return node.value;
|
|
5211
|
-
if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, rows, resolveAggSortKind));
|
|
5242
|
+
if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, node.separator, rows, resolveAggSortKind));
|
|
5212
5243
|
const l = evalAggArithExpr(node.left, rows, resolveAggSortKind);
|
|
5213
5244
|
const r = evalAggArithExpr(node.right, rows, resolveAggSortKind);
|
|
5214
5245
|
switch (node.op) {
|
|
@@ -5557,7 +5588,7 @@ function hasAggregateInStringFuncExpr2(expr) {
|
|
|
5557
5588
|
}
|
|
5558
5589
|
function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
|
|
5559
5590
|
if (arg.type === "AGG_REF") {
|
|
5560
|
-
const value = evalAggregate(arg.func, arg.distinct, arg.arg, rows, resolveAggSortKind);
|
|
5591
|
+
const value = evalAggregate(arg.func, arg.distinct, arg.arg, arg.separator, rows, resolveAggSortKind);
|
|
5561
5592
|
return typeof value === "number" ? { type: "NUMBER", value } : { type: "STRING", value };
|
|
5562
5593
|
}
|
|
5563
5594
|
if (arg.type === "AGG_ARITH") {
|
|
@@ -5803,7 +5834,8 @@ function isValidTemporal(value, type) {
|
|
|
5803
5834
|
const date = new Date(Date.UTC(year, month - 1, day));
|
|
5804
5835
|
if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) return false;
|
|
5805
5836
|
if (type === "DATE") return true;
|
|
5806
|
-
|
|
5837
|
+
const timePart = value.slice(11, value.endsWith("Z") ? -1 : value.length - 6).replace(/\.\d+$/, "");
|
|
5838
|
+
return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2})?(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) && isValidTemporal(timePart, "TIME");
|
|
5807
5839
|
}
|
|
5808
5840
|
|
|
5809
5841
|
// src/core/dmlValidationCandidates.ts
|
|
@@ -5883,6 +5915,8 @@ var SearchAbortedError = class extends Error {
|
|
|
5883
5915
|
this.name = "SearchAbortedError";
|
|
5884
5916
|
}
|
|
5885
5917
|
};
|
|
5918
|
+
var materializedMetaBySelectResult = /* @__PURE__ */ new WeakMap();
|
|
5919
|
+
var materializedMetaByValidationResult = /* @__PURE__ */ new WeakMap();
|
|
5886
5920
|
async function execute(sql, client, options = {}) {
|
|
5887
5921
|
const startedAt = Date.now();
|
|
5888
5922
|
const stmt = parseSql(sql);
|
|
@@ -6028,16 +6062,25 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
|
6028
6062
|
}
|
|
6029
6063
|
}
|
|
6030
6064
|
var TEMP_TABLE_MAX_ROWS = 1e4;
|
|
6031
|
-
function appendValidationErrors(tempTables, name, columns, rows, maxRows) {
|
|
6065
|
+
function appendValidationErrors(tempTables, name, columns, rows, maxRows, columnMeta) {
|
|
6032
6066
|
const current = tempTables.get(name);
|
|
6033
|
-
if (current && (current.columns.length !== columns.length || current.columns.some((c, i) => c !== columns[i]))) {
|
|
6067
|
+
if (current && (current.columns.length !== columns.length || current.columns.some((c, i) => c !== columns[i]) || !materializedColumnMetaEqual(current.columnMeta, columnMeta))) {
|
|
6034
6068
|
throw new Error(`ArgumentError: validation error table ${name} has a different schema.`);
|
|
6035
6069
|
}
|
|
6036
6070
|
const existingRows = current?.rows ?? [];
|
|
6037
6071
|
if (existingRows.length + rows.length > maxRows) {
|
|
6038
6072
|
throw new Error(`ArgumentError: temp table ${name} exceeds max rows (${maxRows}).`);
|
|
6039
6073
|
}
|
|
6040
|
-
tempTables.set(name, { columns: [...columns], rows: [...existingRows, ...rows] });
|
|
6074
|
+
tempTables.set(name, { columns: [...columns], rows: [...existingRows, ...rows], columnMeta });
|
|
6075
|
+
}
|
|
6076
|
+
function materializedColumnMetaEqual(left, right) {
|
|
6077
|
+
if (left === right) return true;
|
|
6078
|
+
if (!left || !right || left.size !== right.size) return false;
|
|
6079
|
+
for (const [column, meta] of left) {
|
|
6080
|
+
const candidate = right.get(column);
|
|
6081
|
+
if (!candidate || candidate.sortKind !== meta.sortKind || candidate.fieldType !== meta.fieldType) return false;
|
|
6082
|
+
}
|
|
6083
|
+
return true;
|
|
6041
6084
|
}
|
|
6042
6085
|
var BatchTimeoutError = class extends Error {
|
|
6043
6086
|
constructor() {
|
|
@@ -6199,7 +6242,8 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
6199
6242
|
resolvedStmt.validationErrorTable,
|
|
6200
6243
|
result.columns,
|
|
6201
6244
|
result.errors,
|
|
6202
|
-
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
|
|
6245
|
+
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
|
|
6246
|
+
materializedMetaByValidationResult.get(result) ?? /* @__PURE__ */ new Map()
|
|
6203
6247
|
);
|
|
6204
6248
|
}
|
|
6205
6249
|
return { result };
|
|
@@ -6223,7 +6267,11 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
6223
6267
|
onLimitReached: "error"
|
|
6224
6268
|
};
|
|
6225
6269
|
const result = await runSelectLike(resolvedStmt.query, client, materializeOptions, cacheContext, tempTables);
|
|
6226
|
-
tempTables.set(resolvedStmt.name, {
|
|
6270
|
+
tempTables.set(resolvedStmt.name, {
|
|
6271
|
+
rows: result.rows,
|
|
6272
|
+
columns: result.columns,
|
|
6273
|
+
columnMeta: materializedMetaBySelectResult.get(result)
|
|
6274
|
+
});
|
|
6227
6275
|
return { tempTable: resolvedStmt.name, rowCount: result.rows.length };
|
|
6228
6276
|
}
|
|
6229
6277
|
if (stmt.type === "DROP_TEMP_TABLE") {
|
|
@@ -6259,9 +6307,9 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
6259
6307
|
}
|
|
6260
6308
|
async function runSelectLike(query, client, options, cacheContext, tempTables) {
|
|
6261
6309
|
if (query.type === "WITH") {
|
|
6262
|
-
return executeWith(query, client, options, cacheContext, tempTables);
|
|
6310
|
+
return executeWith(query, client, options, cacheContext, tempTables, true);
|
|
6263
6311
|
}
|
|
6264
|
-
return executeQueryWithCte(query, client, options, tempTables, cacheContext);
|
|
6312
|
+
return executeQueryWithCte(query, client, options, tempTables, cacheContext, true);
|
|
6265
6313
|
}
|
|
6266
6314
|
async function runWithDeadline(work, remainingMs) {
|
|
6267
6315
|
if (remainingMs === null) return work;
|
|
@@ -6474,18 +6522,27 @@ function evalAssertArith(node) {
|
|
|
6474
6522
|
}
|
|
6475
6523
|
throw new Error(`ArgumentError: unsupported operand in ASSERT expression: ${node.type}`);
|
|
6476
6524
|
}
|
|
6477
|
-
async function executeSelect(stmt, client, options, cacheContext, cteCache) {
|
|
6525
|
+
async function executeSelect(stmt, client, options, cacheContext, cteCache, captureColumnMeta = false) {
|
|
6526
|
+
let result;
|
|
6478
6527
|
if (isNoFromSelect(stmt)) {
|
|
6479
|
-
|
|
6528
|
+
result = executeNoFromSelect(stmt);
|
|
6529
|
+
if (captureColumnMeta) {
|
|
6530
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
|
|
6531
|
+
}
|
|
6532
|
+
return result;
|
|
6480
6533
|
}
|
|
6481
6534
|
await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache);
|
|
6482
6535
|
const mode = resolveSelectMode(stmt);
|
|
6483
6536
|
await validateSelectFieldCodes(stmt, mode, client, cacheContext);
|
|
6484
6537
|
if (mode === "SIMPLE") {
|
|
6485
|
-
|
|
6538
|
+
result = await executeSimpleSelect(stmt, client, options, cacheContext);
|
|
6486
6539
|
} else {
|
|
6487
|
-
|
|
6540
|
+
result = await executeFullScanSelect(stmt, client, options, cacheContext, cteCache);
|
|
6488
6541
|
}
|
|
6542
|
+
if (captureColumnMeta) {
|
|
6543
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
|
|
6544
|
+
}
|
|
6545
|
+
return result;
|
|
6489
6546
|
}
|
|
6490
6547
|
function isNoFromSelect(stmt) {
|
|
6491
6548
|
return stmt.from.appId === 0 && stmt.from.cteName === NO_FROM_CTE_NAME;
|
|
@@ -6809,7 +6866,7 @@ function aggregateSortKind(info) {
|
|
|
6809
6866
|
if (info.fieldType === "NUMBER" || info.fieldType === "RECORD_NUMBER") return "number";
|
|
6810
6867
|
return AGGREGATE_STRING_FIELD_TYPES.has(info.fieldType) ? "string" : void 0;
|
|
6811
6868
|
}
|
|
6812
|
-
async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
6869
|
+
async function loadAggregateSortKindResolver(stmt, client, cacheContext, materializedTables) {
|
|
6813
6870
|
const refs = collectSelectAggregateSortRefs(stmt.columns);
|
|
6814
6871
|
if (refs.length === 0) return void 0;
|
|
6815
6872
|
const appIds = /* @__PURE__ */ new Set();
|
|
@@ -6825,11 +6882,9 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
|
6825
6882
|
} else if (stmt.joins.length === 0) {
|
|
6826
6883
|
if (stmt.from.cteName === null) appIds.add(stmt.from.appId);
|
|
6827
6884
|
} else {
|
|
6828
|
-
if ([stmt.from, ...stmt.joins.map((join2) => join2.table)].some((table) => table.cteName !== null)) continue;
|
|
6829
6885
|
for (const table of physicalTables) appIds.add(table.appId);
|
|
6830
6886
|
}
|
|
6831
6887
|
}
|
|
6832
|
-
if (appIds.size === 0) return void 0;
|
|
6833
6888
|
const fieldInfosByApp = new Map(
|
|
6834
6889
|
await Promise.all([...appIds].map(async (appId) => {
|
|
6835
6890
|
const infos = await getFieldsCached(appId, client, cacheContext);
|
|
@@ -6844,17 +6899,28 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
|
6844
6899
|
info = fieldInfosByApp.get(stmt.from.appId)?.get(ref.field);
|
|
6845
6900
|
} else {
|
|
6846
6901
|
const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
|
|
6847
|
-
if (!table
|
|
6902
|
+
if (!table) return void 0;
|
|
6903
|
+
if (table.cteName !== null) {
|
|
6904
|
+
return materializedTables?.get(table.cteName)?.columnMeta?.get(ref.field)?.sortKind;
|
|
6905
|
+
}
|
|
6848
6906
|
info = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
6849
6907
|
}
|
|
6850
6908
|
} else if (stmt.joins.length === 0) {
|
|
6851
|
-
if (stmt.from.cteName !== null)
|
|
6909
|
+
if (stmt.from.cteName !== null) {
|
|
6910
|
+
return materializedTables?.get(stmt.from.cteName)?.columnMeta?.get(ref.field)?.sortKind;
|
|
6911
|
+
}
|
|
6852
6912
|
info = fieldInfosByApp.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
|
|
6853
6913
|
} else {
|
|
6854
|
-
|
|
6855
|
-
|
|
6914
|
+
const matches = tables.flatMap((table) => {
|
|
6915
|
+
if (table.cteName !== null) {
|
|
6916
|
+
const materialized = materializedTables?.get(table.cteName);
|
|
6917
|
+
return materialized?.columns.includes(ref.field) ? [materialized.columnMeta?.get(ref.field)?.sortKind] : [];
|
|
6918
|
+
}
|
|
6919
|
+
const candidate = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
6920
|
+
return candidate ? [aggregateSortKind(candidate)] : [];
|
|
6921
|
+
});
|
|
6856
6922
|
if (matches.length !== 1) return void 0;
|
|
6857
|
-
|
|
6923
|
+
return matches[0];
|
|
6858
6924
|
}
|
|
6859
6925
|
return info ? aggregateSortKind(info) : void 0;
|
|
6860
6926
|
};
|
|
@@ -6863,6 +6929,106 @@ function fieldCodeForTypeLookup(table, field) {
|
|
|
6863
6929
|
if (table.subtableCode && field.startsWith("_p.")) return field.slice(3);
|
|
6864
6930
|
return field;
|
|
6865
6931
|
}
|
|
6932
|
+
function materializedMetaFromFieldInfo(info) {
|
|
6933
|
+
return { sortKind: aggregateSortKind(info), fieldType: info.fieldType };
|
|
6934
|
+
}
|
|
6935
|
+
function selectNeedsSourceColumnMeta(stmt) {
|
|
6936
|
+
return stmt.columns.some(
|
|
6937
|
+
(column) => column.type === "FIELD" || column.type === "WILDCARD" || column.type === "PARENT_WILDCARD" || column.type === "AGGREGATE" && (column.func === "MIN" || column.func === "MAX") && column.arg.type === "FIELD_REF"
|
|
6938
|
+
);
|
|
6939
|
+
}
|
|
6940
|
+
async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext, materializedTables) {
|
|
6941
|
+
const physicalInfos = /* @__PURE__ */ new Map();
|
|
6942
|
+
if (selectNeedsSourceColumnMeta(stmt)) {
|
|
6943
|
+
await Promise.all(physicalSelectTables(stmt).map(async (table) => {
|
|
6944
|
+
if (physicalInfos.has(table.appId)) return;
|
|
6945
|
+
const infos = await getFieldsCached(table.appId, client, cacheContext);
|
|
6946
|
+
physicalInfos.set(table.appId, new Map(infos.map((info) => [info.code, info])));
|
|
6947
|
+
}));
|
|
6948
|
+
}
|
|
6949
|
+
const tables = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
6950
|
+
const resolveField2 = (ref) => {
|
|
6951
|
+
if (ref.tableAlias !== null) {
|
|
6952
|
+
if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
6953
|
+
const info2 = physicalInfos.get(stmt.from.appId)?.get(ref.field);
|
|
6954
|
+
return info2 ? materializedMetaFromFieldInfo(info2) : void 0;
|
|
6955
|
+
}
|
|
6956
|
+
const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
|
|
6957
|
+
if (!table) return void 0;
|
|
6958
|
+
if (table.cteName !== null) return materializedTables?.get(table.cteName)?.columnMeta?.get(ref.field);
|
|
6959
|
+
const info = physicalInfos.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
6960
|
+
return info ? materializedMetaFromFieldInfo(info) : void 0;
|
|
6961
|
+
}
|
|
6962
|
+
if (stmt.joins.length === 0) {
|
|
6963
|
+
if (stmt.from.cteName !== null) return materializedTables?.get(stmt.from.cteName)?.columnMeta?.get(ref.field);
|
|
6964
|
+
const info = physicalInfos.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
|
|
6965
|
+
return info ? materializedMetaFromFieldInfo(info) : void 0;
|
|
6966
|
+
}
|
|
6967
|
+
const matches = tables.flatMap((table) => {
|
|
6968
|
+
if (table.cteName !== null) {
|
|
6969
|
+
const materialized = materializedTables?.get(table.cteName);
|
|
6970
|
+
if (!materialized?.columns.includes(ref.field)) return [];
|
|
6971
|
+
return [materialized.columnMeta?.get(ref.field)];
|
|
6972
|
+
}
|
|
6973
|
+
const info = physicalInfos.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
6974
|
+
return info ? [materializedMetaFromFieldInfo(info)] : [];
|
|
6975
|
+
});
|
|
6976
|
+
return matches.length === 1 ? matches[0] : void 0;
|
|
6977
|
+
};
|
|
6978
|
+
const inferred = /* @__PURE__ */ new Map();
|
|
6979
|
+
const hasWildcard = stmt.columns.some((column) => column.type === "WILDCARD" || column.type === "PARENT_WILDCARD");
|
|
6980
|
+
if (stmt.columns.length === 1 && (stmt.columns[0].type === "WILDCARD" || stmt.columns[0].type === "PARENT_WILDCARD")) {
|
|
6981
|
+
for (const output of outputColumns) {
|
|
6982
|
+
const meta = resolveField2(aggregateFieldRef(output));
|
|
6983
|
+
if (meta) inferred.set(output, meta);
|
|
6984
|
+
}
|
|
6985
|
+
return inferred;
|
|
6986
|
+
}
|
|
6987
|
+
if (hasWildcard) {
|
|
6988
|
+
for (const output of outputColumns) {
|
|
6989
|
+
const meta = resolveField2(aggregateFieldRef(output));
|
|
6990
|
+
if (meta) inferred.set(output, meta);
|
|
6991
|
+
}
|
|
6992
|
+
}
|
|
6993
|
+
const explicitColumns = stmt.columns.filter(
|
|
6994
|
+
(column) => column.type !== "WILDCARD" && column.type !== "PARENT_WILDCARD"
|
|
6995
|
+
);
|
|
6996
|
+
explicitColumns.forEach((column, index) => {
|
|
6997
|
+
const output = hasWildcard ? "alias" in column && column.alias ? column.alias : void 0 : outputColumns[index];
|
|
6998
|
+
if (!output) return;
|
|
6999
|
+
let meta;
|
|
7000
|
+
if (column.type === "FIELD") {
|
|
7001
|
+
meta = resolveField2(aggregateFieldRef(column.field));
|
|
7002
|
+
} else if (column.type === "AGGREGATE") {
|
|
7003
|
+
if (column.func === "GROUP_CONCAT") {
|
|
7004
|
+
meta = { sortKind: "string" };
|
|
7005
|
+
} else if (column.func === "COUNT" || column.func === "SUM" || column.func === "AVG") {
|
|
7006
|
+
meta = { sortKind: "number" };
|
|
7007
|
+
} else if ((column.func === "MIN" || column.func === "MAX") && column.arg.type === "FIELD_REF") {
|
|
7008
|
+
const source = resolveField2(aggregateFieldRef(column.arg.field));
|
|
7009
|
+
if (source?.sortKind) meta = { sortKind: source.sortKind };
|
|
7010
|
+
}
|
|
7011
|
+
} else if (column.type === "ARITH_AGG_COL" || column.type === "ARITH_COL") {
|
|
7012
|
+
meta = { sortKind: "number" };
|
|
7013
|
+
} else if (column.type === "LITERAL_COL") {
|
|
7014
|
+
meta = { sortKind: "string" };
|
|
7015
|
+
}
|
|
7016
|
+
if (meta) inferred.set(output, meta);
|
|
7017
|
+
});
|
|
7018
|
+
return inferred;
|
|
7019
|
+
}
|
|
7020
|
+
function mergeUnionColumnMeta(left, right) {
|
|
7021
|
+
const leftMeta = materializedMetaBySelectResult.get(left);
|
|
7022
|
+
const rightMeta = materializedMetaBySelectResult.get(right);
|
|
7023
|
+
const merged = /* @__PURE__ */ new Map();
|
|
7024
|
+
left.columns.forEach((column, index) => {
|
|
7025
|
+
const a = leftMeta?.get(column);
|
|
7026
|
+
const rightColumn = right.columns[index];
|
|
7027
|
+
const b = rightColumn === void 0 ? void 0 : rightMeta?.get(rightColumn);
|
|
7028
|
+
if (a && b && a.sortKind === b.sortKind && a.fieldType === b.fieldType) merged.set(column, a);
|
|
7029
|
+
});
|
|
7030
|
+
return merged;
|
|
7031
|
+
}
|
|
6866
7032
|
function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
|
|
6867
7033
|
const tables = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
6868
7034
|
const physicalTables = tables.filter((table) => table.cteName === null);
|
|
@@ -6907,7 +7073,7 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
6907
7073
|
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
6908
7074
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
6909
7075
|
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
6910
|
-
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
7076
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
|
|
6911
7077
|
]);
|
|
6912
7078
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
6913
7079
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -7027,9 +7193,9 @@ function deduplicateRows(rows, columns) {
|
|
|
7027
7193
|
return true;
|
|
7028
7194
|
});
|
|
7029
7195
|
}
|
|
7030
|
-
async function executeWith(stmt, client, options, cacheContext, seed) {
|
|
7196
|
+
async function executeWith(stmt, client, options, cacheContext, seed, captureColumnMeta = false) {
|
|
7031
7197
|
if ((seed == null || seed.size === 0) && canInlineSingleCte(stmt)) {
|
|
7032
|
-
return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext);
|
|
7198
|
+
return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext, void 0, captureColumnMeta);
|
|
7033
7199
|
}
|
|
7034
7200
|
const cteCache = new Map(seed ?? []);
|
|
7035
7201
|
for (const cte of stmt.ctes) {
|
|
@@ -7039,17 +7205,21 @@ async function executeWith(stmt, client, options, cacheContext, seed) {
|
|
|
7039
7205
|
} else if (cte.query.type === "DESCRIBE") {
|
|
7040
7206
|
result = await executeDescribe(cte.query, client, cacheContext);
|
|
7041
7207
|
} else {
|
|
7042
|
-
result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext);
|
|
7208
|
+
result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext, true);
|
|
7043
7209
|
}
|
|
7044
|
-
cteCache.set(cte.name, {
|
|
7210
|
+
cteCache.set(cte.name, {
|
|
7211
|
+
rows: result.rows,
|
|
7212
|
+
columns: result.columns,
|
|
7213
|
+
columnMeta: materializedMetaBySelectResult.get(result)
|
|
7214
|
+
});
|
|
7045
7215
|
}
|
|
7046
|
-
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext);
|
|
7216
|
+
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext, captureColumnMeta);
|
|
7047
7217
|
}
|
|
7048
|
-
async function executeQueryWithCte(query, client, options, cteCache, cacheContext) {
|
|
7218
|
+
async function executeQueryWithCte(query, client, options, cteCache, cacheContext, captureColumnMeta = false) {
|
|
7049
7219
|
if (query.type === "UNION") {
|
|
7050
7220
|
const [leftResult, rightResult] = await Promise.all([
|
|
7051
|
-
executeQueryWithCte(query.left, client, options, cteCache, cacheContext),
|
|
7052
|
-
executeQueryWithCte(query.right, client, options, cteCache, cacheContext)
|
|
7221
|
+
executeQueryWithCte(query.left, client, options, cteCache, cacheContext, captureColumnMeta),
|
|
7222
|
+
executeQueryWithCte(query.right, client, options, cteCache, cacheContext, captureColumnMeta)
|
|
7053
7223
|
]);
|
|
7054
7224
|
const leftCols = leftResult.columns;
|
|
7055
7225
|
const rightCols = rightResult.columns;
|
|
@@ -7062,13 +7232,21 @@ async function executeQueryWithCte(query, client, options, cteCache, cacheContex
|
|
|
7062
7232
|
});
|
|
7063
7233
|
const combined = [...leftResult.rows, ...remapped];
|
|
7064
7234
|
const rows = query.all ? combined : deduplicateRows(combined, leftCols);
|
|
7065
|
-
|
|
7235
|
+
const result2 = { type: "SELECT", rows, columns: leftCols, rowCount: rows.length };
|
|
7236
|
+
if (captureColumnMeta) {
|
|
7237
|
+
materializedMetaBySelectResult.set(result2, mergeUnionColumnMeta(leftResult, rightResult));
|
|
7238
|
+
}
|
|
7239
|
+
return result2;
|
|
7066
7240
|
}
|
|
7067
7241
|
const hasCteRef = query.from.cteName != null && query.from.cteName !== NO_FROM_CTE_NAME || query.joins.some((j) => j.table.cteName != null);
|
|
7068
7242
|
if (!hasCteRef) {
|
|
7069
|
-
return executeSelect(query, client, options, cacheContext, cteCache);
|
|
7243
|
+
return executeSelect(query, client, options, cacheContext, cteCache, captureColumnMeta);
|
|
7244
|
+
}
|
|
7245
|
+
const result = await executeFullScanWithCte(query, client, options, cteCache, cacheContext);
|
|
7246
|
+
if (captureColumnMeta) {
|
|
7247
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(query, result.columns, client, cacheContext, cteCache));
|
|
7070
7248
|
}
|
|
7071
|
-
return
|
|
7249
|
+
return result;
|
|
7072
7250
|
}
|
|
7073
7251
|
async function executeFullScanWithCte(stmt, client, options, cteCache, cacheContext) {
|
|
7074
7252
|
const maxRecords = options.maxRecords ?? 1e4;
|
|
@@ -7082,7 +7260,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
7082
7260
|
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
7083
7261
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
7084
7262
|
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
7085
|
-
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
7263
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
|
|
7086
7264
|
]);
|
|
7087
7265
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
7088
7266
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -7560,7 +7738,23 @@ async function prepareDmlValidation(stmt, client, options, cacheContext, tempTab
|
|
|
7560
7738
|
errors,
|
|
7561
7739
|
...stmt.validationErrorTable ? { errTable: stmt.validationErrorTable } : stmt.onErrorSkip && stmt.errorTable ? { errTable: stmt.errorTable } : {}
|
|
7562
7740
|
};
|
|
7563
|
-
|
|
7741
|
+
const columnMeta = /* @__PURE__ */ new Map();
|
|
7742
|
+
for (const column of payloadFields) {
|
|
7743
|
+
if (column === "$id") {
|
|
7744
|
+
columnMeta.set(column, { sortKind: "number", fieldType: "RECORD_NUMBER" });
|
|
7745
|
+
continue;
|
|
7746
|
+
}
|
|
7747
|
+
const info = infoByCode.get(column);
|
|
7748
|
+
if (info) columnMeta.set(column, materializedMetaFromFieldInfo(info));
|
|
7749
|
+
}
|
|
7750
|
+
columnMeta.set("$err_statement", { sortKind: "number" });
|
|
7751
|
+
columnMeta.set("$err_operation", { sortKind: "string" });
|
|
7752
|
+
columnMeta.set("$err_row", { sortKind: "number" });
|
|
7753
|
+
columnMeta.set("$err_field", { sortKind: "string" });
|
|
7754
|
+
columnMeta.set("$err_code", { sortKind: "string" });
|
|
7755
|
+
columnMeta.set("$err_message", { sortKind: "string" });
|
|
7756
|
+
materializedMetaByValidationResult.set(result, columnMeta);
|
|
7757
|
+
return { result, candidates, invalidRowNumbers, columnMeta };
|
|
7564
7758
|
}
|
|
7565
7759
|
async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTables, statementNumber) {
|
|
7566
7760
|
const prepared = await prepareDmlValidation(
|
|
@@ -7578,7 +7772,8 @@ async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTable
|
|
|
7578
7772
|
errTable,
|
|
7579
7773
|
prepared.result.columns,
|
|
7580
7774
|
prepared.result.errors,
|
|
7581
|
-
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
|
|
7775
|
+
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
|
|
7776
|
+
prepared.columnMeta
|
|
7582
7777
|
);
|
|
7583
7778
|
const rejectLimit = stmt.rejectLimit ?? null;
|
|
7584
7779
|
if (rejectLimit !== null && prepared.result.invalidRows > rejectLimit) {
|
package/dist-mcp/ksql-mcp.js
CHANGED
|
@@ -30999,6 +30999,7 @@ var KEYWORDS = /* @__PURE__ */ new Map([
|
|
|
30999
30999
|
["AVG", "AVG" /* AVG */],
|
|
31000
31000
|
["MAX", "MAX" /* MAX */],
|
|
31001
31001
|
["MIN", "MIN" /* MIN */],
|
|
31002
|
+
["GROUP_CONCAT", "GROUP_CONCAT" /* GROUP_CONCAT */],
|
|
31002
31003
|
["ASSERT", "ASSERT" /* ASSERT */],
|
|
31003
31004
|
["AND", "AND" /* AND */],
|
|
31004
31005
|
["OR", "OR" /* OR */],
|
|
@@ -31991,6 +31992,7 @@ var Parser = class {
|
|
|
31991
31992
|
func: ref.func,
|
|
31992
31993
|
distinct: ref.distinct,
|
|
31993
31994
|
arg: ref.arg,
|
|
31995
|
+
...ref.separator !== void 0 ? { separator: ref.separator } : {},
|
|
31994
31996
|
alias: alias2
|
|
31995
31997
|
};
|
|
31996
31998
|
}
|
|
@@ -32362,7 +32364,8 @@ var Parser = class {
|
|
|
32362
32364
|
["SUM" /* SUM */]: "SUM",
|
|
32363
32365
|
["AVG" /* AVG */]: "AVG",
|
|
32364
32366
|
["MAX" /* MAX */]: "MAX",
|
|
32365
|
-
["MIN" /* MIN */]: "MIN"
|
|
32367
|
+
["MIN" /* MIN */]: "MIN",
|
|
32368
|
+
["GROUP_CONCAT" /* GROUP_CONCAT */]: "GROUP_CONCAT"
|
|
32366
32369
|
};
|
|
32367
32370
|
const kind = this.peek().kind;
|
|
32368
32371
|
return map2[kind] ?? null;
|
|
@@ -32374,12 +32377,29 @@ var Parser = class {
|
|
|
32374
32377
|
const distinct = this.consume("DISTINCT" /* DISTINCT */);
|
|
32375
32378
|
let arg;
|
|
32376
32379
|
if (this.consume("*" /* STAR */)) {
|
|
32380
|
+
if (func === "GROUP_CONCAT") {
|
|
32381
|
+
throw new ParseError("GROUP_CONCAT(*) \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u30D5\u30A3\u30FC\u30EB\u30C9\u307E\u305F\u306F\u5F0F\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044", this.prev());
|
|
32382
|
+
}
|
|
32377
32383
|
arg = { type: "WILDCARD" };
|
|
32378
32384
|
} else {
|
|
32379
32385
|
arg = this.parseArithAddSub();
|
|
32380
32386
|
}
|
|
32387
|
+
let separator;
|
|
32388
|
+
if (this.isSoftKeyword("SEPARATOR")) {
|
|
32389
|
+
const separatorToken = this.advance();
|
|
32390
|
+
if (func !== "GROUP_CONCAT") {
|
|
32391
|
+
throw new ParseError("SEPARATOR \u306F GROUP_CONCAT \u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059", separatorToken);
|
|
32392
|
+
}
|
|
32393
|
+
separator = this.expect("STRING" /* STRING */, "SEPARATOR \u306E\u5F8C\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059").value;
|
|
32394
|
+
}
|
|
32381
32395
|
this.expect(")" /* RPAREN */);
|
|
32382
|
-
return {
|
|
32396
|
+
return {
|
|
32397
|
+
type: "AGG_REF",
|
|
32398
|
+
func,
|
|
32399
|
+
distinct,
|
|
32400
|
+
arg,
|
|
32401
|
+
...separator !== void 0 ? { separator } : {}
|
|
32402
|
+
};
|
|
32383
32403
|
}
|
|
32384
32404
|
// ----------------------------------------------------------
|
|
32385
32405
|
// FROM / JOIN
|
|
@@ -32657,10 +32677,20 @@ var Parser = class {
|
|
|
32657
32677
|
const distinct = this.consume("DISTINCT" /* DISTINCT */);
|
|
32658
32678
|
let argStr;
|
|
32659
32679
|
if (this.consume("*" /* STAR */)) {
|
|
32680
|
+
if (aggFunc === "GROUP_CONCAT") {
|
|
32681
|
+
throw new ParseError("GROUP_CONCAT(*) \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u30D5\u30A3\u30FC\u30EB\u30C9\u307E\u305F\u306F\u5F0F\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044", this.prev());
|
|
32682
|
+
}
|
|
32660
32683
|
argStr = "*";
|
|
32661
32684
|
} else {
|
|
32662
32685
|
argStr = this.parseIdentifier();
|
|
32663
32686
|
}
|
|
32687
|
+
if (this.isSoftKeyword("SEPARATOR")) {
|
|
32688
|
+
const separatorToken = this.advance();
|
|
32689
|
+
if (aggFunc !== "GROUP_CONCAT") {
|
|
32690
|
+
throw new ParseError("SEPARATOR \u306F GROUP_CONCAT \u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059", separatorToken);
|
|
32691
|
+
}
|
|
32692
|
+
this.expect("STRING" /* STRING */, "SEPARATOR \u306E\u5F8C\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059");
|
|
32693
|
+
}
|
|
32664
32694
|
this.expect(")" /* RPAREN */);
|
|
32665
32695
|
const syntheticName = distinct ? `${aggFunc}(DISTINCT ${argStr})` : `${aggFunc}(${argStr})`;
|
|
32666
32696
|
return { type: "FIELD", tableAlias: null, field: syntheticName };
|
|
@@ -34257,7 +34287,7 @@ function stringFuncLabel(expr) {
|
|
|
34257
34287
|
return `${expr.func}(${args.join(",")})`;
|
|
34258
34288
|
}
|
|
34259
34289
|
function isAggregateSyntheticName(name) {
|
|
34260
|
-
return /^(COUNT|SUM|AVG|MAX|MIN)\(/i.test(name);
|
|
34290
|
+
return /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT)\(/i.test(name);
|
|
34261
34291
|
}
|
|
34262
34292
|
|
|
34263
34293
|
// src/core/cteInlining.ts
|
|
@@ -36023,7 +36053,7 @@ function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
|
|
|
36023
36053
|
for (const col of columns) {
|
|
36024
36054
|
if (col.type === "AGGREGATE") {
|
|
36025
36055
|
const syntheticKey = aggregateSyntheticName2(col.func, col.distinct, col.arg);
|
|
36026
|
-
const value = String(evalAggregate(col.func, col.distinct, col.arg, groupRows, resolveAggSortKind));
|
|
36056
|
+
const value = String(evalAggregate(col.func, col.distinct, col.arg, col.separator, groupRows, resolveAggSortKind));
|
|
36027
36057
|
outRow[col.alias ?? syntheticKey] = value;
|
|
36028
36058
|
if (col.alias) outRow[syntheticKey] = value;
|
|
36029
36059
|
} else if (col.type === "ARITH_AGG_COL") {
|
|
@@ -36044,7 +36074,7 @@ function evalGroupByKey(key, row) {
|
|
|
36044
36074
|
if (key.type === "FUNC_KEY") return evalStringFunc(key.expr, row);
|
|
36045
36075
|
return String(evalArithExpr(key.expr, row));
|
|
36046
36076
|
}
|
|
36047
|
-
function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
36077
|
+
function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind) {
|
|
36048
36078
|
if (arg.type === "WILDCARD") {
|
|
36049
36079
|
return func === "COUNT" ? rows.length : 0;
|
|
36050
36080
|
}
|
|
@@ -36064,6 +36094,7 @@ function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
|
36064
36094
|
}
|
|
36065
36095
|
const eff = distinct ? [...new Set(strValues)] : strValues;
|
|
36066
36096
|
if (func === "COUNT") return eff.length;
|
|
36097
|
+
if (func === "GROUP_CONCAT") return eff.join(separator ?? ",");
|
|
36067
36098
|
const sortKind = (func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" ? resolveAggSortKind?.(toAggregateFieldRef(arg.field)) : void 0;
|
|
36068
36099
|
if (sortKind === "string") {
|
|
36069
36100
|
if (eff.length === 0) return "";
|
|
@@ -36108,7 +36139,7 @@ function minOf(nums) {
|
|
|
36108
36139
|
}
|
|
36109
36140
|
function evalAggArithExpr(node, rows, resolveAggSortKind) {
|
|
36110
36141
|
if (node.type === "NUMBER") return node.value;
|
|
36111
|
-
if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, rows, resolveAggSortKind));
|
|
36142
|
+
if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, node.separator, rows, resolveAggSortKind));
|
|
36112
36143
|
const l = evalAggArithExpr(node.left, rows, resolveAggSortKind);
|
|
36113
36144
|
const r = evalAggArithExpr(node.right, rows, resolveAggSortKind);
|
|
36114
36145
|
switch (node.op) {
|
|
@@ -36457,7 +36488,7 @@ function hasAggregateInStringFuncExpr2(expr) {
|
|
|
36457
36488
|
}
|
|
36458
36489
|
function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
|
|
36459
36490
|
if (arg.type === "AGG_REF") {
|
|
36460
|
-
const value = evalAggregate(arg.func, arg.distinct, arg.arg, rows, resolveAggSortKind);
|
|
36491
|
+
const value = evalAggregate(arg.func, arg.distinct, arg.arg, arg.separator, rows, resolveAggSortKind);
|
|
36461
36492
|
return typeof value === "number" ? { type: "NUMBER", value } : { type: "STRING", value };
|
|
36462
36493
|
}
|
|
36463
36494
|
if (arg.type === "AGG_ARITH") {
|
|
@@ -36703,7 +36734,8 @@ function isValidTemporal(value, type) {
|
|
|
36703
36734
|
const date5 = new Date(Date.UTC(year, month - 1, day));
|
|
36704
36735
|
if (date5.getUTCFullYear() !== year || date5.getUTCMonth() !== month - 1 || date5.getUTCDate() !== day) return false;
|
|
36705
36736
|
if (type === "DATE") return true;
|
|
36706
|
-
|
|
36737
|
+
const timePart = value.slice(11, value.endsWith("Z") ? -1 : value.length - 6).replace(/\.\d+$/, "");
|
|
36738
|
+
return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2})?(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) && isValidTemporal(timePart, "TIME");
|
|
36707
36739
|
}
|
|
36708
36740
|
|
|
36709
36741
|
// src/core/dmlValidationCandidates.ts
|
|
@@ -36783,6 +36815,8 @@ var SearchAbortedError = class extends Error {
|
|
|
36783
36815
|
this.name = "SearchAbortedError";
|
|
36784
36816
|
}
|
|
36785
36817
|
};
|
|
36818
|
+
var materializedMetaBySelectResult = /* @__PURE__ */ new WeakMap();
|
|
36819
|
+
var materializedMetaByValidationResult = /* @__PURE__ */ new WeakMap();
|
|
36786
36820
|
async function execute(sql, client, options = {}) {
|
|
36787
36821
|
const startedAt = Date.now();
|
|
36788
36822
|
const stmt = parseSql(sql);
|
|
@@ -36928,16 +36962,25 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
|
36928
36962
|
}
|
|
36929
36963
|
}
|
|
36930
36964
|
var TEMP_TABLE_MAX_ROWS = 1e4;
|
|
36931
|
-
function appendValidationErrors(tempTables, name, columns, rows, maxRows) {
|
|
36965
|
+
function appendValidationErrors(tempTables, name, columns, rows, maxRows, columnMeta) {
|
|
36932
36966
|
const current = tempTables.get(name);
|
|
36933
|
-
if (current && (current.columns.length !== columns.length || current.columns.some((c, i) => c !== columns[i]))) {
|
|
36967
|
+
if (current && (current.columns.length !== columns.length || current.columns.some((c, i) => c !== columns[i]) || !materializedColumnMetaEqual(current.columnMeta, columnMeta))) {
|
|
36934
36968
|
throw new Error(`ArgumentError: validation error table ${name} has a different schema.`);
|
|
36935
36969
|
}
|
|
36936
36970
|
const existingRows = current?.rows ?? [];
|
|
36937
36971
|
if (existingRows.length + rows.length > maxRows) {
|
|
36938
36972
|
throw new Error(`ArgumentError: temp table ${name} exceeds max rows (${maxRows}).`);
|
|
36939
36973
|
}
|
|
36940
|
-
tempTables.set(name, { columns: [...columns], rows: [...existingRows, ...rows] });
|
|
36974
|
+
tempTables.set(name, { columns: [...columns], rows: [...existingRows, ...rows], columnMeta });
|
|
36975
|
+
}
|
|
36976
|
+
function materializedColumnMetaEqual(left, right) {
|
|
36977
|
+
if (left === right) return true;
|
|
36978
|
+
if (!left || !right || left.size !== right.size) return false;
|
|
36979
|
+
for (const [column, meta3] of left) {
|
|
36980
|
+
const candidate = right.get(column);
|
|
36981
|
+
if (!candidate || candidate.sortKind !== meta3.sortKind || candidate.fieldType !== meta3.fieldType) return false;
|
|
36982
|
+
}
|
|
36983
|
+
return true;
|
|
36941
36984
|
}
|
|
36942
36985
|
var BatchTimeoutError = class extends Error {
|
|
36943
36986
|
constructor() {
|
|
@@ -37099,7 +37142,8 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
37099
37142
|
resolvedStmt.validationErrorTable,
|
|
37100
37143
|
result.columns,
|
|
37101
37144
|
result.errors,
|
|
37102
|
-
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
|
|
37145
|
+
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
|
|
37146
|
+
materializedMetaByValidationResult.get(result) ?? /* @__PURE__ */ new Map()
|
|
37103
37147
|
);
|
|
37104
37148
|
}
|
|
37105
37149
|
return { result };
|
|
@@ -37123,7 +37167,11 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
37123
37167
|
onLimitReached: "error"
|
|
37124
37168
|
};
|
|
37125
37169
|
const result = await runSelectLike(resolvedStmt.query, client, materializeOptions, cacheContext, tempTables);
|
|
37126
|
-
tempTables.set(resolvedStmt.name, {
|
|
37170
|
+
tempTables.set(resolvedStmt.name, {
|
|
37171
|
+
rows: result.rows,
|
|
37172
|
+
columns: result.columns,
|
|
37173
|
+
columnMeta: materializedMetaBySelectResult.get(result)
|
|
37174
|
+
});
|
|
37127
37175
|
return { tempTable: resolvedStmt.name, rowCount: result.rows.length };
|
|
37128
37176
|
}
|
|
37129
37177
|
if (stmt.type === "DROP_TEMP_TABLE") {
|
|
@@ -37159,9 +37207,9 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
37159
37207
|
}
|
|
37160
37208
|
async function runSelectLike(query, client, options, cacheContext, tempTables) {
|
|
37161
37209
|
if (query.type === "WITH") {
|
|
37162
|
-
return executeWith(query, client, options, cacheContext, tempTables);
|
|
37210
|
+
return executeWith(query, client, options, cacheContext, tempTables, true);
|
|
37163
37211
|
}
|
|
37164
|
-
return executeQueryWithCte(query, client, options, tempTables, cacheContext);
|
|
37212
|
+
return executeQueryWithCte(query, client, options, tempTables, cacheContext, true);
|
|
37165
37213
|
}
|
|
37166
37214
|
async function runWithDeadline(work, remainingMs) {
|
|
37167
37215
|
if (remainingMs === null) return work;
|
|
@@ -37374,18 +37422,27 @@ function evalAssertArith(node) {
|
|
|
37374
37422
|
}
|
|
37375
37423
|
throw new Error(`ArgumentError: unsupported operand in ASSERT expression: ${node.type}`);
|
|
37376
37424
|
}
|
|
37377
|
-
async function executeSelect(stmt, client, options, cacheContext, cteCache) {
|
|
37425
|
+
async function executeSelect(stmt, client, options, cacheContext, cteCache, captureColumnMeta = false) {
|
|
37426
|
+
let result;
|
|
37378
37427
|
if (isNoFromSelect(stmt)) {
|
|
37379
|
-
|
|
37428
|
+
result = executeNoFromSelect(stmt);
|
|
37429
|
+
if (captureColumnMeta) {
|
|
37430
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
|
|
37431
|
+
}
|
|
37432
|
+
return result;
|
|
37380
37433
|
}
|
|
37381
37434
|
await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache);
|
|
37382
37435
|
const mode = resolveSelectMode(stmt);
|
|
37383
37436
|
await validateSelectFieldCodes(stmt, mode, client, cacheContext);
|
|
37384
37437
|
if (mode === "SIMPLE") {
|
|
37385
|
-
|
|
37438
|
+
result = await executeSimpleSelect(stmt, client, options, cacheContext);
|
|
37386
37439
|
} else {
|
|
37387
|
-
|
|
37440
|
+
result = await executeFullScanSelect(stmt, client, options, cacheContext, cteCache);
|
|
37388
37441
|
}
|
|
37442
|
+
if (captureColumnMeta) {
|
|
37443
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
|
|
37444
|
+
}
|
|
37445
|
+
return result;
|
|
37389
37446
|
}
|
|
37390
37447
|
function isNoFromSelect(stmt) {
|
|
37391
37448
|
return stmt.from.appId === 0 && stmt.from.cteName === NO_FROM_CTE_NAME;
|
|
@@ -37709,7 +37766,7 @@ function aggregateSortKind(info) {
|
|
|
37709
37766
|
if (info.fieldType === "NUMBER" || info.fieldType === "RECORD_NUMBER") return "number";
|
|
37710
37767
|
return AGGREGATE_STRING_FIELD_TYPES.has(info.fieldType) ? "string" : void 0;
|
|
37711
37768
|
}
|
|
37712
|
-
async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
37769
|
+
async function loadAggregateSortKindResolver(stmt, client, cacheContext, materializedTables) {
|
|
37713
37770
|
const refs = collectSelectAggregateSortRefs(stmt.columns);
|
|
37714
37771
|
if (refs.length === 0) return void 0;
|
|
37715
37772
|
const appIds = /* @__PURE__ */ new Set();
|
|
@@ -37725,11 +37782,9 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
|
37725
37782
|
} else if (stmt.joins.length === 0) {
|
|
37726
37783
|
if (stmt.from.cteName === null) appIds.add(stmt.from.appId);
|
|
37727
37784
|
} else {
|
|
37728
|
-
if ([stmt.from, ...stmt.joins.map((join) => join.table)].some((table) => table.cteName !== null)) continue;
|
|
37729
37785
|
for (const table of physicalTables) appIds.add(table.appId);
|
|
37730
37786
|
}
|
|
37731
37787
|
}
|
|
37732
|
-
if (appIds.size === 0) return void 0;
|
|
37733
37788
|
const fieldInfosByApp = new Map(
|
|
37734
37789
|
await Promise.all([...appIds].map(async (appId) => {
|
|
37735
37790
|
const infos = await getFieldsCached(appId, client, cacheContext);
|
|
@@ -37744,17 +37799,28 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
|
37744
37799
|
info = fieldInfosByApp.get(stmt.from.appId)?.get(ref.field);
|
|
37745
37800
|
} else {
|
|
37746
37801
|
const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
|
|
37747
|
-
if (!table
|
|
37802
|
+
if (!table) return void 0;
|
|
37803
|
+
if (table.cteName !== null) {
|
|
37804
|
+
return materializedTables?.get(table.cteName)?.columnMeta?.get(ref.field)?.sortKind;
|
|
37805
|
+
}
|
|
37748
37806
|
info = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
37749
37807
|
}
|
|
37750
37808
|
} else if (stmt.joins.length === 0) {
|
|
37751
|
-
if (stmt.from.cteName !== null)
|
|
37809
|
+
if (stmt.from.cteName !== null) {
|
|
37810
|
+
return materializedTables?.get(stmt.from.cteName)?.columnMeta?.get(ref.field)?.sortKind;
|
|
37811
|
+
}
|
|
37752
37812
|
info = fieldInfosByApp.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
|
|
37753
37813
|
} else {
|
|
37754
|
-
|
|
37755
|
-
|
|
37814
|
+
const matches = tables.flatMap((table) => {
|
|
37815
|
+
if (table.cteName !== null) {
|
|
37816
|
+
const materialized = materializedTables?.get(table.cteName);
|
|
37817
|
+
return materialized?.columns.includes(ref.field) ? [materialized.columnMeta?.get(ref.field)?.sortKind] : [];
|
|
37818
|
+
}
|
|
37819
|
+
const candidate = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
37820
|
+
return candidate ? [aggregateSortKind(candidate)] : [];
|
|
37821
|
+
});
|
|
37756
37822
|
if (matches.length !== 1) return void 0;
|
|
37757
|
-
|
|
37823
|
+
return matches[0];
|
|
37758
37824
|
}
|
|
37759
37825
|
return info ? aggregateSortKind(info) : void 0;
|
|
37760
37826
|
};
|
|
@@ -37763,6 +37829,106 @@ function fieldCodeForTypeLookup(table, field) {
|
|
|
37763
37829
|
if (table.subtableCode && field.startsWith("_p.")) return field.slice(3);
|
|
37764
37830
|
return field;
|
|
37765
37831
|
}
|
|
37832
|
+
function materializedMetaFromFieldInfo(info) {
|
|
37833
|
+
return { sortKind: aggregateSortKind(info), fieldType: info.fieldType };
|
|
37834
|
+
}
|
|
37835
|
+
function selectNeedsSourceColumnMeta(stmt) {
|
|
37836
|
+
return stmt.columns.some(
|
|
37837
|
+
(column) => column.type === "FIELD" || column.type === "WILDCARD" || column.type === "PARENT_WILDCARD" || column.type === "AGGREGATE" && (column.func === "MIN" || column.func === "MAX") && column.arg.type === "FIELD_REF"
|
|
37838
|
+
);
|
|
37839
|
+
}
|
|
37840
|
+
async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext, materializedTables) {
|
|
37841
|
+
const physicalInfos = /* @__PURE__ */ new Map();
|
|
37842
|
+
if (selectNeedsSourceColumnMeta(stmt)) {
|
|
37843
|
+
await Promise.all(physicalSelectTables(stmt).map(async (table) => {
|
|
37844
|
+
if (physicalInfos.has(table.appId)) return;
|
|
37845
|
+
const infos = await getFieldsCached(table.appId, client, cacheContext);
|
|
37846
|
+
physicalInfos.set(table.appId, new Map(infos.map((info) => [info.code, info])));
|
|
37847
|
+
}));
|
|
37848
|
+
}
|
|
37849
|
+
const tables = [stmt.from, ...stmt.joins.map((join) => join.table)];
|
|
37850
|
+
const resolveField2 = (ref) => {
|
|
37851
|
+
if (ref.tableAlias !== null) {
|
|
37852
|
+
if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
37853
|
+
const info2 = physicalInfos.get(stmt.from.appId)?.get(ref.field);
|
|
37854
|
+
return info2 ? materializedMetaFromFieldInfo(info2) : void 0;
|
|
37855
|
+
}
|
|
37856
|
+
const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
|
|
37857
|
+
if (!table) return void 0;
|
|
37858
|
+
if (table.cteName !== null) return materializedTables?.get(table.cteName)?.columnMeta?.get(ref.field);
|
|
37859
|
+
const info = physicalInfos.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
37860
|
+
return info ? materializedMetaFromFieldInfo(info) : void 0;
|
|
37861
|
+
}
|
|
37862
|
+
if (stmt.joins.length === 0) {
|
|
37863
|
+
if (stmt.from.cteName !== null) return materializedTables?.get(stmt.from.cteName)?.columnMeta?.get(ref.field);
|
|
37864
|
+
const info = physicalInfos.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
|
|
37865
|
+
return info ? materializedMetaFromFieldInfo(info) : void 0;
|
|
37866
|
+
}
|
|
37867
|
+
const matches = tables.flatMap((table) => {
|
|
37868
|
+
if (table.cteName !== null) {
|
|
37869
|
+
const materialized = materializedTables?.get(table.cteName);
|
|
37870
|
+
if (!materialized?.columns.includes(ref.field)) return [];
|
|
37871
|
+
return [materialized.columnMeta?.get(ref.field)];
|
|
37872
|
+
}
|
|
37873
|
+
const info = physicalInfos.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
37874
|
+
return info ? [materializedMetaFromFieldInfo(info)] : [];
|
|
37875
|
+
});
|
|
37876
|
+
return matches.length === 1 ? matches[0] : void 0;
|
|
37877
|
+
};
|
|
37878
|
+
const inferred = /* @__PURE__ */ new Map();
|
|
37879
|
+
const hasWildcard = stmt.columns.some((column) => column.type === "WILDCARD" || column.type === "PARENT_WILDCARD");
|
|
37880
|
+
if (stmt.columns.length === 1 && (stmt.columns[0].type === "WILDCARD" || stmt.columns[0].type === "PARENT_WILDCARD")) {
|
|
37881
|
+
for (const output of outputColumns) {
|
|
37882
|
+
const meta3 = resolveField2(aggregateFieldRef(output));
|
|
37883
|
+
if (meta3) inferred.set(output, meta3);
|
|
37884
|
+
}
|
|
37885
|
+
return inferred;
|
|
37886
|
+
}
|
|
37887
|
+
if (hasWildcard) {
|
|
37888
|
+
for (const output of outputColumns) {
|
|
37889
|
+
const meta3 = resolveField2(aggregateFieldRef(output));
|
|
37890
|
+
if (meta3) inferred.set(output, meta3);
|
|
37891
|
+
}
|
|
37892
|
+
}
|
|
37893
|
+
const explicitColumns = stmt.columns.filter(
|
|
37894
|
+
(column) => column.type !== "WILDCARD" && column.type !== "PARENT_WILDCARD"
|
|
37895
|
+
);
|
|
37896
|
+
explicitColumns.forEach((column, index) => {
|
|
37897
|
+
const output = hasWildcard ? "alias" in column && column.alias ? column.alias : void 0 : outputColumns[index];
|
|
37898
|
+
if (!output) return;
|
|
37899
|
+
let meta3;
|
|
37900
|
+
if (column.type === "FIELD") {
|
|
37901
|
+
meta3 = resolveField2(aggregateFieldRef(column.field));
|
|
37902
|
+
} else if (column.type === "AGGREGATE") {
|
|
37903
|
+
if (column.func === "GROUP_CONCAT") {
|
|
37904
|
+
meta3 = { sortKind: "string" };
|
|
37905
|
+
} else if (column.func === "COUNT" || column.func === "SUM" || column.func === "AVG") {
|
|
37906
|
+
meta3 = { sortKind: "number" };
|
|
37907
|
+
} else if ((column.func === "MIN" || column.func === "MAX") && column.arg.type === "FIELD_REF") {
|
|
37908
|
+
const source = resolveField2(aggregateFieldRef(column.arg.field));
|
|
37909
|
+
if (source?.sortKind) meta3 = { sortKind: source.sortKind };
|
|
37910
|
+
}
|
|
37911
|
+
} else if (column.type === "ARITH_AGG_COL" || column.type === "ARITH_COL") {
|
|
37912
|
+
meta3 = { sortKind: "number" };
|
|
37913
|
+
} else if (column.type === "LITERAL_COL") {
|
|
37914
|
+
meta3 = { sortKind: "string" };
|
|
37915
|
+
}
|
|
37916
|
+
if (meta3) inferred.set(output, meta3);
|
|
37917
|
+
});
|
|
37918
|
+
return inferred;
|
|
37919
|
+
}
|
|
37920
|
+
function mergeUnionColumnMeta(left, right) {
|
|
37921
|
+
const leftMeta = materializedMetaBySelectResult.get(left);
|
|
37922
|
+
const rightMeta = materializedMetaBySelectResult.get(right);
|
|
37923
|
+
const merged = /* @__PURE__ */ new Map();
|
|
37924
|
+
left.columns.forEach((column, index) => {
|
|
37925
|
+
const a = leftMeta?.get(column);
|
|
37926
|
+
const rightColumn = right.columns[index];
|
|
37927
|
+
const b = rightColumn === void 0 ? void 0 : rightMeta?.get(rightColumn);
|
|
37928
|
+
if (a && b && a.sortKind === b.sortKind && a.fieldType === b.fieldType) merged.set(column, a);
|
|
37929
|
+
});
|
|
37930
|
+
return merged;
|
|
37931
|
+
}
|
|
37766
37932
|
function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
|
|
37767
37933
|
const tables = [stmt.from, ...stmt.joins.map((join) => join.table)];
|
|
37768
37934
|
const physicalTables = tables.filter((table) => table.cteName === null);
|
|
@@ -37807,7 +37973,7 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
37807
37973
|
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
37808
37974
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
37809
37975
|
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
37810
|
-
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
37976
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
|
|
37811
37977
|
]);
|
|
37812
37978
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
37813
37979
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -37927,9 +38093,9 @@ function deduplicateRows(rows, columns) {
|
|
|
37927
38093
|
return true;
|
|
37928
38094
|
});
|
|
37929
38095
|
}
|
|
37930
|
-
async function executeWith(stmt, client, options, cacheContext, seed) {
|
|
38096
|
+
async function executeWith(stmt, client, options, cacheContext, seed, captureColumnMeta = false) {
|
|
37931
38097
|
if ((seed == null || seed.size === 0) && canInlineSingleCte(stmt)) {
|
|
37932
|
-
return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext);
|
|
38098
|
+
return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext, void 0, captureColumnMeta);
|
|
37933
38099
|
}
|
|
37934
38100
|
const cteCache = new Map(seed ?? []);
|
|
37935
38101
|
for (const cte of stmt.ctes) {
|
|
@@ -37939,17 +38105,21 @@ async function executeWith(stmt, client, options, cacheContext, seed) {
|
|
|
37939
38105
|
} else if (cte.query.type === "DESCRIBE") {
|
|
37940
38106
|
result = await executeDescribe(cte.query, client, cacheContext);
|
|
37941
38107
|
} else {
|
|
37942
|
-
result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext);
|
|
38108
|
+
result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext, true);
|
|
37943
38109
|
}
|
|
37944
|
-
cteCache.set(cte.name, {
|
|
38110
|
+
cteCache.set(cte.name, {
|
|
38111
|
+
rows: result.rows,
|
|
38112
|
+
columns: result.columns,
|
|
38113
|
+
columnMeta: materializedMetaBySelectResult.get(result)
|
|
38114
|
+
});
|
|
37945
38115
|
}
|
|
37946
|
-
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext);
|
|
38116
|
+
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext, captureColumnMeta);
|
|
37947
38117
|
}
|
|
37948
|
-
async function executeQueryWithCte(query, client, options, cteCache, cacheContext) {
|
|
38118
|
+
async function executeQueryWithCte(query, client, options, cteCache, cacheContext, captureColumnMeta = false) {
|
|
37949
38119
|
if (query.type === "UNION") {
|
|
37950
38120
|
const [leftResult, rightResult] = await Promise.all([
|
|
37951
|
-
executeQueryWithCte(query.left, client, options, cteCache, cacheContext),
|
|
37952
|
-
executeQueryWithCte(query.right, client, options, cteCache, cacheContext)
|
|
38121
|
+
executeQueryWithCte(query.left, client, options, cteCache, cacheContext, captureColumnMeta),
|
|
38122
|
+
executeQueryWithCte(query.right, client, options, cteCache, cacheContext, captureColumnMeta)
|
|
37953
38123
|
]);
|
|
37954
38124
|
const leftCols = leftResult.columns;
|
|
37955
38125
|
const rightCols = rightResult.columns;
|
|
@@ -37962,13 +38132,21 @@ async function executeQueryWithCte(query, client, options, cteCache, cacheContex
|
|
|
37962
38132
|
});
|
|
37963
38133
|
const combined = [...leftResult.rows, ...remapped];
|
|
37964
38134
|
const rows = query.all ? combined : deduplicateRows(combined, leftCols);
|
|
37965
|
-
|
|
38135
|
+
const result2 = { type: "SELECT", rows, columns: leftCols, rowCount: rows.length };
|
|
38136
|
+
if (captureColumnMeta) {
|
|
38137
|
+
materializedMetaBySelectResult.set(result2, mergeUnionColumnMeta(leftResult, rightResult));
|
|
38138
|
+
}
|
|
38139
|
+
return result2;
|
|
37966
38140
|
}
|
|
37967
38141
|
const hasCteRef = query.from.cteName != null && query.from.cteName !== NO_FROM_CTE_NAME || query.joins.some((j) => j.table.cteName != null);
|
|
37968
38142
|
if (!hasCteRef) {
|
|
37969
|
-
return executeSelect(query, client, options, cacheContext, cteCache);
|
|
38143
|
+
return executeSelect(query, client, options, cacheContext, cteCache, captureColumnMeta);
|
|
38144
|
+
}
|
|
38145
|
+
const result = await executeFullScanWithCte(query, client, options, cteCache, cacheContext);
|
|
38146
|
+
if (captureColumnMeta) {
|
|
38147
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(query, result.columns, client, cacheContext, cteCache));
|
|
37970
38148
|
}
|
|
37971
|
-
return
|
|
38149
|
+
return result;
|
|
37972
38150
|
}
|
|
37973
38151
|
async function executeFullScanWithCte(stmt, client, options, cteCache, cacheContext) {
|
|
37974
38152
|
const maxRecords2 = options.maxRecords ?? 1e4;
|
|
@@ -37982,7 +38160,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
37982
38160
|
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
37983
38161
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
37984
38162
|
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
37985
|
-
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
38163
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
|
|
37986
38164
|
]);
|
|
37987
38165
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
37988
38166
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -38460,7 +38638,23 @@ async function prepareDmlValidation(stmt, client, options, cacheContext, tempTab
|
|
|
38460
38638
|
errors,
|
|
38461
38639
|
...stmt.validationErrorTable ? { errTable: stmt.validationErrorTable } : stmt.onErrorSkip && stmt.errorTable ? { errTable: stmt.errorTable } : {}
|
|
38462
38640
|
};
|
|
38463
|
-
|
|
38641
|
+
const columnMeta = /* @__PURE__ */ new Map();
|
|
38642
|
+
for (const column of payloadFields) {
|
|
38643
|
+
if (column === "$id") {
|
|
38644
|
+
columnMeta.set(column, { sortKind: "number", fieldType: "RECORD_NUMBER" });
|
|
38645
|
+
continue;
|
|
38646
|
+
}
|
|
38647
|
+
const info = infoByCode.get(column);
|
|
38648
|
+
if (info) columnMeta.set(column, materializedMetaFromFieldInfo(info));
|
|
38649
|
+
}
|
|
38650
|
+
columnMeta.set("$err_statement", { sortKind: "number" });
|
|
38651
|
+
columnMeta.set("$err_operation", { sortKind: "string" });
|
|
38652
|
+
columnMeta.set("$err_row", { sortKind: "number" });
|
|
38653
|
+
columnMeta.set("$err_field", { sortKind: "string" });
|
|
38654
|
+
columnMeta.set("$err_code", { sortKind: "string" });
|
|
38655
|
+
columnMeta.set("$err_message", { sortKind: "string" });
|
|
38656
|
+
materializedMetaByValidationResult.set(result, columnMeta);
|
|
38657
|
+
return { result, candidates, invalidRowNumbers, columnMeta };
|
|
38464
38658
|
}
|
|
38465
38659
|
async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTables, statementNumber) {
|
|
38466
38660
|
const prepared = await prepareDmlValidation(
|
|
@@ -38478,7 +38672,8 @@ async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTable
|
|
|
38478
38672
|
errTable,
|
|
38479
38673
|
prepared.result.columns,
|
|
38480
38674
|
prepared.result.errors,
|
|
38481
|
-
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
|
|
38675
|
+
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
|
|
38676
|
+
prepared.columnMeta
|
|
38482
38677
|
);
|
|
38483
38678
|
const rejectLimit = stmt.rejectLimit ?? null;
|
|
38484
38679
|
if (rejectLimit !== null && prepared.result.invalidRows > rejectLimit) {
|
|
@@ -42219,7 +42414,7 @@ Options:
|
|
|
42219
42414
|
-h, --help Show help
|
|
42220
42415
|
`);
|
|
42221
42416
|
}
|
|
42222
|
-
var SERVER_VERSION = true ? "2.
|
|
42417
|
+
var SERVER_VERSION = true ? "2.15.0" : "0.0.0-dev";
|
|
42223
42418
|
function createServer(args) {
|
|
42224
42419
|
const server = new McpServer({
|
|
42225
42420
|
name: "ksql-mcp",
|
package/dist-mcpb/ksql-mcp.mcpb
CHANGED
|
Binary file
|