@rex0220/kintone-sql-tools 2.14.0 → 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 +247 -43
- package/dist-mcp/ksql-mcp.js +248 -44
- 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 };
|
|
@@ -1842,16 +1872,25 @@ var Parser = class {
|
|
|
1842
1872
|
// IN リストの値
|
|
1843
1873
|
parseInValues() {
|
|
1844
1874
|
const values = [];
|
|
1875
|
+
const invalidValueMessage = "IN \u30EA\u30B9\u30C8\u306B\u306F\u6587\u5B57\u5217\u3001\u6570\u5024\u3001\u307E\u305F\u306F\u30D0\u30C3\u30C1\u5909\u6570\u304C\u5FC5\u8981\u3067\u3059";
|
|
1845
1876
|
do {
|
|
1846
1877
|
const tok = this.advance();
|
|
1847
1878
|
if (tok.kind === "STRING" /* STRING */) {
|
|
1848
1879
|
values.push({ type: "STRING", value: tok.value });
|
|
1849
1880
|
} else if (tok.kind === "NUMBER" /* NUMBER */) {
|
|
1850
1881
|
values.push({ type: "NUMBER", value: Number(tok.value) });
|
|
1882
|
+
} else if (tok.kind === "-" /* MINUS */ || tok.kind === "+" /* PLUS */) {
|
|
1883
|
+
const number = this.peek();
|
|
1884
|
+
if (number.kind !== "NUMBER" /* NUMBER */) {
|
|
1885
|
+
throw new ParseError(invalidValueMessage, tok);
|
|
1886
|
+
}
|
|
1887
|
+
this.advance();
|
|
1888
|
+
const sign = tok.kind === "-" /* MINUS */ ? -1 : 1;
|
|
1889
|
+
values.push({ type: "NUMBER", value: sign * Number(number.value) });
|
|
1851
1890
|
} else if (tok.kind === "VARIABLE" /* VARIABLE */) {
|
|
1852
1891
|
values.push({ type: "VARIABLE", name: tok.value.slice(1).toLowerCase() });
|
|
1853
1892
|
} else {
|
|
1854
|
-
throw new ParseError(
|
|
1893
|
+
throw new ParseError(invalidValueMessage, tok);
|
|
1855
1894
|
}
|
|
1856
1895
|
} while (this.consume("," /* COMMA */));
|
|
1857
1896
|
return values;
|
|
@@ -3348,7 +3387,7 @@ function stringFuncLabel(expr) {
|
|
|
3348
3387
|
return `${expr.func}(${args.join(",")})`;
|
|
3349
3388
|
}
|
|
3350
3389
|
function isAggregateSyntheticName(name) {
|
|
3351
|
-
return /^(COUNT|SUM|AVG|MAX|MIN)\(/i.test(name);
|
|
3390
|
+
return /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT)\(/i.test(name);
|
|
3352
3391
|
}
|
|
3353
3392
|
|
|
3354
3393
|
// src/core/cteInlining.ts
|
|
@@ -5114,7 +5153,7 @@ function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
|
|
|
5114
5153
|
for (const col of columns) {
|
|
5115
5154
|
if (col.type === "AGGREGATE") {
|
|
5116
5155
|
const syntheticKey = aggregateSyntheticName2(col.func, col.distinct, col.arg);
|
|
5117
|
-
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));
|
|
5118
5157
|
outRow[col.alias ?? syntheticKey] = value;
|
|
5119
5158
|
if (col.alias) outRow[syntheticKey] = value;
|
|
5120
5159
|
} else if (col.type === "ARITH_AGG_COL") {
|
|
@@ -5135,7 +5174,7 @@ function evalGroupByKey(key, row) {
|
|
|
5135
5174
|
if (key.type === "FUNC_KEY") return evalStringFunc(key.expr, row);
|
|
5136
5175
|
return String(evalArithExpr(key.expr, row));
|
|
5137
5176
|
}
|
|
5138
|
-
function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
5177
|
+
function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind) {
|
|
5139
5178
|
if (arg.type === "WILDCARD") {
|
|
5140
5179
|
return func === "COUNT" ? rows.length : 0;
|
|
5141
5180
|
}
|
|
@@ -5155,6 +5194,7 @@ function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
|
5155
5194
|
}
|
|
5156
5195
|
const eff = distinct ? [...new Set(strValues)] : strValues;
|
|
5157
5196
|
if (func === "COUNT") return eff.length;
|
|
5197
|
+
if (func === "GROUP_CONCAT") return eff.join(separator ?? ",");
|
|
5158
5198
|
const sortKind = (func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" ? resolveAggSortKind?.(toAggregateFieldRef(arg.field)) : void 0;
|
|
5159
5199
|
if (sortKind === "string") {
|
|
5160
5200
|
if (eff.length === 0) return "";
|
|
@@ -5199,7 +5239,7 @@ function minOf(nums) {
|
|
|
5199
5239
|
}
|
|
5200
5240
|
function evalAggArithExpr(node, rows, resolveAggSortKind) {
|
|
5201
5241
|
if (node.type === "NUMBER") return node.value;
|
|
5202
|
-
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));
|
|
5203
5243
|
const l = evalAggArithExpr(node.left, rows, resolveAggSortKind);
|
|
5204
5244
|
const r = evalAggArithExpr(node.right, rows, resolveAggSortKind);
|
|
5205
5245
|
switch (node.op) {
|
|
@@ -5548,7 +5588,7 @@ function hasAggregateInStringFuncExpr2(expr) {
|
|
|
5548
5588
|
}
|
|
5549
5589
|
function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
|
|
5550
5590
|
if (arg.type === "AGG_REF") {
|
|
5551
|
-
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);
|
|
5552
5592
|
return typeof value === "number" ? { type: "NUMBER", value } : { type: "STRING", value };
|
|
5553
5593
|
}
|
|
5554
5594
|
if (arg.type === "AGG_ARITH") {
|
|
@@ -5794,7 +5834,8 @@ function isValidTemporal(value, type) {
|
|
|
5794
5834
|
const date = new Date(Date.UTC(year, month - 1, day));
|
|
5795
5835
|
if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) return false;
|
|
5796
5836
|
if (type === "DATE") return true;
|
|
5797
|
-
|
|
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");
|
|
5798
5839
|
}
|
|
5799
5840
|
|
|
5800
5841
|
// src/core/dmlValidationCandidates.ts
|
|
@@ -5874,6 +5915,8 @@ var SearchAbortedError = class extends Error {
|
|
|
5874
5915
|
this.name = "SearchAbortedError";
|
|
5875
5916
|
}
|
|
5876
5917
|
};
|
|
5918
|
+
var materializedMetaBySelectResult = /* @__PURE__ */ new WeakMap();
|
|
5919
|
+
var materializedMetaByValidationResult = /* @__PURE__ */ new WeakMap();
|
|
5877
5920
|
async function execute(sql, client, options = {}) {
|
|
5878
5921
|
const startedAt = Date.now();
|
|
5879
5922
|
const stmt = parseSql(sql);
|
|
@@ -6019,16 +6062,25 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
|
6019
6062
|
}
|
|
6020
6063
|
}
|
|
6021
6064
|
var TEMP_TABLE_MAX_ROWS = 1e4;
|
|
6022
|
-
function appendValidationErrors(tempTables, name, columns, rows, maxRows) {
|
|
6065
|
+
function appendValidationErrors(tempTables, name, columns, rows, maxRows, columnMeta) {
|
|
6023
6066
|
const current = tempTables.get(name);
|
|
6024
|
-
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))) {
|
|
6025
6068
|
throw new Error(`ArgumentError: validation error table ${name} has a different schema.`);
|
|
6026
6069
|
}
|
|
6027
6070
|
const existingRows = current?.rows ?? [];
|
|
6028
6071
|
if (existingRows.length + rows.length > maxRows) {
|
|
6029
6072
|
throw new Error(`ArgumentError: temp table ${name} exceeds max rows (${maxRows}).`);
|
|
6030
6073
|
}
|
|
6031
|
-
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;
|
|
6032
6084
|
}
|
|
6033
6085
|
var BatchTimeoutError = class extends Error {
|
|
6034
6086
|
constructor() {
|
|
@@ -6190,7 +6242,8 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
6190
6242
|
resolvedStmt.validationErrorTable,
|
|
6191
6243
|
result.columns,
|
|
6192
6244
|
result.errors,
|
|
6193
|
-
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
|
|
6245
|
+
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
|
|
6246
|
+
materializedMetaByValidationResult.get(result) ?? /* @__PURE__ */ new Map()
|
|
6194
6247
|
);
|
|
6195
6248
|
}
|
|
6196
6249
|
return { result };
|
|
@@ -6214,7 +6267,11 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
6214
6267
|
onLimitReached: "error"
|
|
6215
6268
|
};
|
|
6216
6269
|
const result = await runSelectLike(resolvedStmt.query, client, materializeOptions, cacheContext, tempTables);
|
|
6217
|
-
tempTables.set(resolvedStmt.name, {
|
|
6270
|
+
tempTables.set(resolvedStmt.name, {
|
|
6271
|
+
rows: result.rows,
|
|
6272
|
+
columns: result.columns,
|
|
6273
|
+
columnMeta: materializedMetaBySelectResult.get(result)
|
|
6274
|
+
});
|
|
6218
6275
|
return { tempTable: resolvedStmt.name, rowCount: result.rows.length };
|
|
6219
6276
|
}
|
|
6220
6277
|
if (stmt.type === "DROP_TEMP_TABLE") {
|
|
@@ -6250,9 +6307,9 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
6250
6307
|
}
|
|
6251
6308
|
async function runSelectLike(query, client, options, cacheContext, tempTables) {
|
|
6252
6309
|
if (query.type === "WITH") {
|
|
6253
|
-
return executeWith(query, client, options, cacheContext, tempTables);
|
|
6310
|
+
return executeWith(query, client, options, cacheContext, tempTables, true);
|
|
6254
6311
|
}
|
|
6255
|
-
return executeQueryWithCte(query, client, options, tempTables, cacheContext);
|
|
6312
|
+
return executeQueryWithCte(query, client, options, tempTables, cacheContext, true);
|
|
6256
6313
|
}
|
|
6257
6314
|
async function runWithDeadline(work, remainingMs) {
|
|
6258
6315
|
if (remainingMs === null) return work;
|
|
@@ -6465,18 +6522,27 @@ function evalAssertArith(node) {
|
|
|
6465
6522
|
}
|
|
6466
6523
|
throw new Error(`ArgumentError: unsupported operand in ASSERT expression: ${node.type}`);
|
|
6467
6524
|
}
|
|
6468
|
-
async function executeSelect(stmt, client, options, cacheContext, cteCache) {
|
|
6525
|
+
async function executeSelect(stmt, client, options, cacheContext, cteCache, captureColumnMeta = false) {
|
|
6526
|
+
let result;
|
|
6469
6527
|
if (isNoFromSelect(stmt)) {
|
|
6470
|
-
|
|
6528
|
+
result = executeNoFromSelect(stmt);
|
|
6529
|
+
if (captureColumnMeta) {
|
|
6530
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
|
|
6531
|
+
}
|
|
6532
|
+
return result;
|
|
6471
6533
|
}
|
|
6472
6534
|
await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache);
|
|
6473
6535
|
const mode = resolveSelectMode(stmt);
|
|
6474
6536
|
await validateSelectFieldCodes(stmt, mode, client, cacheContext);
|
|
6475
6537
|
if (mode === "SIMPLE") {
|
|
6476
|
-
|
|
6538
|
+
result = await executeSimpleSelect(stmt, client, options, cacheContext);
|
|
6477
6539
|
} else {
|
|
6478
|
-
|
|
6540
|
+
result = await executeFullScanSelect(stmt, client, options, cacheContext, cteCache);
|
|
6541
|
+
}
|
|
6542
|
+
if (captureColumnMeta) {
|
|
6543
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
|
|
6479
6544
|
}
|
|
6545
|
+
return result;
|
|
6480
6546
|
}
|
|
6481
6547
|
function isNoFromSelect(stmt) {
|
|
6482
6548
|
return stmt.from.appId === 0 && stmt.from.cteName === NO_FROM_CTE_NAME;
|
|
@@ -6800,7 +6866,7 @@ function aggregateSortKind(info) {
|
|
|
6800
6866
|
if (info.fieldType === "NUMBER" || info.fieldType === "RECORD_NUMBER") return "number";
|
|
6801
6867
|
return AGGREGATE_STRING_FIELD_TYPES.has(info.fieldType) ? "string" : void 0;
|
|
6802
6868
|
}
|
|
6803
|
-
async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
6869
|
+
async function loadAggregateSortKindResolver(stmt, client, cacheContext, materializedTables) {
|
|
6804
6870
|
const refs = collectSelectAggregateSortRefs(stmt.columns);
|
|
6805
6871
|
if (refs.length === 0) return void 0;
|
|
6806
6872
|
const appIds = /* @__PURE__ */ new Set();
|
|
@@ -6816,11 +6882,9 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
|
6816
6882
|
} else if (stmt.joins.length === 0) {
|
|
6817
6883
|
if (stmt.from.cteName === null) appIds.add(stmt.from.appId);
|
|
6818
6884
|
} else {
|
|
6819
|
-
if ([stmt.from, ...stmt.joins.map((join2) => join2.table)].some((table) => table.cteName !== null)) continue;
|
|
6820
6885
|
for (const table of physicalTables) appIds.add(table.appId);
|
|
6821
6886
|
}
|
|
6822
6887
|
}
|
|
6823
|
-
if (appIds.size === 0) return void 0;
|
|
6824
6888
|
const fieldInfosByApp = new Map(
|
|
6825
6889
|
await Promise.all([...appIds].map(async (appId) => {
|
|
6826
6890
|
const infos = await getFieldsCached(appId, client, cacheContext);
|
|
@@ -6835,17 +6899,28 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
|
6835
6899
|
info = fieldInfosByApp.get(stmt.from.appId)?.get(ref.field);
|
|
6836
6900
|
} else {
|
|
6837
6901
|
const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
|
|
6838
|
-
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
|
+
}
|
|
6839
6906
|
info = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
6840
6907
|
}
|
|
6841
6908
|
} else if (stmt.joins.length === 0) {
|
|
6842
|
-
if (stmt.from.cteName !== null)
|
|
6909
|
+
if (stmt.from.cteName !== null) {
|
|
6910
|
+
return materializedTables?.get(stmt.from.cteName)?.columnMeta?.get(ref.field)?.sortKind;
|
|
6911
|
+
}
|
|
6843
6912
|
info = fieldInfosByApp.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
|
|
6844
6913
|
} else {
|
|
6845
|
-
|
|
6846
|
-
|
|
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
|
+
});
|
|
6847
6922
|
if (matches.length !== 1) return void 0;
|
|
6848
|
-
|
|
6923
|
+
return matches[0];
|
|
6849
6924
|
}
|
|
6850
6925
|
return info ? aggregateSortKind(info) : void 0;
|
|
6851
6926
|
};
|
|
@@ -6854,6 +6929,106 @@ function fieldCodeForTypeLookup(table, field) {
|
|
|
6854
6929
|
if (table.subtableCode && field.startsWith("_p.")) return field.slice(3);
|
|
6855
6930
|
return field;
|
|
6856
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
|
+
}
|
|
6857
7032
|
function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
|
|
6858
7033
|
const tables = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
6859
7034
|
const physicalTables = tables.filter((table) => table.cteName === null);
|
|
@@ -6898,7 +7073,7 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
6898
7073
|
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
6899
7074
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
6900
7075
|
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
6901
|
-
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
7076
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
|
|
6902
7077
|
]);
|
|
6903
7078
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
6904
7079
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -7018,9 +7193,9 @@ function deduplicateRows(rows, columns) {
|
|
|
7018
7193
|
return true;
|
|
7019
7194
|
});
|
|
7020
7195
|
}
|
|
7021
|
-
async function executeWith(stmt, client, options, cacheContext, seed) {
|
|
7196
|
+
async function executeWith(stmt, client, options, cacheContext, seed, captureColumnMeta = false) {
|
|
7022
7197
|
if ((seed == null || seed.size === 0) && canInlineSingleCte(stmt)) {
|
|
7023
|
-
return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext);
|
|
7198
|
+
return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext, void 0, captureColumnMeta);
|
|
7024
7199
|
}
|
|
7025
7200
|
const cteCache = new Map(seed ?? []);
|
|
7026
7201
|
for (const cte of stmt.ctes) {
|
|
@@ -7030,17 +7205,21 @@ async function executeWith(stmt, client, options, cacheContext, seed) {
|
|
|
7030
7205
|
} else if (cte.query.type === "DESCRIBE") {
|
|
7031
7206
|
result = await executeDescribe(cte.query, client, cacheContext);
|
|
7032
7207
|
} else {
|
|
7033
|
-
result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext);
|
|
7208
|
+
result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext, true);
|
|
7034
7209
|
}
|
|
7035
|
-
cteCache.set(cte.name, {
|
|
7210
|
+
cteCache.set(cte.name, {
|
|
7211
|
+
rows: result.rows,
|
|
7212
|
+
columns: result.columns,
|
|
7213
|
+
columnMeta: materializedMetaBySelectResult.get(result)
|
|
7214
|
+
});
|
|
7036
7215
|
}
|
|
7037
|
-
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext);
|
|
7216
|
+
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext, captureColumnMeta);
|
|
7038
7217
|
}
|
|
7039
|
-
async function executeQueryWithCte(query, client, options, cteCache, cacheContext) {
|
|
7218
|
+
async function executeQueryWithCte(query, client, options, cteCache, cacheContext, captureColumnMeta = false) {
|
|
7040
7219
|
if (query.type === "UNION") {
|
|
7041
7220
|
const [leftResult, rightResult] = await Promise.all([
|
|
7042
|
-
executeQueryWithCte(query.left, client, options, cteCache, cacheContext),
|
|
7043
|
-
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)
|
|
7044
7223
|
]);
|
|
7045
7224
|
const leftCols = leftResult.columns;
|
|
7046
7225
|
const rightCols = rightResult.columns;
|
|
@@ -7053,13 +7232,21 @@ async function executeQueryWithCte(query, client, options, cteCache, cacheContex
|
|
|
7053
7232
|
});
|
|
7054
7233
|
const combined = [...leftResult.rows, ...remapped];
|
|
7055
7234
|
const rows = query.all ? combined : deduplicateRows(combined, leftCols);
|
|
7056
|
-
|
|
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;
|
|
7057
7240
|
}
|
|
7058
7241
|
const hasCteRef = query.from.cteName != null && query.from.cteName !== NO_FROM_CTE_NAME || query.joins.some((j) => j.table.cteName != null);
|
|
7059
7242
|
if (!hasCteRef) {
|
|
7060
|
-
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));
|
|
7061
7248
|
}
|
|
7062
|
-
return
|
|
7249
|
+
return result;
|
|
7063
7250
|
}
|
|
7064
7251
|
async function executeFullScanWithCte(stmt, client, options, cteCache, cacheContext) {
|
|
7065
7252
|
const maxRecords = options.maxRecords ?? 1e4;
|
|
@@ -7073,7 +7260,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
7073
7260
|
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
7074
7261
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
7075
7262
|
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
7076
|
-
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
7263
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
|
|
7077
7264
|
]);
|
|
7078
7265
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
7079
7266
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -7551,7 +7738,23 @@ async function prepareDmlValidation(stmt, client, options, cacheContext, tempTab
|
|
|
7551
7738
|
errors,
|
|
7552
7739
|
...stmt.validationErrorTable ? { errTable: stmt.validationErrorTable } : stmt.onErrorSkip && stmt.errorTable ? { errTable: stmt.errorTable } : {}
|
|
7553
7740
|
};
|
|
7554
|
-
|
|
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 };
|
|
7555
7758
|
}
|
|
7556
7759
|
async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTables, statementNumber) {
|
|
7557
7760
|
const prepared = await prepareDmlValidation(
|
|
@@ -7569,7 +7772,8 @@ async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTable
|
|
|
7569
7772
|
errTable,
|
|
7570
7773
|
prepared.result.columns,
|
|
7571
7774
|
prepared.result.errors,
|
|
7572
|
-
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
|
|
7775
|
+
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
|
|
7776
|
+
prepared.columnMeta
|
|
7573
7777
|
);
|
|
7574
7778
|
const rejectLimit = stmt.rejectLimit ?? null;
|
|
7575
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 };
|
|
@@ -32754,16 +32784,25 @@ var Parser = class {
|
|
|
32754
32784
|
// IN リストの値
|
|
32755
32785
|
parseInValues() {
|
|
32756
32786
|
const values = [];
|
|
32787
|
+
const invalidValueMessage = "IN \u30EA\u30B9\u30C8\u306B\u306F\u6587\u5B57\u5217\u3001\u6570\u5024\u3001\u307E\u305F\u306F\u30D0\u30C3\u30C1\u5909\u6570\u304C\u5FC5\u8981\u3067\u3059";
|
|
32757
32788
|
do {
|
|
32758
32789
|
const tok = this.advance();
|
|
32759
32790
|
if (tok.kind === "STRING" /* STRING */) {
|
|
32760
32791
|
values.push({ type: "STRING", value: tok.value });
|
|
32761
32792
|
} else if (tok.kind === "NUMBER" /* NUMBER */) {
|
|
32762
32793
|
values.push({ type: "NUMBER", value: Number(tok.value) });
|
|
32794
|
+
} else if (tok.kind === "-" /* MINUS */ || tok.kind === "+" /* PLUS */) {
|
|
32795
|
+
const number4 = this.peek();
|
|
32796
|
+
if (number4.kind !== "NUMBER" /* NUMBER */) {
|
|
32797
|
+
throw new ParseError(invalidValueMessage, tok);
|
|
32798
|
+
}
|
|
32799
|
+
this.advance();
|
|
32800
|
+
const sign = tok.kind === "-" /* MINUS */ ? -1 : 1;
|
|
32801
|
+
values.push({ type: "NUMBER", value: sign * Number(number4.value) });
|
|
32763
32802
|
} else if (tok.kind === "VARIABLE" /* VARIABLE */) {
|
|
32764
32803
|
values.push({ type: "VARIABLE", name: tok.value.slice(1).toLowerCase() });
|
|
32765
32804
|
} else {
|
|
32766
|
-
throw new ParseError(
|
|
32805
|
+
throw new ParseError(invalidValueMessage, tok);
|
|
32767
32806
|
}
|
|
32768
32807
|
} while (this.consume("," /* COMMA */));
|
|
32769
32808
|
return values;
|
|
@@ -34248,7 +34287,7 @@ function stringFuncLabel(expr) {
|
|
|
34248
34287
|
return `${expr.func}(${args.join(",")})`;
|
|
34249
34288
|
}
|
|
34250
34289
|
function isAggregateSyntheticName(name) {
|
|
34251
|
-
return /^(COUNT|SUM|AVG|MAX|MIN)\(/i.test(name);
|
|
34290
|
+
return /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT)\(/i.test(name);
|
|
34252
34291
|
}
|
|
34253
34292
|
|
|
34254
34293
|
// src/core/cteInlining.ts
|
|
@@ -36014,7 +36053,7 @@ function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
|
|
|
36014
36053
|
for (const col of columns) {
|
|
36015
36054
|
if (col.type === "AGGREGATE") {
|
|
36016
36055
|
const syntheticKey = aggregateSyntheticName2(col.func, col.distinct, col.arg);
|
|
36017
|
-
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));
|
|
36018
36057
|
outRow[col.alias ?? syntheticKey] = value;
|
|
36019
36058
|
if (col.alias) outRow[syntheticKey] = value;
|
|
36020
36059
|
} else if (col.type === "ARITH_AGG_COL") {
|
|
@@ -36035,7 +36074,7 @@ function evalGroupByKey(key, row) {
|
|
|
36035
36074
|
if (key.type === "FUNC_KEY") return evalStringFunc(key.expr, row);
|
|
36036
36075
|
return String(evalArithExpr(key.expr, row));
|
|
36037
36076
|
}
|
|
36038
|
-
function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
36077
|
+
function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind) {
|
|
36039
36078
|
if (arg.type === "WILDCARD") {
|
|
36040
36079
|
return func === "COUNT" ? rows.length : 0;
|
|
36041
36080
|
}
|
|
@@ -36055,6 +36094,7 @@ function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
|
36055
36094
|
}
|
|
36056
36095
|
const eff = distinct ? [...new Set(strValues)] : strValues;
|
|
36057
36096
|
if (func === "COUNT") return eff.length;
|
|
36097
|
+
if (func === "GROUP_CONCAT") return eff.join(separator ?? ",");
|
|
36058
36098
|
const sortKind = (func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" ? resolveAggSortKind?.(toAggregateFieldRef(arg.field)) : void 0;
|
|
36059
36099
|
if (sortKind === "string") {
|
|
36060
36100
|
if (eff.length === 0) return "";
|
|
@@ -36099,7 +36139,7 @@ function minOf(nums) {
|
|
|
36099
36139
|
}
|
|
36100
36140
|
function evalAggArithExpr(node, rows, resolveAggSortKind) {
|
|
36101
36141
|
if (node.type === "NUMBER") return node.value;
|
|
36102
|
-
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));
|
|
36103
36143
|
const l = evalAggArithExpr(node.left, rows, resolveAggSortKind);
|
|
36104
36144
|
const r = evalAggArithExpr(node.right, rows, resolveAggSortKind);
|
|
36105
36145
|
switch (node.op) {
|
|
@@ -36448,7 +36488,7 @@ function hasAggregateInStringFuncExpr2(expr) {
|
|
|
36448
36488
|
}
|
|
36449
36489
|
function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
|
|
36450
36490
|
if (arg.type === "AGG_REF") {
|
|
36451
|
-
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);
|
|
36452
36492
|
return typeof value === "number" ? { type: "NUMBER", value } : { type: "STRING", value };
|
|
36453
36493
|
}
|
|
36454
36494
|
if (arg.type === "AGG_ARITH") {
|
|
@@ -36694,7 +36734,8 @@ function isValidTemporal(value, type) {
|
|
|
36694
36734
|
const date5 = new Date(Date.UTC(year, month - 1, day));
|
|
36695
36735
|
if (date5.getUTCFullYear() !== year || date5.getUTCMonth() !== month - 1 || date5.getUTCDate() !== day) return false;
|
|
36696
36736
|
if (type === "DATE") return true;
|
|
36697
|
-
|
|
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");
|
|
36698
36739
|
}
|
|
36699
36740
|
|
|
36700
36741
|
// src/core/dmlValidationCandidates.ts
|
|
@@ -36774,6 +36815,8 @@ var SearchAbortedError = class extends Error {
|
|
|
36774
36815
|
this.name = "SearchAbortedError";
|
|
36775
36816
|
}
|
|
36776
36817
|
};
|
|
36818
|
+
var materializedMetaBySelectResult = /* @__PURE__ */ new WeakMap();
|
|
36819
|
+
var materializedMetaByValidationResult = /* @__PURE__ */ new WeakMap();
|
|
36777
36820
|
async function execute(sql, client, options = {}) {
|
|
36778
36821
|
const startedAt = Date.now();
|
|
36779
36822
|
const stmt = parseSql(sql);
|
|
@@ -36919,16 +36962,25 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
|
36919
36962
|
}
|
|
36920
36963
|
}
|
|
36921
36964
|
var TEMP_TABLE_MAX_ROWS = 1e4;
|
|
36922
|
-
function appendValidationErrors(tempTables, name, columns, rows, maxRows) {
|
|
36965
|
+
function appendValidationErrors(tempTables, name, columns, rows, maxRows, columnMeta) {
|
|
36923
36966
|
const current = tempTables.get(name);
|
|
36924
|
-
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))) {
|
|
36925
36968
|
throw new Error(`ArgumentError: validation error table ${name} has a different schema.`);
|
|
36926
36969
|
}
|
|
36927
36970
|
const existingRows = current?.rows ?? [];
|
|
36928
36971
|
if (existingRows.length + rows.length > maxRows) {
|
|
36929
36972
|
throw new Error(`ArgumentError: temp table ${name} exceeds max rows (${maxRows}).`);
|
|
36930
36973
|
}
|
|
36931
|
-
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;
|
|
36932
36984
|
}
|
|
36933
36985
|
var BatchTimeoutError = class extends Error {
|
|
36934
36986
|
constructor() {
|
|
@@ -37090,7 +37142,8 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
37090
37142
|
resolvedStmt.validationErrorTable,
|
|
37091
37143
|
result.columns,
|
|
37092
37144
|
result.errors,
|
|
37093
|
-
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
|
|
37145
|
+
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
|
|
37146
|
+
materializedMetaByValidationResult.get(result) ?? /* @__PURE__ */ new Map()
|
|
37094
37147
|
);
|
|
37095
37148
|
}
|
|
37096
37149
|
return { result };
|
|
@@ -37114,7 +37167,11 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
37114
37167
|
onLimitReached: "error"
|
|
37115
37168
|
};
|
|
37116
37169
|
const result = await runSelectLike(resolvedStmt.query, client, materializeOptions, cacheContext, tempTables);
|
|
37117
|
-
tempTables.set(resolvedStmt.name, {
|
|
37170
|
+
tempTables.set(resolvedStmt.name, {
|
|
37171
|
+
rows: result.rows,
|
|
37172
|
+
columns: result.columns,
|
|
37173
|
+
columnMeta: materializedMetaBySelectResult.get(result)
|
|
37174
|
+
});
|
|
37118
37175
|
return { tempTable: resolvedStmt.name, rowCount: result.rows.length };
|
|
37119
37176
|
}
|
|
37120
37177
|
if (stmt.type === "DROP_TEMP_TABLE") {
|
|
@@ -37150,9 +37207,9 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
37150
37207
|
}
|
|
37151
37208
|
async function runSelectLike(query, client, options, cacheContext, tempTables) {
|
|
37152
37209
|
if (query.type === "WITH") {
|
|
37153
|
-
return executeWith(query, client, options, cacheContext, tempTables);
|
|
37210
|
+
return executeWith(query, client, options, cacheContext, tempTables, true);
|
|
37154
37211
|
}
|
|
37155
|
-
return executeQueryWithCte(query, client, options, tempTables, cacheContext);
|
|
37212
|
+
return executeQueryWithCte(query, client, options, tempTables, cacheContext, true);
|
|
37156
37213
|
}
|
|
37157
37214
|
async function runWithDeadline(work, remainingMs) {
|
|
37158
37215
|
if (remainingMs === null) return work;
|
|
@@ -37365,18 +37422,27 @@ function evalAssertArith(node) {
|
|
|
37365
37422
|
}
|
|
37366
37423
|
throw new Error(`ArgumentError: unsupported operand in ASSERT expression: ${node.type}`);
|
|
37367
37424
|
}
|
|
37368
|
-
async function executeSelect(stmt, client, options, cacheContext, cteCache) {
|
|
37425
|
+
async function executeSelect(stmt, client, options, cacheContext, cteCache, captureColumnMeta = false) {
|
|
37426
|
+
let result;
|
|
37369
37427
|
if (isNoFromSelect(stmt)) {
|
|
37370
|
-
|
|
37428
|
+
result = executeNoFromSelect(stmt);
|
|
37429
|
+
if (captureColumnMeta) {
|
|
37430
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
|
|
37431
|
+
}
|
|
37432
|
+
return result;
|
|
37371
37433
|
}
|
|
37372
37434
|
await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache);
|
|
37373
37435
|
const mode = resolveSelectMode(stmt);
|
|
37374
37436
|
await validateSelectFieldCodes(stmt, mode, client, cacheContext);
|
|
37375
37437
|
if (mode === "SIMPLE") {
|
|
37376
|
-
|
|
37438
|
+
result = await executeSimpleSelect(stmt, client, options, cacheContext);
|
|
37377
37439
|
} else {
|
|
37378
|
-
|
|
37440
|
+
result = await executeFullScanSelect(stmt, client, options, cacheContext, cteCache);
|
|
37441
|
+
}
|
|
37442
|
+
if (captureColumnMeta) {
|
|
37443
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
|
|
37379
37444
|
}
|
|
37445
|
+
return result;
|
|
37380
37446
|
}
|
|
37381
37447
|
function isNoFromSelect(stmt) {
|
|
37382
37448
|
return stmt.from.appId === 0 && stmt.from.cteName === NO_FROM_CTE_NAME;
|
|
@@ -37700,7 +37766,7 @@ function aggregateSortKind(info) {
|
|
|
37700
37766
|
if (info.fieldType === "NUMBER" || info.fieldType === "RECORD_NUMBER") return "number";
|
|
37701
37767
|
return AGGREGATE_STRING_FIELD_TYPES.has(info.fieldType) ? "string" : void 0;
|
|
37702
37768
|
}
|
|
37703
|
-
async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
37769
|
+
async function loadAggregateSortKindResolver(stmt, client, cacheContext, materializedTables) {
|
|
37704
37770
|
const refs = collectSelectAggregateSortRefs(stmt.columns);
|
|
37705
37771
|
if (refs.length === 0) return void 0;
|
|
37706
37772
|
const appIds = /* @__PURE__ */ new Set();
|
|
@@ -37716,11 +37782,9 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
|
37716
37782
|
} else if (stmt.joins.length === 0) {
|
|
37717
37783
|
if (stmt.from.cteName === null) appIds.add(stmt.from.appId);
|
|
37718
37784
|
} else {
|
|
37719
|
-
if ([stmt.from, ...stmt.joins.map((join) => join.table)].some((table) => table.cteName !== null)) continue;
|
|
37720
37785
|
for (const table of physicalTables) appIds.add(table.appId);
|
|
37721
37786
|
}
|
|
37722
37787
|
}
|
|
37723
|
-
if (appIds.size === 0) return void 0;
|
|
37724
37788
|
const fieldInfosByApp = new Map(
|
|
37725
37789
|
await Promise.all([...appIds].map(async (appId) => {
|
|
37726
37790
|
const infos = await getFieldsCached(appId, client, cacheContext);
|
|
@@ -37735,17 +37799,28 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
|
37735
37799
|
info = fieldInfosByApp.get(stmt.from.appId)?.get(ref.field);
|
|
37736
37800
|
} else {
|
|
37737
37801
|
const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
|
|
37738
|
-
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
|
+
}
|
|
37739
37806
|
info = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
37740
37807
|
}
|
|
37741
37808
|
} else if (stmt.joins.length === 0) {
|
|
37742
|
-
if (stmt.from.cteName !== null)
|
|
37809
|
+
if (stmt.from.cteName !== null) {
|
|
37810
|
+
return materializedTables?.get(stmt.from.cteName)?.columnMeta?.get(ref.field)?.sortKind;
|
|
37811
|
+
}
|
|
37743
37812
|
info = fieldInfosByApp.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
|
|
37744
37813
|
} else {
|
|
37745
|
-
|
|
37746
|
-
|
|
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
|
+
});
|
|
37747
37822
|
if (matches.length !== 1) return void 0;
|
|
37748
|
-
|
|
37823
|
+
return matches[0];
|
|
37749
37824
|
}
|
|
37750
37825
|
return info ? aggregateSortKind(info) : void 0;
|
|
37751
37826
|
};
|
|
@@ -37754,6 +37829,106 @@ function fieldCodeForTypeLookup(table, field) {
|
|
|
37754
37829
|
if (table.subtableCode && field.startsWith("_p.")) return field.slice(3);
|
|
37755
37830
|
return field;
|
|
37756
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
|
+
}
|
|
37757
37932
|
function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
|
|
37758
37933
|
const tables = [stmt.from, ...stmt.joins.map((join) => join.table)];
|
|
37759
37934
|
const physicalTables = tables.filter((table) => table.cteName === null);
|
|
@@ -37798,7 +37973,7 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
37798
37973
|
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
37799
37974
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
37800
37975
|
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
37801
|
-
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
37976
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
|
|
37802
37977
|
]);
|
|
37803
37978
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
37804
37979
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -37918,9 +38093,9 @@ function deduplicateRows(rows, columns) {
|
|
|
37918
38093
|
return true;
|
|
37919
38094
|
});
|
|
37920
38095
|
}
|
|
37921
|
-
async function executeWith(stmt, client, options, cacheContext, seed) {
|
|
38096
|
+
async function executeWith(stmt, client, options, cacheContext, seed, captureColumnMeta = false) {
|
|
37922
38097
|
if ((seed == null || seed.size === 0) && canInlineSingleCte(stmt)) {
|
|
37923
|
-
return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext);
|
|
38098
|
+
return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext, void 0, captureColumnMeta);
|
|
37924
38099
|
}
|
|
37925
38100
|
const cteCache = new Map(seed ?? []);
|
|
37926
38101
|
for (const cte of stmt.ctes) {
|
|
@@ -37930,17 +38105,21 @@ async function executeWith(stmt, client, options, cacheContext, seed) {
|
|
|
37930
38105
|
} else if (cte.query.type === "DESCRIBE") {
|
|
37931
38106
|
result = await executeDescribe(cte.query, client, cacheContext);
|
|
37932
38107
|
} else {
|
|
37933
|
-
result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext);
|
|
38108
|
+
result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext, true);
|
|
37934
38109
|
}
|
|
37935
|
-
cteCache.set(cte.name, {
|
|
38110
|
+
cteCache.set(cte.name, {
|
|
38111
|
+
rows: result.rows,
|
|
38112
|
+
columns: result.columns,
|
|
38113
|
+
columnMeta: materializedMetaBySelectResult.get(result)
|
|
38114
|
+
});
|
|
37936
38115
|
}
|
|
37937
|
-
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext);
|
|
38116
|
+
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext, captureColumnMeta);
|
|
37938
38117
|
}
|
|
37939
|
-
async function executeQueryWithCte(query, client, options, cteCache, cacheContext) {
|
|
38118
|
+
async function executeQueryWithCte(query, client, options, cteCache, cacheContext, captureColumnMeta = false) {
|
|
37940
38119
|
if (query.type === "UNION") {
|
|
37941
38120
|
const [leftResult, rightResult] = await Promise.all([
|
|
37942
|
-
executeQueryWithCte(query.left, client, options, cteCache, cacheContext),
|
|
37943
|
-
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)
|
|
37944
38123
|
]);
|
|
37945
38124
|
const leftCols = leftResult.columns;
|
|
37946
38125
|
const rightCols = rightResult.columns;
|
|
@@ -37953,13 +38132,21 @@ async function executeQueryWithCte(query, client, options, cteCache, cacheContex
|
|
|
37953
38132
|
});
|
|
37954
38133
|
const combined = [...leftResult.rows, ...remapped];
|
|
37955
38134
|
const rows = query.all ? combined : deduplicateRows(combined, leftCols);
|
|
37956
|
-
|
|
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;
|
|
37957
38140
|
}
|
|
37958
38141
|
const hasCteRef = query.from.cteName != null && query.from.cteName !== NO_FROM_CTE_NAME || query.joins.some((j) => j.table.cteName != null);
|
|
37959
38142
|
if (!hasCteRef) {
|
|
37960
|
-
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));
|
|
37961
38148
|
}
|
|
37962
|
-
return
|
|
38149
|
+
return result;
|
|
37963
38150
|
}
|
|
37964
38151
|
async function executeFullScanWithCte(stmt, client, options, cteCache, cacheContext) {
|
|
37965
38152
|
const maxRecords2 = options.maxRecords ?? 1e4;
|
|
@@ -37973,7 +38160,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
37973
38160
|
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
37974
38161
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
37975
38162
|
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
37976
|
-
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
38163
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
|
|
37977
38164
|
]);
|
|
37978
38165
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
37979
38166
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -38451,7 +38638,23 @@ async function prepareDmlValidation(stmt, client, options, cacheContext, tempTab
|
|
|
38451
38638
|
errors,
|
|
38452
38639
|
...stmt.validationErrorTable ? { errTable: stmt.validationErrorTable } : stmt.onErrorSkip && stmt.errorTable ? { errTable: stmt.errorTable } : {}
|
|
38453
38640
|
};
|
|
38454
|
-
|
|
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 };
|
|
38455
38658
|
}
|
|
38456
38659
|
async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTables, statementNumber) {
|
|
38457
38660
|
const prepared = await prepareDmlValidation(
|
|
@@ -38469,7 +38672,8 @@ async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTable
|
|
|
38469
38672
|
errTable,
|
|
38470
38673
|
prepared.result.columns,
|
|
38471
38674
|
prepared.result.errors,
|
|
38472
|
-
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
|
|
38675
|
+
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
|
|
38676
|
+
prepared.columnMeta
|
|
38473
38677
|
);
|
|
38474
38678
|
const rejectLimit = stmt.rejectLimit ?? null;
|
|
38475
38679
|
if (rejectLimit !== null && prepared.result.invalidRows > rejectLimit) {
|
|
@@ -42210,7 +42414,7 @@ Options:
|
|
|
42210
42414
|
-h, --help Show help
|
|
42211
42415
|
`);
|
|
42212
42416
|
}
|
|
42213
|
-
var SERVER_VERSION = true ? "2.
|
|
42417
|
+
var SERVER_VERSION = true ? "2.15.0" : "0.0.0-dev";
|
|
42214
42418
|
function createServer(args) {
|
|
42215
42419
|
const server = new McpServer({
|
|
42216
42420
|
name: "ksql-mcp",
|
package/dist-mcpb/ksql-mcp.mcpb
CHANGED
|
Binary file
|