@rex0220/kintone-sql-tools 2.13.0 → 2.14.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 +155 -23
- package/dist-mcp/ksql-mcp.js +156 -24
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -5090,7 +5090,7 @@ function hasAggregateColumns(columns) {
|
|
|
5090
5090
|
(c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(c.expr)
|
|
5091
5091
|
);
|
|
5092
5092
|
}
|
|
5093
|
-
function applyGroupBy(rows, groupByKeys, columns) {
|
|
5093
|
+
function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
|
|
5094
5094
|
const groups = /* @__PURE__ */ new Map();
|
|
5095
5095
|
for (const row of rows) {
|
|
5096
5096
|
const key = groupByKeys.map((k) => evalGroupByKey(k, row)).join("\0");
|
|
@@ -5114,15 +5114,15 @@ function applyGroupBy(rows, groupByKeys, columns) {
|
|
|
5114
5114
|
for (const col of columns) {
|
|
5115
5115
|
if (col.type === "AGGREGATE") {
|
|
5116
5116
|
const syntheticKey = aggregateSyntheticName2(col.func, col.distinct, col.arg);
|
|
5117
|
-
const value = String(evalAggregate(col.func, col.distinct, col.arg, groupRows));
|
|
5117
|
+
const value = String(evalAggregate(col.func, col.distinct, col.arg, groupRows, resolveAggSortKind));
|
|
5118
5118
|
outRow[col.alias ?? syntheticKey] = value;
|
|
5119
5119
|
if (col.alias) outRow[syntheticKey] = value;
|
|
5120
5120
|
} else if (col.type === "ARITH_AGG_COL") {
|
|
5121
5121
|
const outputKey = col.alias ?? aggArithDefaultKey(col.expr);
|
|
5122
|
-
outRow[outputKey] = String(evalAggArithExpr(col.expr, groupRows));
|
|
5122
|
+
outRow[outputKey] = String(evalAggArithExpr(col.expr, groupRows, resolveAggSortKind));
|
|
5123
5123
|
} else if (col.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(col.expr)) {
|
|
5124
5124
|
const outputKey = col.alias ?? stringFuncDefaultKey(col.expr);
|
|
5125
|
-
const resolvedExpr = resolveAggInStringFuncExpr(col.expr, groupRows);
|
|
5125
|
+
const resolvedExpr = resolveAggInStringFuncExpr(col.expr, groupRows, resolveAggSortKind);
|
|
5126
5126
|
outRow[outputKey] = evalStringFunc(resolvedExpr, outRow);
|
|
5127
5127
|
}
|
|
5128
5128
|
}
|
|
@@ -5135,7 +5135,7 @@ function evalGroupByKey(key, row) {
|
|
|
5135
5135
|
if (key.type === "FUNC_KEY") return evalStringFunc(key.expr, row);
|
|
5136
5136
|
return String(evalArithExpr(key.expr, row));
|
|
5137
5137
|
}
|
|
5138
|
-
function evalAggregate(func, distinct, arg, rows) {
|
|
5138
|
+
function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
5139
5139
|
if (arg.type === "WILDCARD") {
|
|
5140
5140
|
return func === "COUNT" ? rows.length : 0;
|
|
5141
5141
|
}
|
|
@@ -5155,6 +5155,11 @@ function evalAggregate(func, distinct, arg, rows) {
|
|
|
5155
5155
|
}
|
|
5156
5156
|
const eff = distinct ? [...new Set(strValues)] : strValues;
|
|
5157
5157
|
if (func === "COUNT") return eff.length;
|
|
5158
|
+
const sortKind = (func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" ? resolveAggSortKind?.(toAggregateFieldRef(arg.field)) : void 0;
|
|
5159
|
+
if (sortKind === "string") {
|
|
5160
|
+
if (eff.length === 0) return "";
|
|
5161
|
+
return func === "MAX" ? maxStringOf(eff) : minStringOf(eff);
|
|
5162
|
+
}
|
|
5158
5163
|
const nums = eff.map(Number);
|
|
5159
5164
|
switch (func) {
|
|
5160
5165
|
case "SUM":
|
|
@@ -5168,6 +5173,20 @@ function evalAggregate(func, distinct, arg, rows) {
|
|
|
5168
5173
|
return nums.length === 0 ? 0 : minOf(nums);
|
|
5169
5174
|
}
|
|
5170
5175
|
}
|
|
5176
|
+
function toAggregateFieldRef(field) {
|
|
5177
|
+
const dot = field.indexOf(".");
|
|
5178
|
+
return dot > 0 ? { type: "FIELD", tableAlias: field.slice(0, dot), field: field.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field };
|
|
5179
|
+
}
|
|
5180
|
+
function maxStringOf(values) {
|
|
5181
|
+
let value = values[0];
|
|
5182
|
+
for (const candidate of values) if (candidate > value) value = candidate;
|
|
5183
|
+
return value;
|
|
5184
|
+
}
|
|
5185
|
+
function minStringOf(values) {
|
|
5186
|
+
let value = values[0];
|
|
5187
|
+
for (const candidate of values) if (candidate < value) value = candidate;
|
|
5188
|
+
return value;
|
|
5189
|
+
}
|
|
5171
5190
|
function maxOf(nums) {
|
|
5172
5191
|
let m = nums[0];
|
|
5173
5192
|
for (const n of nums) if (n > m) m = n;
|
|
@@ -5178,11 +5197,11 @@ function minOf(nums) {
|
|
|
5178
5197
|
for (const n of nums) if (n < m) m = n;
|
|
5179
5198
|
return m;
|
|
5180
5199
|
}
|
|
5181
|
-
function evalAggArithExpr(node, rows) {
|
|
5200
|
+
function evalAggArithExpr(node, rows, resolveAggSortKind) {
|
|
5182
5201
|
if (node.type === "NUMBER") return node.value;
|
|
5183
|
-
if (node.type === "AGG_REF") return evalAggregate(node.func, node.distinct, node.arg, rows);
|
|
5184
|
-
const l = evalAggArithExpr(node.left, rows);
|
|
5185
|
-
const r = evalAggArithExpr(node.right, rows);
|
|
5202
|
+
if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, rows, resolveAggSortKind));
|
|
5203
|
+
const l = evalAggArithExpr(node.left, rows, resolveAggSortKind);
|
|
5204
|
+
const r = evalAggArithExpr(node.right, rows, resolveAggSortKind);
|
|
5186
5205
|
switch (node.op) {
|
|
5187
5206
|
case "+":
|
|
5188
5207
|
return l + r;
|
|
@@ -5527,26 +5546,24 @@ function hasAggregateInStringFuncArg(arg) {
|
|
|
5527
5546
|
function hasAggregateInStringFuncExpr2(expr) {
|
|
5528
5547
|
return expr.args.some((arg) => hasAggregateInStringFuncArg(arg));
|
|
5529
5548
|
}
|
|
5530
|
-
function resolveAggInStringFuncArg(arg, rows) {
|
|
5549
|
+
function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
|
|
5531
5550
|
if (arg.type === "AGG_REF") {
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
value: evalAggregate(arg.func, arg.distinct, arg.arg, rows)
|
|
5535
|
-
};
|
|
5551
|
+
const value = evalAggregate(arg.func, arg.distinct, arg.arg, rows, resolveAggSortKind);
|
|
5552
|
+
return typeof value === "number" ? { type: "NUMBER", value } : { type: "STRING", value };
|
|
5536
5553
|
}
|
|
5537
5554
|
if (arg.type === "AGG_ARITH") {
|
|
5538
|
-
return { type: "NUMBER", value: evalAggArithExpr(arg, rows) };
|
|
5555
|
+
return { type: "NUMBER", value: evalAggArithExpr(arg, rows, resolveAggSortKind) };
|
|
5539
5556
|
}
|
|
5540
5557
|
if (arg.type === "STRING_FUNC") {
|
|
5541
|
-
return resolveAggInStringFuncExpr(arg, rows);
|
|
5558
|
+
return resolveAggInStringFuncExpr(arg, rows, resolveAggSortKind);
|
|
5542
5559
|
}
|
|
5543
5560
|
return arg;
|
|
5544
5561
|
}
|
|
5545
|
-
function resolveAggInStringFuncExpr(expr, rows) {
|
|
5562
|
+
function resolveAggInStringFuncExpr(expr, rows, resolveAggSortKind) {
|
|
5546
5563
|
return {
|
|
5547
5564
|
type: "STRING_FUNC",
|
|
5548
5565
|
func: expr.func,
|
|
5549
|
-
args: expr.args.map((arg) => resolveAggInStringFuncArg(arg, rows))
|
|
5566
|
+
args: expr.args.map((arg) => resolveAggInStringFuncArg(arg, rows, resolveAggSortKind))
|
|
5550
5567
|
};
|
|
5551
5568
|
}
|
|
5552
5569
|
function runFullScan(input) {
|
|
@@ -5558,6 +5575,7 @@ function runFullScan(input) {
|
|
|
5558
5575
|
sortKinds,
|
|
5559
5576
|
fieldTypeResolver,
|
|
5560
5577
|
havingFieldTypeResolver,
|
|
5578
|
+
aggregateSortKindResolver,
|
|
5561
5579
|
appliedKlikes,
|
|
5562
5580
|
sourceColumns
|
|
5563
5581
|
} = input;
|
|
@@ -5573,7 +5591,7 @@ function runFullScan(input) {
|
|
|
5573
5591
|
}
|
|
5574
5592
|
rows = applyFilter(rows, stmt.where, fieldTypeResolver, appliedKlikes);
|
|
5575
5593
|
if (stmt.groupBy.length > 0 || hasAggregateColumns(stmt.columns)) {
|
|
5576
|
-
rows = applyGroupBy(rows, stmt.groupBy, stmt.columns);
|
|
5594
|
+
rows = applyGroupBy(rows, stmt.groupBy, stmt.columns, aggregateSortKindResolver);
|
|
5577
5595
|
}
|
|
5578
5596
|
rows = applyHaving(rows, stmt.having, havingFieldTypeResolver);
|
|
5579
5597
|
if (stmt.distinct) {
|
|
@@ -6722,6 +6740,116 @@ async function loadTypedInFieldTypes(stmt, client, cacheContext) {
|
|
|
6722
6740
|
const entries = await Promise.all([...appIds].map(async (appId) => [appId, await getFieldTypeMap(appId, client, cacheContext)]));
|
|
6723
6741
|
return new Map(entries);
|
|
6724
6742
|
}
|
|
6743
|
+
function aggregateFieldRef(field) {
|
|
6744
|
+
const dot = field.indexOf(".");
|
|
6745
|
+
return dot > 0 ? { type: "FIELD", tableAlias: field.slice(0, dot), field: field.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field };
|
|
6746
|
+
}
|
|
6747
|
+
function collectAggregateRef(func, arg, out) {
|
|
6748
|
+
if ((func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" && arg.field) {
|
|
6749
|
+
out.push(aggregateFieldRef(arg.field));
|
|
6750
|
+
}
|
|
6751
|
+
}
|
|
6752
|
+
function collectAggregateOperandRefs(node, out) {
|
|
6753
|
+
if (node.type === "AGG_REF") {
|
|
6754
|
+
collectAggregateRef(node.func, node.arg, out);
|
|
6755
|
+
return;
|
|
6756
|
+
}
|
|
6757
|
+
if (node.type === "AGG_ARITH") {
|
|
6758
|
+
collectAggregateOperandRefs(node.left, out);
|
|
6759
|
+
collectAggregateOperandRefs(node.right, out);
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
function collectStringFuncAggregateRefs(expr, out) {
|
|
6763
|
+
for (const arg of expr.args) {
|
|
6764
|
+
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
6765
|
+
collectAggregateOperandRefs(arg, out);
|
|
6766
|
+
} else if (arg.type === "STRING_FUNC") {
|
|
6767
|
+
collectStringFuncAggregateRefs(arg, out);
|
|
6768
|
+
}
|
|
6769
|
+
}
|
|
6770
|
+
}
|
|
6771
|
+
function collectSelectAggregateSortRefs(columns) {
|
|
6772
|
+
const refs = [];
|
|
6773
|
+
for (const column of columns) {
|
|
6774
|
+
if (column.type === "AGGREGATE") {
|
|
6775
|
+
collectAggregateRef(column.func, column.arg, refs);
|
|
6776
|
+
} else if (column.type === "ARITH_AGG_COL") {
|
|
6777
|
+
collectAggregateOperandRefs(column.expr, refs);
|
|
6778
|
+
} else if (column.type === "STRFUNC_COL") {
|
|
6779
|
+
collectStringFuncAggregateRefs(column.expr, refs);
|
|
6780
|
+
}
|
|
6781
|
+
}
|
|
6782
|
+
return refs;
|
|
6783
|
+
}
|
|
6784
|
+
var AGGREGATE_STRING_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
6785
|
+
"SINGLE_LINE_TEXT",
|
|
6786
|
+
"MULTI_LINE_TEXT",
|
|
6787
|
+
"RICH_TEXT",
|
|
6788
|
+
"LINK",
|
|
6789
|
+
"DROP_DOWN",
|
|
6790
|
+
"RADIO_BUTTON",
|
|
6791
|
+
"STATUS",
|
|
6792
|
+
"DATE",
|
|
6793
|
+
"TIME",
|
|
6794
|
+
"DATETIME",
|
|
6795
|
+
"CREATED_TIME",
|
|
6796
|
+
"UPDATED_TIME"
|
|
6797
|
+
]);
|
|
6798
|
+
function aggregateSortKind(info) {
|
|
6799
|
+
if (info.sortKind !== void 0) return info.sortKind;
|
|
6800
|
+
if (info.fieldType === "NUMBER" || info.fieldType === "RECORD_NUMBER") return "number";
|
|
6801
|
+
return AGGREGATE_STRING_FIELD_TYPES.has(info.fieldType) ? "string" : void 0;
|
|
6802
|
+
}
|
|
6803
|
+
async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
6804
|
+
const refs = collectSelectAggregateSortRefs(stmt.columns);
|
|
6805
|
+
if (refs.length === 0) return void 0;
|
|
6806
|
+
const appIds = /* @__PURE__ */ new Set();
|
|
6807
|
+
const physicalTables = physicalSelectTables(stmt);
|
|
6808
|
+
for (const ref of refs) {
|
|
6809
|
+
if (ref.tableAlias !== null) {
|
|
6810
|
+
if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
6811
|
+
appIds.add(stmt.from.appId);
|
|
6812
|
+
continue;
|
|
6813
|
+
}
|
|
6814
|
+
const table = findTableForAlias(stmt, ref.tableAlias);
|
|
6815
|
+
if (table && table.cteName === null) appIds.add(table.appId);
|
|
6816
|
+
} else if (stmt.joins.length === 0) {
|
|
6817
|
+
if (stmt.from.cteName === null) appIds.add(stmt.from.appId);
|
|
6818
|
+
} else {
|
|
6819
|
+
if ([stmt.from, ...stmt.joins.map((join2) => join2.table)].some((table) => table.cteName !== null)) continue;
|
|
6820
|
+
for (const table of physicalTables) appIds.add(table.appId);
|
|
6821
|
+
}
|
|
6822
|
+
}
|
|
6823
|
+
if (appIds.size === 0) return void 0;
|
|
6824
|
+
const fieldInfosByApp = new Map(
|
|
6825
|
+
await Promise.all([...appIds].map(async (appId) => {
|
|
6826
|
+
const infos = await getFieldsCached(appId, client, cacheContext);
|
|
6827
|
+
return [appId, new Map(infos.map((info) => [info.code, info]))];
|
|
6828
|
+
}))
|
|
6829
|
+
);
|
|
6830
|
+
const tables = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
6831
|
+
return (ref) => {
|
|
6832
|
+
let info;
|
|
6833
|
+
if (ref.tableAlias !== null) {
|
|
6834
|
+
if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
6835
|
+
info = fieldInfosByApp.get(stmt.from.appId)?.get(ref.field);
|
|
6836
|
+
} else {
|
|
6837
|
+
const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
|
|
6838
|
+
if (!table || table.cteName !== null) return void 0;
|
|
6839
|
+
info = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
6840
|
+
}
|
|
6841
|
+
} else if (stmt.joins.length === 0) {
|
|
6842
|
+
if (stmt.from.cteName !== null) return void 0;
|
|
6843
|
+
info = fieldInfosByApp.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
|
|
6844
|
+
} else {
|
|
6845
|
+
if (tables.some((table) => table.cteName !== null)) return void 0;
|
|
6846
|
+
const matches = physicalTables.map((table) => fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field))).filter((candidate) => candidate !== void 0);
|
|
6847
|
+
if (matches.length !== 1) return void 0;
|
|
6848
|
+
info = matches[0];
|
|
6849
|
+
}
|
|
6850
|
+
return info ? aggregateSortKind(info) : void 0;
|
|
6851
|
+
};
|
|
6852
|
+
}
|
|
6725
6853
|
function fieldCodeForTypeLookup(table, field) {
|
|
6726
6854
|
if (table.subtableCode && field.startsWith("_p.")) return field.slice(3);
|
|
6727
6855
|
return field;
|
|
@@ -6767,9 +6895,10 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
6767
6895
|
resolveSubqueries(stmt.where, client, options, cacheContext, cteCache),
|
|
6768
6896
|
resolveSubqueries(stmt.having, client, options, cacheContext, cteCache)
|
|
6769
6897
|
]);
|
|
6770
|
-
const [pushdownMeta, typedInFieldTypes] = await Promise.all([
|
|
6898
|
+
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
6771
6899
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
6772
|
-
loadTypedInFieldTypes(stmt, client, cacheContext)
|
|
6900
|
+
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
6901
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
6773
6902
|
]);
|
|
6774
6903
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
6775
6904
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -6857,6 +6986,7 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
6857
6986
|
sortKinds,
|
|
6858
6987
|
fieldTypeResolver: fieldTypeResolvers.row,
|
|
6859
6988
|
havingFieldTypeResolver: fieldTypeResolvers.having,
|
|
6989
|
+
aggregateSortKindResolver,
|
|
6860
6990
|
appliedKlikes: pushdownPlan.appliedKlikes
|
|
6861
6991
|
});
|
|
6862
6992
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
@@ -6940,9 +7070,10 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
6940
7070
|
resolveSubqueries(stmt.having, client, options, cacheContext, cteCache),
|
|
6941
7071
|
resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache)
|
|
6942
7072
|
]);
|
|
6943
|
-
const [pushdownMeta, typedInFieldTypes] = await Promise.all([
|
|
7073
|
+
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
6944
7074
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
6945
|
-
loadTypedInFieldTypes(stmt, client, cacheContext)
|
|
7075
|
+
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
7076
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
6946
7077
|
]);
|
|
6947
7078
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
6948
7079
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -7014,6 +7145,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
7014
7145
|
sortKinds,
|
|
7015
7146
|
fieldTypeResolver: fieldTypeResolvers.row,
|
|
7016
7147
|
havingFieldTypeResolver: fieldTypeResolvers.having,
|
|
7148
|
+
aggregateSortKindResolver,
|
|
7017
7149
|
appliedKlikes: pushdownPlan.appliedKlikes,
|
|
7018
7150
|
sourceColumns
|
|
7019
7151
|
});
|
package/dist-mcp/ksql-mcp.js
CHANGED
|
@@ -35990,7 +35990,7 @@ function hasAggregateColumns(columns) {
|
|
|
35990
35990
|
(c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(c.expr)
|
|
35991
35991
|
);
|
|
35992
35992
|
}
|
|
35993
|
-
function applyGroupBy(rows, groupByKeys, columns) {
|
|
35993
|
+
function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
|
|
35994
35994
|
const groups = /* @__PURE__ */ new Map();
|
|
35995
35995
|
for (const row of rows) {
|
|
35996
35996
|
const key = groupByKeys.map((k) => evalGroupByKey(k, row)).join("\0");
|
|
@@ -36014,15 +36014,15 @@ function applyGroupBy(rows, groupByKeys, columns) {
|
|
|
36014
36014
|
for (const col of columns) {
|
|
36015
36015
|
if (col.type === "AGGREGATE") {
|
|
36016
36016
|
const syntheticKey = aggregateSyntheticName2(col.func, col.distinct, col.arg);
|
|
36017
|
-
const value = String(evalAggregate(col.func, col.distinct, col.arg, groupRows));
|
|
36017
|
+
const value = String(evalAggregate(col.func, col.distinct, col.arg, groupRows, resolveAggSortKind));
|
|
36018
36018
|
outRow[col.alias ?? syntheticKey] = value;
|
|
36019
36019
|
if (col.alias) outRow[syntheticKey] = value;
|
|
36020
36020
|
} else if (col.type === "ARITH_AGG_COL") {
|
|
36021
36021
|
const outputKey = col.alias ?? aggArithDefaultKey(col.expr);
|
|
36022
|
-
outRow[outputKey] = String(evalAggArithExpr(col.expr, groupRows));
|
|
36022
|
+
outRow[outputKey] = String(evalAggArithExpr(col.expr, groupRows, resolveAggSortKind));
|
|
36023
36023
|
} else if (col.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(col.expr)) {
|
|
36024
36024
|
const outputKey = col.alias ?? stringFuncDefaultKey(col.expr);
|
|
36025
|
-
const resolvedExpr = resolveAggInStringFuncExpr(col.expr, groupRows);
|
|
36025
|
+
const resolvedExpr = resolveAggInStringFuncExpr(col.expr, groupRows, resolveAggSortKind);
|
|
36026
36026
|
outRow[outputKey] = evalStringFunc(resolvedExpr, outRow);
|
|
36027
36027
|
}
|
|
36028
36028
|
}
|
|
@@ -36035,7 +36035,7 @@ function evalGroupByKey(key, row) {
|
|
|
36035
36035
|
if (key.type === "FUNC_KEY") return evalStringFunc(key.expr, row);
|
|
36036
36036
|
return String(evalArithExpr(key.expr, row));
|
|
36037
36037
|
}
|
|
36038
|
-
function evalAggregate(func, distinct, arg, rows) {
|
|
36038
|
+
function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
|
|
36039
36039
|
if (arg.type === "WILDCARD") {
|
|
36040
36040
|
return func === "COUNT" ? rows.length : 0;
|
|
36041
36041
|
}
|
|
@@ -36055,6 +36055,11 @@ function evalAggregate(func, distinct, arg, rows) {
|
|
|
36055
36055
|
}
|
|
36056
36056
|
const eff = distinct ? [...new Set(strValues)] : strValues;
|
|
36057
36057
|
if (func === "COUNT") return eff.length;
|
|
36058
|
+
const sortKind = (func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" ? resolveAggSortKind?.(toAggregateFieldRef(arg.field)) : void 0;
|
|
36059
|
+
if (sortKind === "string") {
|
|
36060
|
+
if (eff.length === 0) return "";
|
|
36061
|
+
return func === "MAX" ? maxStringOf(eff) : minStringOf(eff);
|
|
36062
|
+
}
|
|
36058
36063
|
const nums = eff.map(Number);
|
|
36059
36064
|
switch (func) {
|
|
36060
36065
|
case "SUM":
|
|
@@ -36068,6 +36073,20 @@ function evalAggregate(func, distinct, arg, rows) {
|
|
|
36068
36073
|
return nums.length === 0 ? 0 : minOf(nums);
|
|
36069
36074
|
}
|
|
36070
36075
|
}
|
|
36076
|
+
function toAggregateFieldRef(field) {
|
|
36077
|
+
const dot = field.indexOf(".");
|
|
36078
|
+
return dot > 0 ? { type: "FIELD", tableAlias: field.slice(0, dot), field: field.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field };
|
|
36079
|
+
}
|
|
36080
|
+
function maxStringOf(values) {
|
|
36081
|
+
let value = values[0];
|
|
36082
|
+
for (const candidate of values) if (candidate > value) value = candidate;
|
|
36083
|
+
return value;
|
|
36084
|
+
}
|
|
36085
|
+
function minStringOf(values) {
|
|
36086
|
+
let value = values[0];
|
|
36087
|
+
for (const candidate of values) if (candidate < value) value = candidate;
|
|
36088
|
+
return value;
|
|
36089
|
+
}
|
|
36071
36090
|
function maxOf(nums) {
|
|
36072
36091
|
let m = nums[0];
|
|
36073
36092
|
for (const n of nums) if (n > m) m = n;
|
|
@@ -36078,11 +36097,11 @@ function minOf(nums) {
|
|
|
36078
36097
|
for (const n of nums) if (n < m) m = n;
|
|
36079
36098
|
return m;
|
|
36080
36099
|
}
|
|
36081
|
-
function evalAggArithExpr(node, rows) {
|
|
36100
|
+
function evalAggArithExpr(node, rows, resolveAggSortKind) {
|
|
36082
36101
|
if (node.type === "NUMBER") return node.value;
|
|
36083
|
-
if (node.type === "AGG_REF") return evalAggregate(node.func, node.distinct, node.arg, rows);
|
|
36084
|
-
const l = evalAggArithExpr(node.left, rows);
|
|
36085
|
-
const r = evalAggArithExpr(node.right, rows);
|
|
36102
|
+
if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, rows, resolveAggSortKind));
|
|
36103
|
+
const l = evalAggArithExpr(node.left, rows, resolveAggSortKind);
|
|
36104
|
+
const r = evalAggArithExpr(node.right, rows, resolveAggSortKind);
|
|
36086
36105
|
switch (node.op) {
|
|
36087
36106
|
case "+":
|
|
36088
36107
|
return l + r;
|
|
@@ -36427,26 +36446,24 @@ function hasAggregateInStringFuncArg(arg) {
|
|
|
36427
36446
|
function hasAggregateInStringFuncExpr2(expr) {
|
|
36428
36447
|
return expr.args.some((arg) => hasAggregateInStringFuncArg(arg));
|
|
36429
36448
|
}
|
|
36430
|
-
function resolveAggInStringFuncArg(arg, rows) {
|
|
36449
|
+
function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
|
|
36431
36450
|
if (arg.type === "AGG_REF") {
|
|
36432
|
-
|
|
36433
|
-
|
|
36434
|
-
value: evalAggregate(arg.func, arg.distinct, arg.arg, rows)
|
|
36435
|
-
};
|
|
36451
|
+
const value = evalAggregate(arg.func, arg.distinct, arg.arg, rows, resolveAggSortKind);
|
|
36452
|
+
return typeof value === "number" ? { type: "NUMBER", value } : { type: "STRING", value };
|
|
36436
36453
|
}
|
|
36437
36454
|
if (arg.type === "AGG_ARITH") {
|
|
36438
|
-
return { type: "NUMBER", value: evalAggArithExpr(arg, rows) };
|
|
36455
|
+
return { type: "NUMBER", value: evalAggArithExpr(arg, rows, resolveAggSortKind) };
|
|
36439
36456
|
}
|
|
36440
36457
|
if (arg.type === "STRING_FUNC") {
|
|
36441
|
-
return resolveAggInStringFuncExpr(arg, rows);
|
|
36458
|
+
return resolveAggInStringFuncExpr(arg, rows, resolveAggSortKind);
|
|
36442
36459
|
}
|
|
36443
36460
|
return arg;
|
|
36444
36461
|
}
|
|
36445
|
-
function resolveAggInStringFuncExpr(expr, rows) {
|
|
36462
|
+
function resolveAggInStringFuncExpr(expr, rows, resolveAggSortKind) {
|
|
36446
36463
|
return {
|
|
36447
36464
|
type: "STRING_FUNC",
|
|
36448
36465
|
func: expr.func,
|
|
36449
|
-
args: expr.args.map((arg) => resolveAggInStringFuncArg(arg, rows))
|
|
36466
|
+
args: expr.args.map((arg) => resolveAggInStringFuncArg(arg, rows, resolveAggSortKind))
|
|
36450
36467
|
};
|
|
36451
36468
|
}
|
|
36452
36469
|
function runFullScan(input) {
|
|
@@ -36458,6 +36475,7 @@ function runFullScan(input) {
|
|
|
36458
36475
|
sortKinds,
|
|
36459
36476
|
fieldTypeResolver,
|
|
36460
36477
|
havingFieldTypeResolver,
|
|
36478
|
+
aggregateSortKindResolver,
|
|
36461
36479
|
appliedKlikes,
|
|
36462
36480
|
sourceColumns
|
|
36463
36481
|
} = input;
|
|
@@ -36473,7 +36491,7 @@ function runFullScan(input) {
|
|
|
36473
36491
|
}
|
|
36474
36492
|
rows = applyFilter(rows, stmt.where, fieldTypeResolver, appliedKlikes);
|
|
36475
36493
|
if (stmt.groupBy.length > 0 || hasAggregateColumns(stmt.columns)) {
|
|
36476
|
-
rows = applyGroupBy(rows, stmt.groupBy, stmt.columns);
|
|
36494
|
+
rows = applyGroupBy(rows, stmt.groupBy, stmt.columns, aggregateSortKindResolver);
|
|
36477
36495
|
}
|
|
36478
36496
|
rows = applyHaving(rows, stmt.having, havingFieldTypeResolver);
|
|
36479
36497
|
if (stmt.distinct) {
|
|
@@ -37622,6 +37640,116 @@ async function loadTypedInFieldTypes(stmt, client, cacheContext) {
|
|
|
37622
37640
|
const entries = await Promise.all([...appIds].map(async (appId) => [appId, await getFieldTypeMap(appId, client, cacheContext)]));
|
|
37623
37641
|
return new Map(entries);
|
|
37624
37642
|
}
|
|
37643
|
+
function aggregateFieldRef(field) {
|
|
37644
|
+
const dot = field.indexOf(".");
|
|
37645
|
+
return dot > 0 ? { type: "FIELD", tableAlias: field.slice(0, dot), field: field.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field };
|
|
37646
|
+
}
|
|
37647
|
+
function collectAggregateRef(func, arg, out) {
|
|
37648
|
+
if ((func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" && arg.field) {
|
|
37649
|
+
out.push(aggregateFieldRef(arg.field));
|
|
37650
|
+
}
|
|
37651
|
+
}
|
|
37652
|
+
function collectAggregateOperandRefs(node, out) {
|
|
37653
|
+
if (node.type === "AGG_REF") {
|
|
37654
|
+
collectAggregateRef(node.func, node.arg, out);
|
|
37655
|
+
return;
|
|
37656
|
+
}
|
|
37657
|
+
if (node.type === "AGG_ARITH") {
|
|
37658
|
+
collectAggregateOperandRefs(node.left, out);
|
|
37659
|
+
collectAggregateOperandRefs(node.right, out);
|
|
37660
|
+
}
|
|
37661
|
+
}
|
|
37662
|
+
function collectStringFuncAggregateRefs(expr, out) {
|
|
37663
|
+
for (const arg of expr.args) {
|
|
37664
|
+
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
37665
|
+
collectAggregateOperandRefs(arg, out);
|
|
37666
|
+
} else if (arg.type === "STRING_FUNC") {
|
|
37667
|
+
collectStringFuncAggregateRefs(arg, out);
|
|
37668
|
+
}
|
|
37669
|
+
}
|
|
37670
|
+
}
|
|
37671
|
+
function collectSelectAggregateSortRefs(columns) {
|
|
37672
|
+
const refs = [];
|
|
37673
|
+
for (const column of columns) {
|
|
37674
|
+
if (column.type === "AGGREGATE") {
|
|
37675
|
+
collectAggregateRef(column.func, column.arg, refs);
|
|
37676
|
+
} else if (column.type === "ARITH_AGG_COL") {
|
|
37677
|
+
collectAggregateOperandRefs(column.expr, refs);
|
|
37678
|
+
} else if (column.type === "STRFUNC_COL") {
|
|
37679
|
+
collectStringFuncAggregateRefs(column.expr, refs);
|
|
37680
|
+
}
|
|
37681
|
+
}
|
|
37682
|
+
return refs;
|
|
37683
|
+
}
|
|
37684
|
+
var AGGREGATE_STRING_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
37685
|
+
"SINGLE_LINE_TEXT",
|
|
37686
|
+
"MULTI_LINE_TEXT",
|
|
37687
|
+
"RICH_TEXT",
|
|
37688
|
+
"LINK",
|
|
37689
|
+
"DROP_DOWN",
|
|
37690
|
+
"RADIO_BUTTON",
|
|
37691
|
+
"STATUS",
|
|
37692
|
+
"DATE",
|
|
37693
|
+
"TIME",
|
|
37694
|
+
"DATETIME",
|
|
37695
|
+
"CREATED_TIME",
|
|
37696
|
+
"UPDATED_TIME"
|
|
37697
|
+
]);
|
|
37698
|
+
function aggregateSortKind(info) {
|
|
37699
|
+
if (info.sortKind !== void 0) return info.sortKind;
|
|
37700
|
+
if (info.fieldType === "NUMBER" || info.fieldType === "RECORD_NUMBER") return "number";
|
|
37701
|
+
return AGGREGATE_STRING_FIELD_TYPES.has(info.fieldType) ? "string" : void 0;
|
|
37702
|
+
}
|
|
37703
|
+
async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
|
|
37704
|
+
const refs = collectSelectAggregateSortRefs(stmt.columns);
|
|
37705
|
+
if (refs.length === 0) return void 0;
|
|
37706
|
+
const appIds = /* @__PURE__ */ new Set();
|
|
37707
|
+
const physicalTables = physicalSelectTables(stmt);
|
|
37708
|
+
for (const ref of refs) {
|
|
37709
|
+
if (ref.tableAlias !== null) {
|
|
37710
|
+
if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
37711
|
+
appIds.add(stmt.from.appId);
|
|
37712
|
+
continue;
|
|
37713
|
+
}
|
|
37714
|
+
const table = findTableForAlias(stmt, ref.tableAlias);
|
|
37715
|
+
if (table && table.cteName === null) appIds.add(table.appId);
|
|
37716
|
+
} else if (stmt.joins.length === 0) {
|
|
37717
|
+
if (stmt.from.cteName === null) appIds.add(stmt.from.appId);
|
|
37718
|
+
} else {
|
|
37719
|
+
if ([stmt.from, ...stmt.joins.map((join) => join.table)].some((table) => table.cteName !== null)) continue;
|
|
37720
|
+
for (const table of physicalTables) appIds.add(table.appId);
|
|
37721
|
+
}
|
|
37722
|
+
}
|
|
37723
|
+
if (appIds.size === 0) return void 0;
|
|
37724
|
+
const fieldInfosByApp = new Map(
|
|
37725
|
+
await Promise.all([...appIds].map(async (appId) => {
|
|
37726
|
+
const infos = await getFieldsCached(appId, client, cacheContext);
|
|
37727
|
+
return [appId, new Map(infos.map((info) => [info.code, info]))];
|
|
37728
|
+
}))
|
|
37729
|
+
);
|
|
37730
|
+
const tables = [stmt.from, ...stmt.joins.map((join) => join.table)];
|
|
37731
|
+
return (ref) => {
|
|
37732
|
+
let info;
|
|
37733
|
+
if (ref.tableAlias !== null) {
|
|
37734
|
+
if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
37735
|
+
info = fieldInfosByApp.get(stmt.from.appId)?.get(ref.field);
|
|
37736
|
+
} else {
|
|
37737
|
+
const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
|
|
37738
|
+
if (!table || table.cteName !== null) return void 0;
|
|
37739
|
+
info = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
|
|
37740
|
+
}
|
|
37741
|
+
} else if (stmt.joins.length === 0) {
|
|
37742
|
+
if (stmt.from.cteName !== null) return void 0;
|
|
37743
|
+
info = fieldInfosByApp.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
|
|
37744
|
+
} else {
|
|
37745
|
+
if (tables.some((table) => table.cteName !== null)) return void 0;
|
|
37746
|
+
const matches = physicalTables.map((table) => fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field))).filter((candidate) => candidate !== void 0);
|
|
37747
|
+
if (matches.length !== 1) return void 0;
|
|
37748
|
+
info = matches[0];
|
|
37749
|
+
}
|
|
37750
|
+
return info ? aggregateSortKind(info) : void 0;
|
|
37751
|
+
};
|
|
37752
|
+
}
|
|
37625
37753
|
function fieldCodeForTypeLookup(table, field) {
|
|
37626
37754
|
if (table.subtableCode && field.startsWith("_p.")) return field.slice(3);
|
|
37627
37755
|
return field;
|
|
@@ -37667,9 +37795,10 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
37667
37795
|
resolveSubqueries(stmt.where, client, options, cacheContext, cteCache),
|
|
37668
37796
|
resolveSubqueries(stmt.having, client, options, cacheContext, cteCache)
|
|
37669
37797
|
]);
|
|
37670
|
-
const [pushdownMeta, typedInFieldTypes] = await Promise.all([
|
|
37798
|
+
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
37671
37799
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
37672
|
-
loadTypedInFieldTypes(stmt, client, cacheContext)
|
|
37800
|
+
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
37801
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
37673
37802
|
]);
|
|
37674
37803
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
37675
37804
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -37757,6 +37886,7 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
37757
37886
|
sortKinds,
|
|
37758
37887
|
fieldTypeResolver: fieldTypeResolvers.row,
|
|
37759
37888
|
havingFieldTypeResolver: fieldTypeResolvers.having,
|
|
37889
|
+
aggregateSortKindResolver,
|
|
37760
37890
|
appliedKlikes: pushdownPlan.appliedKlikes
|
|
37761
37891
|
});
|
|
37762
37892
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
@@ -37840,9 +37970,10 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
37840
37970
|
resolveSubqueries(stmt.having, client, options, cacheContext, cteCache),
|
|
37841
37971
|
resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache)
|
|
37842
37972
|
]);
|
|
37843
|
-
const [pushdownMeta, typedInFieldTypes] = await Promise.all([
|
|
37973
|
+
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
37844
37974
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
37845
|
-
loadTypedInFieldTypes(stmt, client, cacheContext)
|
|
37975
|
+
loadTypedInFieldTypes(stmt, client, cacheContext),
|
|
37976
|
+
loadAggregateSortKindResolver(stmt, client, cacheContext)
|
|
37846
37977
|
]);
|
|
37847
37978
|
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
37848
37979
|
const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
|
|
@@ -37914,6 +38045,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
37914
38045
|
sortKinds,
|
|
37915
38046
|
fieldTypeResolver: fieldTypeResolvers.row,
|
|
37916
38047
|
havingFieldTypeResolver: fieldTypeResolvers.having,
|
|
38048
|
+
aggregateSortKindResolver,
|
|
37917
38049
|
appliedKlikes: pushdownPlan.appliedKlikes,
|
|
37918
38050
|
sourceColumns
|
|
37919
38051
|
});
|
|
@@ -42078,7 +42210,7 @@ Options:
|
|
|
42078
42210
|
-h, --help Show help
|
|
42079
42211
|
`);
|
|
42080
42212
|
}
|
|
42081
|
-
var SERVER_VERSION = true ? "2.
|
|
42213
|
+
var SERVER_VERSION = true ? "2.14.0" : "0.0.0-dev";
|
|
42082
42214
|
function createServer(args) {
|
|
42083
42215
|
const server = new McpServer({
|
|
42084
42216
|
name: "ksql-mcp",
|
package/dist-mcpb/ksql-mcp.mcpb
CHANGED
|
Binary file
|