@rex0220/kintone-sql-tools 2.14.1 → 2.16.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 +391 -56
- package/dist-mcp/ksql-mcp.js +392 -57
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-mcp/ksql-mcp.js
CHANGED
|
@@ -30999,6 +30999,10 @@ 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 */],
|
|
31003
|
+
["ROW_NUMBER", "ROW_NUMBER" /* ROW_NUMBER */],
|
|
31004
|
+
["RANK", "RANK" /* RANK */],
|
|
31005
|
+
["DENSE_RANK", "DENSE_RANK" /* DENSE_RANK */],
|
|
31002
31006
|
["ASSERT", "ASSERT" /* ASSERT */],
|
|
31003
31007
|
["AND", "AND" /* AND */],
|
|
31004
31008
|
["OR", "OR" /* OR */],
|
|
@@ -31375,6 +31379,9 @@ var FUNC_CALL_PREFIX_KINDS = /* @__PURE__ */ new Set([
|
|
|
31375
31379
|
"AVG" /* AVG */,
|
|
31376
31380
|
"MAX" /* MAX */,
|
|
31377
31381
|
"MIN" /* MIN */,
|
|
31382
|
+
"ROW_NUMBER" /* ROW_NUMBER */,
|
|
31383
|
+
"RANK" /* RANK */,
|
|
31384
|
+
"DENSE_RANK" /* DENSE_RANK */,
|
|
31378
31385
|
"TODAY" /* TODAY */,
|
|
31379
31386
|
"NOW" /* NOW */,
|
|
31380
31387
|
"LOGINUSER" /* LOGINUSER */,
|
|
@@ -31893,6 +31900,11 @@ var Parser = class {
|
|
|
31893
31900
|
const orderBy = this.consume("ORDER" /* ORDER */) ? (this.expect("BY" /* BY */), this.parseOrderBy()) : [];
|
|
31894
31901
|
const limit = this.consume("LIMIT" /* LIMIT */) ? this.parseUnsignedInt() : null;
|
|
31895
31902
|
const offset = this.consume("OFFSET" /* OFFSET */) ? this.parseUnsignedInt() : null;
|
|
31903
|
+
const hasWindow = columns.some((column) => column.type === "WINDOW_COL");
|
|
31904
|
+
const hasAggregate = columns.some((column) => this.selectColumnHasAggregate(column));
|
|
31905
|
+
if (hasWindow && (groupBy.length > 0 || hasAggregate)) {
|
|
31906
|
+
throw new ParseError("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306F GROUP BY / \u96C6\u8A08\u95A2\u6570\u3068\u540C\u3058 SELECT \u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", this.peek());
|
|
31907
|
+
}
|
|
31896
31908
|
return {
|
|
31897
31909
|
type: "SELECT",
|
|
31898
31910
|
distinct,
|
|
@@ -31957,6 +31969,10 @@ var Parser = class {
|
|
|
31957
31969
|
if (this.consume("*" /* STAR */)) {
|
|
31958
31970
|
return { type: "WILDCARD" };
|
|
31959
31971
|
}
|
|
31972
|
+
const windowFunc = this.tryWindowFunc();
|
|
31973
|
+
if (windowFunc !== null) {
|
|
31974
|
+
return this.parseWindowColumn(windowFunc);
|
|
31975
|
+
}
|
|
31960
31976
|
if (this.peek().kind === "CASE" /* CASE */) {
|
|
31961
31977
|
const expr = this.parseCaseWhenExpr();
|
|
31962
31978
|
const alias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
|
|
@@ -31991,6 +32007,7 @@ var Parser = class {
|
|
|
31991
32007
|
func: ref.func,
|
|
31992
32008
|
distinct: ref.distinct,
|
|
31993
32009
|
arg: ref.arg,
|
|
32010
|
+
...ref.separator !== void 0 ? { separator: ref.separator } : {},
|
|
31994
32011
|
alias: alias2
|
|
31995
32012
|
};
|
|
31996
32013
|
}
|
|
@@ -32027,6 +32044,56 @@ var Parser = class {
|
|
|
32027
32044
|
const alias = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
|
|
32028
32045
|
return { type: "FIELD", field, alias };
|
|
32029
32046
|
}
|
|
32047
|
+
tryWindowFunc() {
|
|
32048
|
+
switch (this.peek().kind) {
|
|
32049
|
+
case "ROW_NUMBER" /* ROW_NUMBER */:
|
|
32050
|
+
return "ROW_NUMBER";
|
|
32051
|
+
case "RANK" /* RANK */:
|
|
32052
|
+
return "RANK";
|
|
32053
|
+
case "DENSE_RANK" /* DENSE_RANK */:
|
|
32054
|
+
return "DENSE_RANK";
|
|
32055
|
+
default:
|
|
32056
|
+
return null;
|
|
32057
|
+
}
|
|
32058
|
+
}
|
|
32059
|
+
parseWindowColumn(func) {
|
|
32060
|
+
this.advance();
|
|
32061
|
+
this.expect("(" /* LPAREN */);
|
|
32062
|
+
if (this.peek().kind !== ")" /* RPAREN */) {
|
|
32063
|
+
throw new ParseError(`${func} \u306F\u5F15\u6570\u3092\u53D7\u3051\u4ED8\u3051\u307E\u305B\u3093`, this.peek());
|
|
32064
|
+
}
|
|
32065
|
+
this.expect(")" /* RPAREN */);
|
|
32066
|
+
this.expectSoftKeyword("OVER", `${func} \u306B\u306F OVER (...) \u304C\u5FC5\u8981\u3067\u3059`);
|
|
32067
|
+
this.expect("(" /* LPAREN */);
|
|
32068
|
+
const partitionBy = [];
|
|
32069
|
+
if (this.isSoftKeyword("PARTITION")) {
|
|
32070
|
+
this.advance();
|
|
32071
|
+
this.expect("BY" /* BY */, "PARTITION \u306E\u5F8C\u306B\u306F BY \u304C\u5FC5\u8981\u3067\u3059");
|
|
32072
|
+
do {
|
|
32073
|
+
const ref = this.parseQualifiedIdent();
|
|
32074
|
+
partitionBy.push({ type: "FIELD", tableAlias: ref.tableAlias, field: ref.field });
|
|
32075
|
+
} while (this.consume("," /* COMMA */));
|
|
32076
|
+
}
|
|
32077
|
+
const orderBy = this.consume("ORDER" /* ORDER */) ? (this.expect("BY" /* BY */), this.parseOrderBy()) : [];
|
|
32078
|
+
this.expect(")" /* RPAREN */);
|
|
32079
|
+
if (!this.consume("AS" /* AS */)) {
|
|
32080
|
+
throw new ParseError("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306B\u306F AS alias \u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
32081
|
+
}
|
|
32082
|
+
const alias = this.parseAliasName();
|
|
32083
|
+
return { type: "WINDOW_COL", func, partitionBy, orderBy, alias };
|
|
32084
|
+
}
|
|
32085
|
+
selectColumnHasAggregate(column) {
|
|
32086
|
+
if (column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL") return true;
|
|
32087
|
+
if (column.type !== "STRFUNC_COL") return false;
|
|
32088
|
+
return column.expr.args.some((arg) => this.stringFuncArgHasAggregate(arg));
|
|
32089
|
+
}
|
|
32090
|
+
stringFuncArgHasAggregate(arg) {
|
|
32091
|
+
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
32092
|
+
if (arg.type === "STRING_FUNC") {
|
|
32093
|
+
return arg.args.some((nested) => this.stringFuncArgHasAggregate(nested));
|
|
32094
|
+
}
|
|
32095
|
+
return false;
|
|
32096
|
+
}
|
|
32030
32097
|
isArithOp(kind) {
|
|
32031
32098
|
return kind === "+" /* PLUS */ || kind === "-" /* MINUS */ || kind === "*" /* STAR */ || kind === "/" /* SLASH */ || kind === "%" /* PERCENT */;
|
|
32032
32099
|
}
|
|
@@ -32362,7 +32429,8 @@ var Parser = class {
|
|
|
32362
32429
|
["SUM" /* SUM */]: "SUM",
|
|
32363
32430
|
["AVG" /* AVG */]: "AVG",
|
|
32364
32431
|
["MAX" /* MAX */]: "MAX",
|
|
32365
|
-
["MIN" /* MIN */]: "MIN"
|
|
32432
|
+
["MIN" /* MIN */]: "MIN",
|
|
32433
|
+
["GROUP_CONCAT" /* GROUP_CONCAT */]: "GROUP_CONCAT"
|
|
32366
32434
|
};
|
|
32367
32435
|
const kind = this.peek().kind;
|
|
32368
32436
|
return map2[kind] ?? null;
|
|
@@ -32374,12 +32442,29 @@ var Parser = class {
|
|
|
32374
32442
|
const distinct = this.consume("DISTINCT" /* DISTINCT */);
|
|
32375
32443
|
let arg;
|
|
32376
32444
|
if (this.consume("*" /* STAR */)) {
|
|
32445
|
+
if (func === "GROUP_CONCAT") {
|
|
32446
|
+
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());
|
|
32447
|
+
}
|
|
32377
32448
|
arg = { type: "WILDCARD" };
|
|
32378
32449
|
} else {
|
|
32379
32450
|
arg = this.parseArithAddSub();
|
|
32380
32451
|
}
|
|
32452
|
+
let separator;
|
|
32453
|
+
if (this.isSoftKeyword("SEPARATOR")) {
|
|
32454
|
+
const separatorToken = this.advance();
|
|
32455
|
+
if (func !== "GROUP_CONCAT") {
|
|
32456
|
+
throw new ParseError("SEPARATOR \u306F GROUP_CONCAT \u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059", separatorToken);
|
|
32457
|
+
}
|
|
32458
|
+
separator = this.expect("STRING" /* STRING */, "SEPARATOR \u306E\u5F8C\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059").value;
|
|
32459
|
+
}
|
|
32381
32460
|
this.expect(")" /* RPAREN */);
|
|
32382
|
-
return {
|
|
32461
|
+
return {
|
|
32462
|
+
type: "AGG_REF",
|
|
32463
|
+
func,
|
|
32464
|
+
distinct,
|
|
32465
|
+
arg,
|
|
32466
|
+
...separator !== void 0 ? { separator } : {}
|
|
32467
|
+
};
|
|
32383
32468
|
}
|
|
32384
32469
|
// ----------------------------------------------------------
|
|
32385
32470
|
// FROM / JOIN
|
|
@@ -32657,10 +32742,20 @@ var Parser = class {
|
|
|
32657
32742
|
const distinct = this.consume("DISTINCT" /* DISTINCT */);
|
|
32658
32743
|
let argStr;
|
|
32659
32744
|
if (this.consume("*" /* STAR */)) {
|
|
32745
|
+
if (aggFunc === "GROUP_CONCAT") {
|
|
32746
|
+
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());
|
|
32747
|
+
}
|
|
32660
32748
|
argStr = "*";
|
|
32661
32749
|
} else {
|
|
32662
32750
|
argStr = this.parseIdentifier();
|
|
32663
32751
|
}
|
|
32752
|
+
if (this.isSoftKeyword("SEPARATOR")) {
|
|
32753
|
+
const separatorToken = this.advance();
|
|
32754
|
+
if (aggFunc !== "GROUP_CONCAT") {
|
|
32755
|
+
throw new ParseError("SEPARATOR \u306F GROUP_CONCAT \u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059", separatorToken);
|
|
32756
|
+
}
|
|
32757
|
+
this.expect("STRING" /* STRING */, "SEPARATOR \u306E\u5F8C\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059");
|
|
32758
|
+
}
|
|
32664
32759
|
this.expect(")" /* RPAREN */);
|
|
32665
32760
|
const syntheticName = distinct ? `${aggFunc}(DISTINCT ${argStr})` : `${aggFunc}(${argStr})`;
|
|
32666
32761
|
return { type: "FIELD", tableAlias: null, field: syntheticName };
|
|
@@ -33768,12 +33863,16 @@ var KintoneQueryError = class extends Error {
|
|
|
33768
33863
|
};
|
|
33769
33864
|
|
|
33770
33865
|
// src/converter/selectToKintone.ts
|
|
33866
|
+
function hasWindowColumns(columns) {
|
|
33867
|
+
return columns.some((column) => column.type === "WINDOW_COL");
|
|
33868
|
+
}
|
|
33771
33869
|
function resolveSelectMode(stmt) {
|
|
33772
33870
|
if (stmt.from.subtableCode) return "FULL_SCAN";
|
|
33773
33871
|
if (stmt.joins.some((j) => j.table.subtableCode)) return "FULL_SCAN";
|
|
33774
33872
|
if (stmt.joins.length > 0) return "FULL_SCAN";
|
|
33775
33873
|
if (stmt.groupBy.length > 0) return "FULL_SCAN";
|
|
33776
33874
|
if (stmt.distinct) return "FULL_SCAN";
|
|
33875
|
+
if (hasWindowColumns(stmt.columns)) return "FULL_SCAN";
|
|
33777
33876
|
if (stmt.columns.some(
|
|
33778
33877
|
(c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "SCALAR_SUBQUERY_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr(c.expr)
|
|
33779
33878
|
)) return "FULL_SCAN";
|
|
@@ -34145,16 +34244,16 @@ function collectRequiredFieldsByTable(stmt) {
|
|
|
34145
34244
|
}
|
|
34146
34245
|
walkStringFunc(k.expr, "groupBy");
|
|
34147
34246
|
};
|
|
34148
|
-
const walkOrderByKey = (k) => {
|
|
34247
|
+
const walkOrderByKey = (k, phase = "orderBy") => {
|
|
34149
34248
|
if (k.type === "FIELD_NAME") {
|
|
34150
|
-
addFieldName(k.name,
|
|
34249
|
+
addFieldName(k.name, phase);
|
|
34151
34250
|
return;
|
|
34152
34251
|
}
|
|
34153
34252
|
if (k.type === "ARITH_KEY") {
|
|
34154
|
-
walkArith(k.expr,
|
|
34253
|
+
walkArith(k.expr, phase);
|
|
34155
34254
|
return;
|
|
34156
34255
|
}
|
|
34157
|
-
walkStringFunc(k.expr,
|
|
34256
|
+
walkStringFunc(k.expr, phase);
|
|
34158
34257
|
};
|
|
34159
34258
|
for (const col of stmt.columns) {
|
|
34160
34259
|
switch (col.type) {
|
|
@@ -34186,6 +34285,10 @@ function collectRequiredFieldsByTable(stmt) {
|
|
|
34186
34285
|
break;
|
|
34187
34286
|
case "SCALAR_SUBQUERY_COL":
|
|
34188
34287
|
break;
|
|
34288
|
+
case "WINDOW_COL":
|
|
34289
|
+
for (const ref of col.partitionBy) addFieldRef(ref.field, ref.tableAlias, "select");
|
|
34290
|
+
for (const item of col.orderBy) walkOrderByKey(item.key, "select");
|
|
34291
|
+
break;
|
|
34189
34292
|
}
|
|
34190
34293
|
}
|
|
34191
34294
|
for (const join of stmt.joins) {
|
|
@@ -34232,6 +34335,10 @@ function collectSelectOutputNames(columns) {
|
|
|
34232
34335
|
}
|
|
34233
34336
|
if (col.type === "SCALAR_SUBQUERY_COL") {
|
|
34234
34337
|
names.add(col.alias ?? "(subquery)");
|
|
34338
|
+
continue;
|
|
34339
|
+
}
|
|
34340
|
+
if (col.type === "WINDOW_COL") {
|
|
34341
|
+
names.add(col.alias);
|
|
34235
34342
|
}
|
|
34236
34343
|
}
|
|
34237
34344
|
return names;
|
|
@@ -34257,7 +34364,7 @@ function stringFuncLabel(expr) {
|
|
|
34257
34364
|
return `${expr.func}(${args.join(",")})`;
|
|
34258
34365
|
}
|
|
34259
34366
|
function isAggregateSyntheticName(name) {
|
|
34260
|
-
return /^(COUNT|SUM|AVG|MAX|MIN)\(/i.test(name);
|
|
34367
|
+
return /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT)\(/i.test(name);
|
|
34261
34368
|
}
|
|
34262
34369
|
|
|
34263
34370
|
// src/core/cteInlining.ts
|
|
@@ -36023,7 +36130,7 @@ function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
|
|
|
36023
36130
|
for (const col of columns) {
|
|
36024
36131
|
if (col.type === "AGGREGATE") {
|
|
36025
36132
|
const syntheticKey = aggregateSyntheticName2(col.func, col.distinct, col.arg);
|
|
36026
|
-
const value = String(evalAggregate(col.func, col.distinct, col.arg, groupRows, resolveAggSortKind));
|
|
36133
|
+
const value = String(evalAggregate(col.func, col.distinct, col.arg, col.separator, groupRows, resolveAggSortKind));
|
|
36027
36134
|
outRow[col.alias ?? syntheticKey] = value;
|
|
36028
36135
|
if (col.alias) outRow[syntheticKey] = value;
|
|
36029
36136
|
} else if (col.type === "ARITH_AGG_COL") {
|
|
@@ -36044,7 +36151,7 @@ function evalGroupByKey(key, row) {
|
|
|
36044
36151
|
if (key.type === "FUNC_KEY") return evalStringFunc(key.expr, row);
|
|
36045
36152
|
return String(evalArithExpr(key.expr, row));
|
|
36046
36153
|
}
|
|
36047
|
-
function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
36154
|
+
function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind) {
|
|
36048
36155
|
if (arg.type === "WILDCARD") {
|
|
36049
36156
|
return func === "COUNT" ? rows.length : 0;
|
|
36050
36157
|
}
|
|
@@ -36064,6 +36171,7 @@ function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
|
36064
36171
|
}
|
|
36065
36172
|
const eff = distinct ? [...new Set(strValues)] : strValues;
|
|
36066
36173
|
if (func === "COUNT") return eff.length;
|
|
36174
|
+
if (func === "GROUP_CONCAT") return eff.join(separator ?? ",");
|
|
36067
36175
|
const sortKind = (func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" ? resolveAggSortKind?.(toAggregateFieldRef(arg.field)) : void 0;
|
|
36068
36176
|
if (sortKind === "string") {
|
|
36069
36177
|
if (eff.length === 0) return "";
|
|
@@ -36108,7 +36216,7 @@ function minOf(nums) {
|
|
|
36108
36216
|
}
|
|
36109
36217
|
function evalAggArithExpr(node, rows, resolveAggSortKind) {
|
|
36110
36218
|
if (node.type === "NUMBER") return node.value;
|
|
36111
|
-
if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, rows, resolveAggSortKind));
|
|
36219
|
+
if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, node.separator, rows, resolveAggSortKind));
|
|
36112
36220
|
const l = evalAggArithExpr(node.left, rows, resolveAggSortKind);
|
|
36113
36221
|
const r = evalAggArithExpr(node.right, rows, resolveAggSortKind);
|
|
36114
36222
|
switch (node.op) {
|
|
@@ -36178,6 +36286,10 @@ function buildDistinctKeyBuilder(rows, columns) {
|
|
|
36178
36286
|
values.push(row[col.field] ?? "");
|
|
36179
36287
|
continue;
|
|
36180
36288
|
}
|
|
36289
|
+
if (col.type === "WINDOW_COL") {
|
|
36290
|
+
values.push(row[col.alias] ?? "");
|
|
36291
|
+
continue;
|
|
36292
|
+
}
|
|
36181
36293
|
if (col.type === "PARENT_WILDCARD") {
|
|
36182
36294
|
for (const k of sortedParentKeys) {
|
|
36183
36295
|
values.push(row[k] !== void 0 ? row[k] : null);
|
|
@@ -36189,6 +36301,9 @@ function buildDistinctKeyBuilder(rows, columns) {
|
|
|
36189
36301
|
}
|
|
36190
36302
|
function applyOrderBy(rows, orderBy, optionOrders, sortKinds) {
|
|
36191
36303
|
if (orderBy.length === 0) return rows;
|
|
36304
|
+
return sortDecoratedRows(rows, orderBy, optionOrders, sortKinds).rows.map((item) => item.row);
|
|
36305
|
+
}
|
|
36306
|
+
function sortDecoratedRows(rows, orderBy, optionOrders, sortKinds) {
|
|
36192
36307
|
const keyMeta = orderBy.map(({ key }) => ({
|
|
36193
36308
|
orderMap: key.type === "FIELD_NAME" ? optionOrders?.get(key.name) : void 0,
|
|
36194
36309
|
sortKind: key.type === "FIELD_NAME" ? sortKinds?.get(key.name) : void 0
|
|
@@ -36207,14 +36322,16 @@ function applyOrderBy(rows, orderBy, optionOrders, sortKinds) {
|
|
|
36207
36322
|
};
|
|
36208
36323
|
})
|
|
36209
36324
|
}));
|
|
36210
|
-
|
|
36211
|
-
|
|
36212
|
-
|
|
36213
|
-
|
|
36214
|
-
|
|
36215
|
-
|
|
36216
|
-
|
|
36217
|
-
|
|
36325
|
+
const compare = (a, b) => compareDecoratedRows(a, b, orderBy, keyMeta);
|
|
36326
|
+
decorated.sort(compare);
|
|
36327
|
+
return { rows: decorated, compare };
|
|
36328
|
+
}
|
|
36329
|
+
function compareDecoratedRows(a, b, orderBy, keyMeta) {
|
|
36330
|
+
for (let i = 0; i < orderBy.length; i++) {
|
|
36331
|
+
const cmp = compareSortKeys(a.keys[i], b.keys[i], keyMeta[i]);
|
|
36332
|
+
if (cmp !== 0) return orderBy[i].direction === "ASC" ? cmp : -cmp;
|
|
36333
|
+
}
|
|
36334
|
+
return 0;
|
|
36218
36335
|
}
|
|
36219
36336
|
function compareSortKeys(a, b, meta3) {
|
|
36220
36337
|
if (meta3.orderMap) {
|
|
@@ -36259,6 +36376,38 @@ function minChoiceIndex(values, orderMap) {
|
|
|
36259
36376
|
}
|
|
36260
36377
|
return min;
|
|
36261
36378
|
}
|
|
36379
|
+
function applyWindow(rows, columns, optionOrders, sortKinds) {
|
|
36380
|
+
const windows = columns.filter((column) => column.type === "WINDOW_COL");
|
|
36381
|
+
if (rows.length === 0 || windows.length === 0) return rows;
|
|
36382
|
+
for (const window of windows) {
|
|
36383
|
+
const partitions = /* @__PURE__ */ new Map();
|
|
36384
|
+
for (const row of rows) {
|
|
36385
|
+
const key = JSON.stringify(window.partitionBy.map((ref) => resolveWindowField(row, ref)));
|
|
36386
|
+
const partition = partitions.get(key);
|
|
36387
|
+
if (partition) partition.push(row);
|
|
36388
|
+
else partitions.set(key, [row]);
|
|
36389
|
+
}
|
|
36390
|
+
for (const partition of partitions.values()) {
|
|
36391
|
+
const sortedResult = sortDecoratedRows(partition, window.orderBy, optionOrders, sortKinds);
|
|
36392
|
+
const sorted = sortedResult.rows;
|
|
36393
|
+
let rank = 1;
|
|
36394
|
+
let denseRank = 1;
|
|
36395
|
+
for (let index = 0; index < sorted.length; index++) {
|
|
36396
|
+
if (index > 0 && sortedResult.compare(sorted[index - 1], sorted[index]) !== 0) {
|
|
36397
|
+
rank = index + 1;
|
|
36398
|
+
denseRank++;
|
|
36399
|
+
}
|
|
36400
|
+
const value = window.func === "ROW_NUMBER" ? index + 1 : window.func === "RANK" ? rank : denseRank;
|
|
36401
|
+
sorted[index].row[window.alias] = String(value);
|
|
36402
|
+
}
|
|
36403
|
+
}
|
|
36404
|
+
}
|
|
36405
|
+
return rows;
|
|
36406
|
+
}
|
|
36407
|
+
function resolveWindowField(row, ref) {
|
|
36408
|
+
const name = ref.tableAlias ? `${ref.tableAlias}.${ref.field}` : ref.field;
|
|
36409
|
+
return resolveFieldRef(row, name);
|
|
36410
|
+
}
|
|
36262
36411
|
function applyLimit(rows, limit, offset) {
|
|
36263
36412
|
const start = offset ?? 0;
|
|
36264
36413
|
if (limit === null) return rows.slice(start);
|
|
@@ -36349,6 +36498,12 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns) {
|
|
|
36349
36498
|
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
36350
36499
|
break;
|
|
36351
36500
|
}
|
|
36501
|
+
case "WINDOW_COL": {
|
|
36502
|
+
const key = outputKeys?.[colIdx] ?? col.alias;
|
|
36503
|
+
out[key] = row[col.alias] ?? "";
|
|
36504
|
+
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
36505
|
+
break;
|
|
36506
|
+
}
|
|
36352
36507
|
}
|
|
36353
36508
|
}
|
|
36354
36509
|
return out;
|
|
@@ -36389,6 +36544,8 @@ function computeOutputKey(col, colIdx, defaultFieldKeys) {
|
|
|
36389
36544
|
return col.alias ?? stringFuncDefaultKey(col.expr);
|
|
36390
36545
|
case "SCALAR_SUBQUERY_COL":
|
|
36391
36546
|
return col.alias ?? "(subquery)";
|
|
36547
|
+
case "WINDOW_COL":
|
|
36548
|
+
return col.alias;
|
|
36392
36549
|
case "WILDCARD":
|
|
36393
36550
|
case "PARENT_WILDCARD":
|
|
36394
36551
|
throw new Error("internal: computeOutputKey received a wildcard column");
|
|
@@ -36457,7 +36614,7 @@ function hasAggregateInStringFuncExpr2(expr) {
|
|
|
36457
36614
|
}
|
|
36458
36615
|
function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
|
|
36459
36616
|
if (arg.type === "AGG_REF") {
|
|
36460
|
-
const value = evalAggregate(arg.func, arg.distinct, arg.arg, rows, resolveAggSortKind);
|
|
36617
|
+
const value = evalAggregate(arg.func, arg.distinct, arg.arg, arg.separator, rows, resolveAggSortKind);
|
|
36461
36618
|
return typeof value === "number" ? { type: "NUMBER", value } : { type: "STRING", value };
|
|
36462
36619
|
}
|
|
36463
36620
|
if (arg.type === "AGG_ARITH") {
|
|
@@ -36503,6 +36660,7 @@ function runFullScan(input) {
|
|
|
36503
36660
|
rows = applyGroupBy(rows, stmt.groupBy, stmt.columns, aggregateSortKindResolver);
|
|
36504
36661
|
}
|
|
36505
36662
|
rows = applyHaving(rows, stmt.having, havingFieldTypeResolver);
|
|
36663
|
+
rows = applyWindow(rows, stmt.columns, optionOrders, sortKinds);
|
|
36506
36664
|
if (stmt.distinct) {
|
|
36507
36665
|
rows = applyDistinct(rows, stmt.columns);
|
|
36508
36666
|
}
|
|
@@ -36703,7 +36861,8 @@ function isValidTemporal(value, type) {
|
|
|
36703
36861
|
const date5 = new Date(Date.UTC(year, month - 1, day));
|
|
36704
36862
|
if (date5.getUTCFullYear() !== year || date5.getUTCMonth() !== month - 1 || date5.getUTCDate() !== day) return false;
|
|
36705
36863
|
if (type === "DATE") return true;
|
|
36706
|
-
|
|
36864
|
+
const timePart = value.slice(11, value.endsWith("Z") ? -1 : value.length - 6).replace(/\.\d+$/, "");
|
|
36865
|
+
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
36866
|
}
|
|
36708
36867
|
|
|
36709
36868
|
// src/core/dmlValidationCandidates.ts
|
|
@@ -36783,6 +36942,8 @@ var SearchAbortedError = class extends Error {
|
|
|
36783
36942
|
this.name = "SearchAbortedError";
|
|
36784
36943
|
}
|
|
36785
36944
|
};
|
|
36945
|
+
var materializedMetaBySelectResult = /* @__PURE__ */ new WeakMap();
|
|
36946
|
+
var materializedMetaByValidationResult = /* @__PURE__ */ new WeakMap();
|
|
36786
36947
|
async function execute(sql, client, options = {}) {
|
|
36787
36948
|
const startedAt = Date.now();
|
|
36788
36949
|
const stmt = parseSql(sql);
|
|
@@ -36928,16 +37089,25 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
|
36928
37089
|
}
|
|
36929
37090
|
}
|
|
36930
37091
|
var TEMP_TABLE_MAX_ROWS = 1e4;
|
|
36931
|
-
function appendValidationErrors(tempTables, name, columns, rows, maxRows) {
|
|
37092
|
+
function appendValidationErrors(tempTables, name, columns, rows, maxRows, columnMeta) {
|
|
36932
37093
|
const current = tempTables.get(name);
|
|
36933
|
-
if (current && (current.columns.length !== columns.length || current.columns.some((c, i) => c !== columns[i]))) {
|
|
37094
|
+
if (current && (current.columns.length !== columns.length || current.columns.some((c, i) => c !== columns[i]) || !materializedColumnMetaEqual(current.columnMeta, columnMeta))) {
|
|
36934
37095
|
throw new Error(`ArgumentError: validation error table ${name} has a different schema.`);
|
|
36935
37096
|
}
|
|
36936
37097
|
const existingRows = current?.rows ?? [];
|
|
36937
37098
|
if (existingRows.length + rows.length > maxRows) {
|
|
36938
37099
|
throw new Error(`ArgumentError: temp table ${name} exceeds max rows (${maxRows}).`);
|
|
36939
37100
|
}
|
|
36940
|
-
tempTables.set(name, { columns: [...columns], rows: [...existingRows, ...rows] });
|
|
37101
|
+
tempTables.set(name, { columns: [...columns], rows: [...existingRows, ...rows], columnMeta });
|
|
37102
|
+
}
|
|
37103
|
+
function materializedColumnMetaEqual(left, right) {
|
|
37104
|
+
if (left === right) return true;
|
|
37105
|
+
if (!left || !right || left.size !== right.size) return false;
|
|
37106
|
+
for (const [column, meta3] of left) {
|
|
37107
|
+
const candidate = right.get(column);
|
|
37108
|
+
if (!candidate || candidate.sortKind !== meta3.sortKind || candidate.fieldType !== meta3.fieldType) return false;
|
|
37109
|
+
}
|
|
37110
|
+
return true;
|
|
36941
37111
|
}
|
|
36942
37112
|
var BatchTimeoutError = class extends Error {
|
|
36943
37113
|
constructor() {
|
|
@@ -37099,7 +37269,8 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
37099
37269
|
resolvedStmt.validationErrorTable,
|
|
37100
37270
|
result.columns,
|
|
37101
37271
|
result.errors,
|
|
37102
|
-
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
|
|
37272
|
+
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
|
|
37273
|
+
materializedMetaByValidationResult.get(result) ?? /* @__PURE__ */ new Map()
|
|
37103
37274
|
);
|
|
37104
37275
|
}
|
|
37105
37276
|
return { result };
|
|
@@ -37123,7 +37294,11 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
37123
37294
|
onLimitReached: "error"
|
|
37124
37295
|
};
|
|
37125
37296
|
const result = await runSelectLike(resolvedStmt.query, client, materializeOptions, cacheContext, tempTables);
|
|
37126
|
-
tempTables.set(resolvedStmt.name, {
|
|
37297
|
+
tempTables.set(resolvedStmt.name, {
|
|
37298
|
+
rows: result.rows,
|
|
37299
|
+
columns: result.columns,
|
|
37300
|
+
columnMeta: materializedMetaBySelectResult.get(result)
|
|
37301
|
+
});
|
|
37127
37302
|
return { tempTable: resolvedStmt.name, rowCount: result.rows.length };
|
|
37128
37303
|
}
|
|
37129
37304
|
if (stmt.type === "DROP_TEMP_TABLE") {
|
|
@@ -37159,9 +37334,9 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
37159
37334
|
}
|
|
37160
37335
|
async function runSelectLike(query, client, options, cacheContext, tempTables) {
|
|
37161
37336
|
if (query.type === "WITH") {
|
|
37162
|
-
return executeWith(query, client, options, cacheContext, tempTables);
|
|
37337
|
+
return executeWith(query, client, options, cacheContext, tempTables, true);
|
|
37163
37338
|
}
|
|
37164
|
-
return executeQueryWithCte(query, client, options, tempTables, cacheContext);
|
|
37339
|
+
return executeQueryWithCte(query, client, options, tempTables, cacheContext, true);
|
|
37165
37340
|
}
|
|
37166
37341
|
async function runWithDeadline(work, remainingMs) {
|
|
37167
37342
|
if (remainingMs === null) return work;
|
|
@@ -37374,18 +37549,27 @@ function evalAssertArith(node) {
|
|
|
37374
37549
|
}
|
|
37375
37550
|
throw new Error(`ArgumentError: unsupported operand in ASSERT expression: ${node.type}`);
|
|
37376
37551
|
}
|
|
37377
|
-
async function executeSelect(stmt, client, options, cacheContext, cteCache) {
|
|
37552
|
+
async function executeSelect(stmt, client, options, cacheContext, cteCache, captureColumnMeta = false) {
|
|
37553
|
+
let result;
|
|
37378
37554
|
if (isNoFromSelect(stmt)) {
|
|
37379
|
-
|
|
37555
|
+
result = executeNoFromSelect(stmt);
|
|
37556
|
+
if (captureColumnMeta) {
|
|
37557
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
|
|
37558
|
+
}
|
|
37559
|
+
return result;
|
|
37380
37560
|
}
|
|
37381
37561
|
await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache);
|
|
37382
37562
|
const mode = resolveSelectMode(stmt);
|
|
37383
37563
|
await validateSelectFieldCodes(stmt, mode, client, cacheContext);
|
|
37384
37564
|
if (mode === "SIMPLE") {
|
|
37385
|
-
|
|
37565
|
+
result = await executeSimpleSelect(stmt, client, options, cacheContext);
|
|
37386
37566
|
} else {
|
|
37387
|
-
|
|
37567
|
+
result = await executeFullScanSelect(stmt, client, options, cacheContext, cteCache);
|
|
37388
37568
|
}
|
|
37569
|
+
if (captureColumnMeta) {
|
|
37570
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
|
|
37571
|
+
}
|
|
37572
|
+
return result;
|
|
37389
37573
|
}
|
|
37390
37574
|
function isNoFromSelect(stmt) {
|
|
37391
37575
|
return stmt.from.appId === 0 && stmt.from.cteName === NO_FROM_CTE_NAME;
|
|
@@ -37421,6 +37605,11 @@ function validateNoFromColumns(stmt) {
|
|
|
37421
37605
|
throw new Error("ArgumentError: field reference is not allowed without FROM.");
|
|
37422
37606
|
}
|
|
37423
37607
|
break;
|
|
37608
|
+
case "WINDOW_COL":
|
|
37609
|
+
if (col.partitionBy.length > 0 || col.orderBy.length > 0) {
|
|
37610
|
+
throw new Error("ArgumentError: field reference is not allowed without FROM.");
|
|
37611
|
+
}
|
|
37612
|
+
break;
|
|
37424
37613
|
default:
|
|
37425
37614
|
throw new Error(`ArgumentError: ${col.type} is not supported without FROM.`);
|
|
37426
37615
|
}
|
|
@@ -37431,7 +37620,8 @@ function executeNoFromSelect(stmt) {
|
|
|
37431
37620
|
throw new Error("ArgumentError: JOIN/WHERE/GROUP BY/HAVING/ORDER BY/DISTINCT are not supported without FROM.");
|
|
37432
37621
|
}
|
|
37433
37622
|
validateNoFromColumns(stmt);
|
|
37434
|
-
const
|
|
37623
|
+
const windowed = applyWindow([{}], stmt.columns);
|
|
37624
|
+
const { rows: projected, columns } = project(windowed, stmt.columns);
|
|
37435
37625
|
const rows = applyLimit(projected, stmt.limit, stmt.offset);
|
|
37436
37626
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [] };
|
|
37437
37627
|
}
|
|
@@ -37709,7 +37899,7 @@ function aggregateSortKind(info) {
|
|
|
37709
37899
|
if (info.fieldType === "NUMBER" || info.fieldType === "RECORD_NUMBER") return "number";
|
|
37710
37900
|
return AGGREGATE_STRING_FIELD_TYPES.has(info.fieldType) ? "string" : void 0;
|
|
37711
37901
|
}
|
|
37712
|
-
async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
37902
|
+
async function loadAggregateSortKindResolver(stmt, client, cacheContext, materializedTables) {
|
|
37713
37903
|
const refs = collectSelectAggregateSortRefs(stmt.columns);
|
|
37714
37904
|
if (refs.length === 0) return void 0;
|
|
37715
37905
|
const appIds = /* @__PURE__ */ new Set();
|
|
@@ -37725,11 +37915,9 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
|
37725
37915
|
} else if (stmt.joins.length === 0) {
|
|
37726
37916
|
if (stmt.from.cteName === null) appIds.add(stmt.from.appId);
|
|
37727
37917
|
} else {
|
|
37728
|
-
if ([stmt.from, ...stmt.joins.map((join) => join.table)].some((table) => table.cteName !== null)) continue;
|
|
37729
37918
|
for (const table of physicalTables) appIds.add(table.appId);
|
|
37730
37919
|
}
|
|
37731
37920
|
}
|
|
37732
|
-
if (appIds.size === 0) return void 0;
|
|
37733
37921
|
const fieldInfosByApp = new Map(
|
|
37734
37922
|
await Promise.all([...appIds].map(async (appId) => {
|
|
37735
37923
|
const infos = await getFieldsCached(appId, client, cacheContext);
|
|
@@ -37744,17 +37932,28 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
|
37744
37932
|
info = fieldInfosByApp.get(stmt.from.appId)?.get(ref.field);
|
|
37745
37933
|
} else {
|
|
37746
37934
|
const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
|
|
37747
|
-
if (!table
|
|
37935
|
+
if (!table) return void 0;
|
|
37936
|
+
if (table.cteName !== null) {
|
|
37937
|
+
return materializedTables?.get(table.cteName)?.columnMeta?.get(ref.field)?.sortKind;
|
|
37938
|
+
}
|
|
37748
37939
|
info = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
37749
37940
|
}
|
|
37750
37941
|
} else if (stmt.joins.length === 0) {
|
|
37751
|
-
if (stmt.from.cteName !== null)
|
|
37942
|
+
if (stmt.from.cteName !== null) {
|
|
37943
|
+
return materializedTables?.get(stmt.from.cteName)?.columnMeta?.get(ref.field)?.sortKind;
|
|
37944
|
+
}
|
|
37752
37945
|
info = fieldInfosByApp.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
|
|
37753
37946
|
} else {
|
|
37754
|
-
|
|
37755
|
-
|
|
37947
|
+
const matches = tables.flatMap((table) => {
|
|
37948
|
+
if (table.cteName !== null) {
|
|
37949
|
+
const materialized = materializedTables?.get(table.cteName);
|
|
37950
|
+
return materialized?.columns.includes(ref.field) ? [materialized.columnMeta?.get(ref.field)?.sortKind] : [];
|
|
37951
|
+
}
|
|
37952
|
+
const candidate = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
37953
|
+
return candidate ? [aggregateSortKind(candidate)] : [];
|
|
37954
|
+
});
|
|
37756
37955
|
if (matches.length !== 1) return void 0;
|
|
37757
|
-
|
|
37956
|
+
return matches[0];
|
|
37758
37957
|
}
|
|
37759
37958
|
return info ? aggregateSortKind(info) : void 0;
|
|
37760
37959
|
};
|
|
@@ -37763,6 +37962,108 @@ function fieldCodeForTypeLookup(table, field) {
|
|
|
37763
37962
|
if (table.subtableCode && field.startsWith("_p.")) return field.slice(3);
|
|
37764
37963
|
return field;
|
|
37765
37964
|
}
|
|
37965
|
+
function materializedMetaFromFieldInfo(info) {
|
|
37966
|
+
return { sortKind: aggregateSortKind(info), fieldType: info.fieldType };
|
|
37967
|
+
}
|
|
37968
|
+
function selectNeedsSourceColumnMeta(stmt) {
|
|
37969
|
+
return stmt.columns.some(
|
|
37970
|
+
(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"
|
|
37971
|
+
);
|
|
37972
|
+
}
|
|
37973
|
+
async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext, materializedTables) {
|
|
37974
|
+
const physicalInfos = /* @__PURE__ */ new Map();
|
|
37975
|
+
if (selectNeedsSourceColumnMeta(stmt)) {
|
|
37976
|
+
await Promise.all(physicalSelectTables(stmt).map(async (table) => {
|
|
37977
|
+
if (physicalInfos.has(table.appId)) return;
|
|
37978
|
+
const infos = await getFieldsCached(table.appId, client, cacheContext);
|
|
37979
|
+
physicalInfos.set(table.appId, new Map(infos.map((info) => [info.code, info])));
|
|
37980
|
+
}));
|
|
37981
|
+
}
|
|
37982
|
+
const tables = [stmt.from, ...stmt.joins.map((join) => join.table)];
|
|
37983
|
+
const resolveField2 = (ref) => {
|
|
37984
|
+
if (ref.tableAlias !== null) {
|
|
37985
|
+
if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
37986
|
+
const info2 = physicalInfos.get(stmt.from.appId)?.get(ref.field);
|
|
37987
|
+
return info2 ? materializedMetaFromFieldInfo(info2) : void 0;
|
|
37988
|
+
}
|
|
37989
|
+
const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
|
|
37990
|
+
if (!table) return void 0;
|
|
37991
|
+
if (table.cteName !== null) return materializedTables?.get(table.cteName)?.columnMeta?.get(ref.field);
|
|
37992
|
+
const info = physicalInfos.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
37993
|
+
return info ? materializedMetaFromFieldInfo(info) : void 0;
|
|
37994
|
+
}
|
|
37995
|
+
if (stmt.joins.length === 0) {
|
|
37996
|
+
if (stmt.from.cteName !== null) return materializedTables?.get(stmt.from.cteName)?.columnMeta?.get(ref.field);
|
|
37997
|
+
const info = physicalInfos.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
|
|
37998
|
+
return info ? materializedMetaFromFieldInfo(info) : void 0;
|
|
37999
|
+
}
|
|
38000
|
+
const matches = tables.flatMap((table) => {
|
|
38001
|
+
if (table.cteName !== null) {
|
|
38002
|
+
const materialized = materializedTables?.get(table.cteName);
|
|
38003
|
+
if (!materialized?.columns.includes(ref.field)) return [];
|
|
38004
|
+
return [materialized.columnMeta?.get(ref.field)];
|
|
38005
|
+
}
|
|
38006
|
+
const info = physicalInfos.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
38007
|
+
return info ? [materializedMetaFromFieldInfo(info)] : [];
|
|
38008
|
+
});
|
|
38009
|
+
return matches.length === 1 ? matches[0] : void 0;
|
|
38010
|
+
};
|
|
38011
|
+
const inferred = /* @__PURE__ */ new Map();
|
|
38012
|
+
const hasWildcard = stmt.columns.some((column) => column.type === "WILDCARD" || column.type === "PARENT_WILDCARD");
|
|
38013
|
+
if (stmt.columns.length === 1 && (stmt.columns[0].type === "WILDCARD" || stmt.columns[0].type === "PARENT_WILDCARD")) {
|
|
38014
|
+
for (const output of outputColumns) {
|
|
38015
|
+
const meta3 = resolveField2(aggregateFieldRef(output));
|
|
38016
|
+
if (meta3) inferred.set(output, meta3);
|
|
38017
|
+
}
|
|
38018
|
+
return inferred;
|
|
38019
|
+
}
|
|
38020
|
+
if (hasWildcard) {
|
|
38021
|
+
for (const output of outputColumns) {
|
|
38022
|
+
const meta3 = resolveField2(aggregateFieldRef(output));
|
|
38023
|
+
if (meta3) inferred.set(output, meta3);
|
|
38024
|
+
}
|
|
38025
|
+
}
|
|
38026
|
+
const explicitColumns = stmt.columns.filter(
|
|
38027
|
+
(column) => column.type !== "WILDCARD" && column.type !== "PARENT_WILDCARD"
|
|
38028
|
+
);
|
|
38029
|
+
explicitColumns.forEach((column, index) => {
|
|
38030
|
+
const output = hasWildcard ? "alias" in column && column.alias ? column.alias : void 0 : outputColumns[index];
|
|
38031
|
+
if (!output) return;
|
|
38032
|
+
let meta3;
|
|
38033
|
+
if (column.type === "FIELD") {
|
|
38034
|
+
meta3 = resolveField2(aggregateFieldRef(column.field));
|
|
38035
|
+
} else if (column.type === "AGGREGATE") {
|
|
38036
|
+
if (column.func === "GROUP_CONCAT") {
|
|
38037
|
+
meta3 = { sortKind: "string" };
|
|
38038
|
+
} else if (column.func === "COUNT" || column.func === "SUM" || column.func === "AVG") {
|
|
38039
|
+
meta3 = { sortKind: "number" };
|
|
38040
|
+
} else if ((column.func === "MIN" || column.func === "MAX") && column.arg.type === "FIELD_REF") {
|
|
38041
|
+
const source = resolveField2(aggregateFieldRef(column.arg.field));
|
|
38042
|
+
if (source?.sortKind) meta3 = { sortKind: source.sortKind };
|
|
38043
|
+
}
|
|
38044
|
+
} else if (column.type === "ARITH_AGG_COL" || column.type === "ARITH_COL") {
|
|
38045
|
+
meta3 = { sortKind: "number" };
|
|
38046
|
+
} else if (column.type === "LITERAL_COL") {
|
|
38047
|
+
meta3 = { sortKind: "string" };
|
|
38048
|
+
} else if (column.type === "WINDOW_COL") {
|
|
38049
|
+
meta3 = { sortKind: "number" };
|
|
38050
|
+
}
|
|
38051
|
+
if (meta3) inferred.set(output, meta3);
|
|
38052
|
+
});
|
|
38053
|
+
return inferred;
|
|
38054
|
+
}
|
|
38055
|
+
function mergeUnionColumnMeta(left, right) {
|
|
38056
|
+
const leftMeta = materializedMetaBySelectResult.get(left);
|
|
38057
|
+
const rightMeta = materializedMetaBySelectResult.get(right);
|
|
38058
|
+
const merged = /* @__PURE__ */ new Map();
|
|
38059
|
+
left.columns.forEach((column, index) => {
|
|
38060
|
+
const a = leftMeta?.get(column);
|
|
38061
|
+
const rightColumn = right.columns[index];
|
|
38062
|
+
const b = rightColumn === void 0 ? void 0 : rightMeta?.get(rightColumn);
|
|
38063
|
+
if (a && b && a.sortKind === b.sortKind && a.fieldType === b.fieldType) merged.set(column, a);
|
|
38064
|
+
});
|
|
38065
|
+
return merged;
|
|
38066
|
+
}
|
|
37766
38067
|
function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
|
|
37767
38068
|
const tables = [stmt.from, ...stmt.joins.map((join) => join.table)];
|
|
37768
38069
|
const physicalTables = tables.filter((table) => table.cteName === null);
|
|
@@ -37807,7 +38108,7 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
37807
38108
|
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
37808
38109
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
37809
38110
|
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
37810
|
-
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
38111
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
|
|
37811
38112
|
]);
|
|
37812
38113
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
37813
38114
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -37927,9 +38228,9 @@ function deduplicateRows(rows, columns) {
|
|
|
37927
38228
|
return true;
|
|
37928
38229
|
});
|
|
37929
38230
|
}
|
|
37930
|
-
async function executeWith(stmt, client, options, cacheContext, seed) {
|
|
38231
|
+
async function executeWith(stmt, client, options, cacheContext, seed, captureColumnMeta = false) {
|
|
37931
38232
|
if ((seed == null || seed.size === 0) && canInlineSingleCte(stmt)) {
|
|
37932
|
-
return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext);
|
|
38233
|
+
return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext, void 0, captureColumnMeta);
|
|
37933
38234
|
}
|
|
37934
38235
|
const cteCache = new Map(seed ?? []);
|
|
37935
38236
|
for (const cte of stmt.ctes) {
|
|
@@ -37939,17 +38240,21 @@ async function executeWith(stmt, client, options, cacheContext, seed) {
|
|
|
37939
38240
|
} else if (cte.query.type === "DESCRIBE") {
|
|
37940
38241
|
result = await executeDescribe(cte.query, client, cacheContext);
|
|
37941
38242
|
} else {
|
|
37942
|
-
result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext);
|
|
38243
|
+
result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext, true);
|
|
37943
38244
|
}
|
|
37944
|
-
cteCache.set(cte.name, {
|
|
38245
|
+
cteCache.set(cte.name, {
|
|
38246
|
+
rows: result.rows,
|
|
38247
|
+
columns: result.columns,
|
|
38248
|
+
columnMeta: materializedMetaBySelectResult.get(result)
|
|
38249
|
+
});
|
|
37945
38250
|
}
|
|
37946
|
-
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext);
|
|
38251
|
+
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext, captureColumnMeta);
|
|
37947
38252
|
}
|
|
37948
|
-
async function executeQueryWithCte(query, client, options, cteCache, cacheContext) {
|
|
38253
|
+
async function executeQueryWithCte(query, client, options, cteCache, cacheContext, captureColumnMeta = false) {
|
|
37949
38254
|
if (query.type === "UNION") {
|
|
37950
38255
|
const [leftResult, rightResult] = await Promise.all([
|
|
37951
|
-
executeQueryWithCte(query.left, client, options, cteCache, cacheContext),
|
|
37952
|
-
executeQueryWithCte(query.right, client, options, cteCache, cacheContext)
|
|
38256
|
+
executeQueryWithCte(query.left, client, options, cteCache, cacheContext, captureColumnMeta),
|
|
38257
|
+
executeQueryWithCte(query.right, client, options, cteCache, cacheContext, captureColumnMeta)
|
|
37953
38258
|
]);
|
|
37954
38259
|
const leftCols = leftResult.columns;
|
|
37955
38260
|
const rightCols = rightResult.columns;
|
|
@@ -37962,13 +38267,21 @@ async function executeQueryWithCte(query, client, options, cteCache, cacheContex
|
|
|
37962
38267
|
});
|
|
37963
38268
|
const combined = [...leftResult.rows, ...remapped];
|
|
37964
38269
|
const rows = query.all ? combined : deduplicateRows(combined, leftCols);
|
|
37965
|
-
|
|
38270
|
+
const result2 = { type: "SELECT", rows, columns: leftCols, rowCount: rows.length };
|
|
38271
|
+
if (captureColumnMeta) {
|
|
38272
|
+
materializedMetaBySelectResult.set(result2, mergeUnionColumnMeta(leftResult, rightResult));
|
|
38273
|
+
}
|
|
38274
|
+
return result2;
|
|
37966
38275
|
}
|
|
37967
38276
|
const hasCteRef = query.from.cteName != null && query.from.cteName !== NO_FROM_CTE_NAME || query.joins.some((j) => j.table.cteName != null);
|
|
37968
38277
|
if (!hasCteRef) {
|
|
37969
|
-
return executeSelect(query, client, options, cacheContext, cteCache);
|
|
38278
|
+
return executeSelect(query, client, options, cacheContext, cteCache, captureColumnMeta);
|
|
37970
38279
|
}
|
|
37971
|
-
|
|
38280
|
+
const result = await executeFullScanWithCte(query, client, options, cteCache, cacheContext);
|
|
38281
|
+
if (captureColumnMeta) {
|
|
38282
|
+
materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(query, result.columns, client, cacheContext, cteCache));
|
|
38283
|
+
}
|
|
38284
|
+
return result;
|
|
37972
38285
|
}
|
|
37973
38286
|
async function executeFullScanWithCte(stmt, client, options, cteCache, cacheContext) {
|
|
37974
38287
|
const maxRecords2 = options.maxRecords ?? 1e4;
|
|
@@ -37982,7 +38295,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
37982
38295
|
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
37983
38296
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
37984
38297
|
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
37985
|
-
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
38298
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
|
|
37986
38299
|
]);
|
|
37987
38300
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
37988
38301
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -38319,7 +38632,10 @@ async function getSortKindMapByApp(appId, client, cacheContext) {
|
|
|
38319
38632
|
return map2;
|
|
38320
38633
|
}
|
|
38321
38634
|
async function buildOrderByMetaForSelect(stmt, client, cacheContext) {
|
|
38322
|
-
|
|
38635
|
+
const hasWindowOrderBy = stmt.columns.some(
|
|
38636
|
+
(column) => column.type === "WINDOW_COL" && column.orderBy.length > 0
|
|
38637
|
+
);
|
|
38638
|
+
if (stmt.orderBy.length === 0 && !hasWindowOrderBy) {
|
|
38323
38639
|
return { optionOrders: /* @__PURE__ */ new Map(), sortKinds: /* @__PURE__ */ new Map() };
|
|
38324
38640
|
}
|
|
38325
38641
|
const [optionOrders, sortKinds] = await Promise.all([
|
|
@@ -38460,7 +38776,23 @@ async function prepareDmlValidation(stmt, client, options, cacheContext, tempTab
|
|
|
38460
38776
|
errors,
|
|
38461
38777
|
...stmt.validationErrorTable ? { errTable: stmt.validationErrorTable } : stmt.onErrorSkip && stmt.errorTable ? { errTable: stmt.errorTable } : {}
|
|
38462
38778
|
};
|
|
38463
|
-
|
|
38779
|
+
const columnMeta = /* @__PURE__ */ new Map();
|
|
38780
|
+
for (const column of payloadFields) {
|
|
38781
|
+
if (column === "$id") {
|
|
38782
|
+
columnMeta.set(column, { sortKind: "number", fieldType: "RECORD_NUMBER" });
|
|
38783
|
+
continue;
|
|
38784
|
+
}
|
|
38785
|
+
const info = infoByCode.get(column);
|
|
38786
|
+
if (info) columnMeta.set(column, materializedMetaFromFieldInfo(info));
|
|
38787
|
+
}
|
|
38788
|
+
columnMeta.set("$err_statement", { sortKind: "number" });
|
|
38789
|
+
columnMeta.set("$err_operation", { sortKind: "string" });
|
|
38790
|
+
columnMeta.set("$err_row", { sortKind: "number" });
|
|
38791
|
+
columnMeta.set("$err_field", { sortKind: "string" });
|
|
38792
|
+
columnMeta.set("$err_code", { sortKind: "string" });
|
|
38793
|
+
columnMeta.set("$err_message", { sortKind: "string" });
|
|
38794
|
+
materializedMetaByValidationResult.set(result, columnMeta);
|
|
38795
|
+
return { result, candidates, invalidRowNumbers, columnMeta };
|
|
38464
38796
|
}
|
|
38465
38797
|
async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTables, statementNumber) {
|
|
38466
38798
|
const prepared = await prepareDmlValidation(
|
|
@@ -38478,7 +38810,8 @@ async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTable
|
|
|
38478
38810
|
errTable,
|
|
38479
38811
|
prepared.result.columns,
|
|
38480
38812
|
prepared.result.errors,
|
|
38481
|
-
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
|
|
38813
|
+
options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
|
|
38814
|
+
prepared.columnMeta
|
|
38482
38815
|
);
|
|
38483
38816
|
const rejectLimit = stmt.rejectLimit ?? null;
|
|
38484
38817
|
if (rejectLimit !== null && prepared.result.invalidRows > rejectLimit) {
|
|
@@ -39764,6 +40097,8 @@ function collectFullScanReasons(stmt) {
|
|
|
39764
40097
|
r.push("DISTINCT \u3042\u308A");
|
|
39765
40098
|
if (stmt.columns.some((c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL"))
|
|
39766
40099
|
r.push("\u96C6\u8A08\u95A2\u6570\uFF08COUNT / SUM \u7B49\uFF09\u3042\u308A");
|
|
40100
|
+
if (stmt.columns.some((c) => c.type === "WINDOW_COL"))
|
|
40101
|
+
r.push("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u3042\u308A");
|
|
39767
40102
|
if (stmt.columns.some((c) => c.type === "SCALAR_SUBQUERY_COL"))
|
|
39768
40103
|
r.push("SELECT \u5217\u306B\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA");
|
|
39769
40104
|
if (whereRequiresJsEval(stmt.where))
|
|
@@ -42219,7 +42554,7 @@ Options:
|
|
|
42219
42554
|
-h, --help Show help
|
|
42220
42555
|
`);
|
|
42221
42556
|
}
|
|
42222
|
-
var SERVER_VERSION = true ? "2.
|
|
42557
|
+
var SERVER_VERSION = true ? "2.16.0" : "0.0.0-dev";
|
|
42223
42558
|
function createServer(args) {
|
|
42224
42559
|
const server = new McpServer({
|
|
42225
42560
|
name: "ksql-mcp",
|