@rex0220/kintone-sql-tools 3.56.3 → 3.58.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 +828 -317
- package/dist-engine/index.cjs +14 -14
- package/dist-engine/index.mjs +14 -14
- package/dist-engine/ksql-engine.umd.js +14 -14
- package/dist-engine/meta/bundle-baseline.json +10 -10
- package/dist-engine/meta/cjs.json +77 -48
- package/dist-engine/meta/esm.json +77 -48
- package/dist-engine/meta/umd.json +77 -48
- package/dist-mcp/ksql-mcp.js +837 -323
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -604,7 +604,7 @@ function expandCubeGroupingSets(items) {
|
|
|
604
604
|
if (expandedSetCount > Math.floor(B65_MAX_GROUPING_SETS / 2)) {
|
|
605
605
|
const rejectedSetCount = expandedSetCount * 2;
|
|
606
606
|
throw new Error(
|
|
607
|
-
`ArgumentError:
|
|
607
|
+
`ArgumentError: expanded grouping set count ${rejectedSetCount} exceeds limit ${B65_MAX_GROUPING_SETS} (reason=GROUPING_SET_LIMIT_EXCEEDED).`
|
|
608
608
|
);
|
|
609
609
|
}
|
|
610
610
|
expandedSetCount *= 2;
|
|
@@ -5622,26 +5622,488 @@ function evalGroupingRef(ref, row) {
|
|
|
5622
5622
|
return membership.has(canonicalId) ? "0" : "1";
|
|
5623
5623
|
}
|
|
5624
5624
|
|
|
5625
|
+
// src/core/systemFields.ts
|
|
5626
|
+
var APP_SYSTEM_FIELD_CODES = [
|
|
5627
|
+
"$id",
|
|
5628
|
+
"$revision",
|
|
5629
|
+
"\u30EC\u30B3\u30FC\u30C9\u756A\u53F7",
|
|
5630
|
+
"\u4F5C\u6210\u8005",
|
|
5631
|
+
"\u4F5C\u6210\u65E5\u6642",
|
|
5632
|
+
"\u66F4\u65B0\u8005",
|
|
5633
|
+
"\u66F4\u65B0\u65E5\u6642",
|
|
5634
|
+
"\u30B9\u30C6\u30FC\u30BF\u30B9",
|
|
5635
|
+
"\u4F5C\u696D\u8005"
|
|
5636
|
+
];
|
|
5637
|
+
function isSystemLikeFieldCode(code) {
|
|
5638
|
+
return code.startsWith("_") || code.startsWith("$");
|
|
5639
|
+
}
|
|
5640
|
+
|
|
5641
|
+
// src/core/optimization/plainGroupByPlan.ts
|
|
5642
|
+
var AGGREGATE_REFERENCE_PREFIX = /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/;
|
|
5643
|
+
function containsAggregateColumnNode(node) {
|
|
5644
|
+
if (node === null || typeof node !== "object") return false;
|
|
5645
|
+
if (Array.isArray(node)) return node.some(containsAggregateColumnNode);
|
|
5646
|
+
const value = node;
|
|
5647
|
+
if (value["type"] === "AGGREGATE" || value["type"] === "ARITH_AGG_COL") return true;
|
|
5648
|
+
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return false;
|
|
5649
|
+
if (value["type"] === "FIELD" && typeof value["field"] === "string") {
|
|
5650
|
+
return AGGREGATE_REFERENCE_PREFIX.test(value["field"]);
|
|
5651
|
+
}
|
|
5652
|
+
return Object.values(value).some(containsAggregateColumnNode);
|
|
5653
|
+
}
|
|
5654
|
+
function classifyPreGroupAlias(column) {
|
|
5655
|
+
switch (column.type) {
|
|
5656
|
+
case "AGGREGATE":
|
|
5657
|
+
case "ARITH_AGG_COL":
|
|
5658
|
+
return "AGGREGATE_DEPENDENT";
|
|
5659
|
+
case "GROUPING_COL":
|
|
5660
|
+
case "WINDOW_COL":
|
|
5661
|
+
return "POST_GROUP_ONLY";
|
|
5662
|
+
case "VARIABLE_COL":
|
|
5663
|
+
throw new Error("InternalError: unresolved VARIABLE_COL reached GROUP BY alias planning.");
|
|
5664
|
+
case "WILDCARD":
|
|
5665
|
+
case "PARENT_WILDCARD":
|
|
5666
|
+
case "FIELD":
|
|
5667
|
+
case "LITERAL_COL":
|
|
5668
|
+
case "ARITH_COL":
|
|
5669
|
+
case "CASE_COL":
|
|
5670
|
+
case "STRFUNC_COL":
|
|
5671
|
+
case "SCALAR_VALUE_COL":
|
|
5672
|
+
case "SCALAR_SUBQUERY_COL":
|
|
5673
|
+
return containsAggregate2(column) || containsAggregateColumnNode(column) ? "AGGREGATE_DEPENDENT" : "SAFE";
|
|
5674
|
+
}
|
|
5675
|
+
}
|
|
5676
|
+
var SUBTABLE_SYSTEM_COLUMNS = ["_pid", "_rid", "_idx"];
|
|
5677
|
+
function unique(values) {
|
|
5678
|
+
return [...new Set(values)];
|
|
5679
|
+
}
|
|
5680
|
+
function sourceColumns(input) {
|
|
5681
|
+
switch (input.kind) {
|
|
5682
|
+
case "APP":
|
|
5683
|
+
return unique([
|
|
5684
|
+
...input.fieldCodes,
|
|
5685
|
+
...APP_SYSTEM_FIELD_CODES
|
|
5686
|
+
]);
|
|
5687
|
+
case "SUBTABLE":
|
|
5688
|
+
return unique([
|
|
5689
|
+
...input.childFieldCodes,
|
|
5690
|
+
...SUBTABLE_SYSTEM_COLUMNS,
|
|
5691
|
+
...input.parentFieldCodes.map((field) => `_p.${field}`)
|
|
5692
|
+
]);
|
|
5693
|
+
case "MATERIALIZED":
|
|
5694
|
+
return unique(input.columns);
|
|
5695
|
+
}
|
|
5696
|
+
}
|
|
5697
|
+
function resolvePlainGroupBySourceSchemas(stmt, lookup) {
|
|
5698
|
+
const sources = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
5699
|
+
return sources.map((source, sourceIndex) => ({
|
|
5700
|
+
sourceIndex,
|
|
5701
|
+
qualifier: source.alias ?? source.cteName,
|
|
5702
|
+
columns: sourceColumns(lookup(source, sourceIndex))
|
|
5703
|
+
}));
|
|
5704
|
+
}
|
|
5705
|
+
function parseGroupName(name) {
|
|
5706
|
+
if (name.startsWith("_p.")) return { qualifier: null, fieldCode: name };
|
|
5707
|
+
const dot = name.indexOf(".");
|
|
5708
|
+
if (dot <= 0 || dot === name.length - 1) {
|
|
5709
|
+
return { qualifier: null, fieldCode: name };
|
|
5710
|
+
}
|
|
5711
|
+
return { qualifier: name.slice(0, dot), fieldCode: name.slice(dot + 1) };
|
|
5712
|
+
}
|
|
5713
|
+
function runtimeKey(source, fieldCode) {
|
|
5714
|
+
return source.qualifier === null ? fieldCode : `${source.qualifier}.${fieldCode}`;
|
|
5715
|
+
}
|
|
5716
|
+
function resolvePlainFieldReference(ref, schemas) {
|
|
5717
|
+
const name = ref.tableAlias === null ? ref.field : `${ref.tableAlias}.${ref.field}`;
|
|
5718
|
+
const parsed = ref.tableAlias === null ? parseGroupName(ref.field) : { qualifier: ref.tableAlias, fieldCode: ref.field };
|
|
5719
|
+
const candidateSources = parsed.qualifier === null ? schemas : schemas.filter((source2) => source2.qualifier === parsed.qualifier);
|
|
5720
|
+
const physical = candidateSources.filter((source2) => source2.columns.includes(parsed.fieldCode));
|
|
5721
|
+
if (physical.length > 1) return { kind: "AMBIGUOUS", name };
|
|
5722
|
+
if (physical.length === 0) return { kind: "UNKNOWN", name };
|
|
5723
|
+
const source = physical[0];
|
|
5724
|
+
return {
|
|
5725
|
+
kind: "PHYSICAL",
|
|
5726
|
+
sourceIndex: source.sourceIndex,
|
|
5727
|
+
fieldCode: parsed.fieldCode,
|
|
5728
|
+
runtimeKey: runtimeKey(source, parsed.fieldCode)
|
|
5729
|
+
};
|
|
5730
|
+
}
|
|
5731
|
+
function explicitAlias(column) {
|
|
5732
|
+
return "alias" in column && typeof column.alias === "string" ? column.alias : null;
|
|
5733
|
+
}
|
|
5734
|
+
function resolveFieldName(name, columns, schemas) {
|
|
5735
|
+
const parsed = parseGroupName(name);
|
|
5736
|
+
const candidateSources = parsed.qualifier === null ? schemas : schemas.filter((source) => source.qualifier === parsed.qualifier);
|
|
5737
|
+
const physical = candidateSources.filter((source) => source.columns.includes(parsed.fieldCode));
|
|
5738
|
+
if (physical.length > 1) {
|
|
5739
|
+
throw new Error(
|
|
5740
|
+
`ArgumentError: GROUP BY field ${name} is ambiguous across multiple sources (reason=GROUP_BY_FIELD_AMBIGUOUS).`
|
|
5741
|
+
);
|
|
5742
|
+
}
|
|
5743
|
+
if (physical.length === 1) {
|
|
5744
|
+
const source = physical[0];
|
|
5745
|
+
return {
|
|
5746
|
+
kind: "PHYSICAL",
|
|
5747
|
+
sourceIndex: source.sourceIndex,
|
|
5748
|
+
fieldCode: parsed.fieldCode,
|
|
5749
|
+
runtimeKey: runtimeKey(source, parsed.fieldCode)
|
|
5750
|
+
};
|
|
5751
|
+
}
|
|
5752
|
+
if (parsed.qualifier !== null) return { kind: "UNKNOWN", name };
|
|
5753
|
+
const aliases = columns.flatMap(
|
|
5754
|
+
(column, columnIndex) => explicitAlias(column) === name ? [{ column, columnIndex }] : []
|
|
5755
|
+
);
|
|
5756
|
+
if (aliases.length > 1) return { kind: "ALIAS_REJECT", reason: "DUPLICATE" };
|
|
5757
|
+
if (aliases.length === 1) {
|
|
5758
|
+
const candidate = aliases[0];
|
|
5759
|
+
const classification = classifyPreGroupAlias(candidate.column);
|
|
5760
|
+
if (classification === "SAFE") {
|
|
5761
|
+
return { kind: "ALIAS_SAFE", columnIndex: candidate.columnIndex };
|
|
5762
|
+
}
|
|
5763
|
+
return {
|
|
5764
|
+
kind: "ALIAS_REJECT",
|
|
5765
|
+
reason: classification === "AGGREGATE_DEPENDENT" ? "AGGREGATE" : "POST_GROUP_ONLY"
|
|
5766
|
+
};
|
|
5767
|
+
}
|
|
5768
|
+
const aggregateSyntheticMatch = columns.some(
|
|
5769
|
+
(column) => column.type === "AGGREGATE" && column.alias === null && aggregateSyntheticName(column.func, column.distinct, column.arg) === name
|
|
5770
|
+
);
|
|
5771
|
+
if (aggregateSyntheticMatch) return { kind: "ALIAS_REJECT", reason: "AGGREGATE" };
|
|
5772
|
+
return { kind: "UNKNOWN", name };
|
|
5773
|
+
}
|
|
5774
|
+
function planPlainGroupByResolution(groupBy, columns, schemas) {
|
|
5775
|
+
return {
|
|
5776
|
+
items: groupBy.map(
|
|
5777
|
+
(key) => key.type === "FIELD_NAME" ? resolveFieldName(key.name, columns, schemas) : { kind: "EXPRESSION" }
|
|
5778
|
+
)
|
|
5779
|
+
};
|
|
5780
|
+
}
|
|
5781
|
+
|
|
5782
|
+
// src/core/aggregateDependencyValidation.ts
|
|
5783
|
+
var NON_GROUPED_DEPENDENCY_REASON = "B65_NON_GROUPED_DEPENDENCY";
|
|
5784
|
+
var WRAPPER_EXPR = /* @__PURE__ */ new Map([
|
|
5785
|
+
["ARITH_COL", "expr"],
|
|
5786
|
+
["ARITH_AGG_COL", "expr"],
|
|
5787
|
+
["STRFUNC_COL", "expr"],
|
|
5788
|
+
["SCALAR_VALUE_COL", "expr"],
|
|
5789
|
+
["CASE_COL", "expr"],
|
|
5790
|
+
["ARITH_KEY", "expr"],
|
|
5791
|
+
["FUNC_KEY", "expr"],
|
|
5792
|
+
["FUNC_FIELD", "expr"],
|
|
5793
|
+
["ARITH_FIELD", "expr"],
|
|
5794
|
+
["CASE_FIELD", "expr"],
|
|
5795
|
+
["ARITH_VALUE", "expr"],
|
|
5796
|
+
["CASE_VALUE", "expr"],
|
|
5797
|
+
["AGG_FIELD", "expr"]
|
|
5798
|
+
]);
|
|
5799
|
+
function refFromName(name) {
|
|
5800
|
+
if (name.startsWith("_p.")) return { type: "FIELD", tableAlias: null, field: name };
|
|
5801
|
+
const dot = name.indexOf(".");
|
|
5802
|
+
return dot > 0 ? { type: "FIELD", tableAlias: name.slice(0, dot), field: name.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field: name };
|
|
5803
|
+
}
|
|
5804
|
+
function fieldRefFromNode(value) {
|
|
5805
|
+
const type = value["type"];
|
|
5806
|
+
if (type === "FIELD_REF" && typeof value["field"] === "string") {
|
|
5807
|
+
return refFromName(value["field"]);
|
|
5808
|
+
}
|
|
5809
|
+
if (type === "AGG_GROUP_KEY" && typeof value["field"] === "string") {
|
|
5810
|
+
return {
|
|
5811
|
+
type: "FIELD",
|
|
5812
|
+
tableAlias: typeof value["tableAlias"] === "string" ? value["tableAlias"] : null,
|
|
5813
|
+
field: value["field"]
|
|
5814
|
+
};
|
|
5815
|
+
}
|
|
5816
|
+
if (type === "FIELD" && typeof value["field"] === "string") {
|
|
5817
|
+
if (value["aggregateRef"] !== void 0) return null;
|
|
5818
|
+
const tableAlias = typeof value["tableAlias"] === "string" ? value["tableAlias"] : null;
|
|
5819
|
+
return tableAlias === null ? refFromName(value["field"]) : {
|
|
5820
|
+
type: "FIELD",
|
|
5821
|
+
tableAlias,
|
|
5822
|
+
field: value["field"]
|
|
5823
|
+
};
|
|
5824
|
+
}
|
|
5825
|
+
return null;
|
|
5826
|
+
}
|
|
5827
|
+
function isQueryBoundary(value) {
|
|
5828
|
+
return value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY" || value["type"] === "SCALAR_SUBQUERY_COL" || value["type"] === "SUBQUERY_IN_LIST" || value["type"] === "EXISTS";
|
|
5829
|
+
}
|
|
5830
|
+
function isAggregateBoundary(value) {
|
|
5831
|
+
return value["type"] === "AGGREGATE" || value["type"] === "AGG_REF";
|
|
5832
|
+
}
|
|
5833
|
+
function isWindowBoundary(value) {
|
|
5834
|
+
return value["type"] === "WINDOW_COL";
|
|
5835
|
+
}
|
|
5836
|
+
function numberMeaning(value) {
|
|
5837
|
+
const number = value["value"];
|
|
5838
|
+
if (typeof number !== "number") return "?";
|
|
5839
|
+
if (Object.is(number, -0)) return "0";
|
|
5840
|
+
return String(number);
|
|
5841
|
+
}
|
|
5842
|
+
function canonicalExpression(node, resolveField2) {
|
|
5843
|
+
if (node === null) return "null";
|
|
5844
|
+
if (typeof node === "string" || typeof node === "boolean") return JSON.stringify(node);
|
|
5845
|
+
if (typeof node === "number") return String(node);
|
|
5846
|
+
if (Array.isArray(node)) {
|
|
5847
|
+
const items = node.map((item) => canonicalExpression(item, resolveField2));
|
|
5848
|
+
return items.some((item) => item === null) ? null : `[${items.join(",")}]`;
|
|
5849
|
+
}
|
|
5850
|
+
if (typeof node !== "object") return null;
|
|
5851
|
+
const value = node;
|
|
5852
|
+
const type = value["type"];
|
|
5853
|
+
if (type === "VARIABLE" || type === "VARIABLE_COL" || isQueryBoundary(value)) return null;
|
|
5854
|
+
if (type === "GROUP" && value["expr"] !== void 0) {
|
|
5855
|
+
return canonicalExpression(value["expr"], resolveField2);
|
|
5856
|
+
}
|
|
5857
|
+
const wrapper = typeof type === "string" ? WRAPPER_EXPR.get(type) : void 0;
|
|
5858
|
+
if (wrapper !== void 0) return canonicalExpression(value[wrapper], resolveField2);
|
|
5859
|
+
if (type === "LITERAL_COL") return `STRING:${JSON.stringify(value["value"] ?? "")}`;
|
|
5860
|
+
if (type === "STRING") return `STRING:${JSON.stringify(value["value"] ?? "")}`;
|
|
5861
|
+
if (type === "NUMBER") return `NUMBER:${numberMeaning(value)}`;
|
|
5862
|
+
if (type === "BOOLEAN") return `BOOLEAN:${String(value["value"])}`;
|
|
5863
|
+
const ref = fieldRefFromNode(value);
|
|
5864
|
+
if (ref !== null) {
|
|
5865
|
+
try {
|
|
5866
|
+
return `FIELD:${resolveField2(ref)}`;
|
|
5867
|
+
} catch {
|
|
5868
|
+
return null;
|
|
5869
|
+
}
|
|
5870
|
+
}
|
|
5871
|
+
if (type === "FIELD" && value["aggregateRef"] !== void 0) return null;
|
|
5872
|
+
const ignored = /* @__PURE__ */ new Set([
|
|
5873
|
+
"alias",
|
|
5874
|
+
"aliasDisplay",
|
|
5875
|
+
"raw",
|
|
5876
|
+
"separator",
|
|
5877
|
+
"distinct",
|
|
5878
|
+
"source"
|
|
5879
|
+
]);
|
|
5880
|
+
const parts = [];
|
|
5881
|
+
for (const key of Object.keys(value)) {
|
|
5882
|
+
if (key === "type" || ignored.has(key)) continue;
|
|
5883
|
+
const child = canonicalExpression(value[key], resolveField2);
|
|
5884
|
+
if (child === null) return null;
|
|
5885
|
+
parts.push(`${key}=${child}`);
|
|
5886
|
+
}
|
|
5887
|
+
const semanticType = type === "ARITH" || type === "SCALAR_ARITH" ? "ARITH" : String(type ?? "OBJECT");
|
|
5888
|
+
return `${semanticType}(${parts.join(",")})`;
|
|
5889
|
+
}
|
|
5890
|
+
function explicitAlias2(column) {
|
|
5891
|
+
return "alias" in column && typeof column.alias === "string" ? column.alias : null;
|
|
5892
|
+
}
|
|
5893
|
+
function aliasesByName(columns) {
|
|
5894
|
+
const result = /* @__PURE__ */ new Map();
|
|
5895
|
+
for (const column of columns) {
|
|
5896
|
+
const alias = explicitAlias2(column);
|
|
5897
|
+
if (alias === null) continue;
|
|
5898
|
+
result.set(alias, [...result.get(alias) ?? [], column]);
|
|
5899
|
+
}
|
|
5900
|
+
return result;
|
|
5901
|
+
}
|
|
5902
|
+
function displayField(ref) {
|
|
5903
|
+
return ref.tableAlias === null ? ref.field : `${ref.tableAlias}.${ref.field}`;
|
|
5904
|
+
}
|
|
5905
|
+
var AGGREGATE_SYNTHETIC_REFERENCE = /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/;
|
|
5906
|
+
function displayExpression(node) {
|
|
5907
|
+
if (node && typeof node === "object") {
|
|
5908
|
+
const value = node;
|
|
5909
|
+
const ref = fieldRefFromNode(value);
|
|
5910
|
+
if (ref !== null) return displayField(ref);
|
|
5911
|
+
if (value["type"] === "FIELD_NAME" && typeof value["name"] === "string") return value["name"];
|
|
5912
|
+
if (value["type"] === "WILDCARD") return "*";
|
|
5913
|
+
if (value["type"] === "PARENT_WILDCARD") return "_p.*";
|
|
5914
|
+
const alias = value["alias"];
|
|
5915
|
+
if (typeof alias === "string" && alias.length > 0) return alias;
|
|
5916
|
+
const wrapper = typeof value["type"] === "string" ? WRAPPER_EXPR.get(value["type"]) : void 0;
|
|
5917
|
+
if (wrapper !== void 0) {
|
|
5918
|
+
const inner = displayExpression(value[wrapper]);
|
|
5919
|
+
if (inner !== "\u5F0F") return inner;
|
|
5920
|
+
}
|
|
5921
|
+
const func = value["func"];
|
|
5922
|
+
if (typeof func === "string" && func.length > 0) return `${func}(...)`;
|
|
5923
|
+
}
|
|
5924
|
+
return "\u5F0F";
|
|
5925
|
+
}
|
|
5926
|
+
function dependencyError(clause, expression, dependency, policy) {
|
|
5927
|
+
const dependencyLabel = dependency === "WILDCARD" ? "wildcard" : displayField(dependency);
|
|
5928
|
+
const expressionLabel = dependency === "WILDCARD" ? displayExpression(expression) : displayExpression(expression);
|
|
5929
|
+
const groupText = policy.groupingLabel === null ? "GROUP BY \u304C\u306A\u3044\u305F\u3081\u5165\u529B\u5168\u4F53\u304C1\u30B0\u30EB\u30FC\u30D7\u306B\u306A\u308A" : `${policy.groupingLabel} \u306E\u5404\u30B0\u30EB\u30FC\u30D7\u3067\u306F`;
|
|
5930
|
+
const migration = dependency === "WILDCARD" ? "\u5FC5\u8981\u306A grouping \u5217\u3092\u660E\u793A\u3057\u3066 SELECT \u3057\u3066\u304F\u3060\u3055\u3044\u3002" : `\u300C${dependencyLabel}\u300D\u3092 MIN() \u306A\u3069\u306E\u96C6\u8A08\u95A2\u6570\u3067\u5305\u3080\u304B\u3001GROUP BY \u3078\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044\u3002`;
|
|
5931
|
+
const concreteMigration = dependency !== "WILDCARD" && dependency.tableAlias === null && expressionLabel === dependencyLabel && policy.migrationSourceSql !== void 0 ? policy.migrationGroupingFields && policy.migrationGroupingFields.length > 0 ? ` \u5B9F\u884C\u53EF\u80FD\u306A\u66F8\u304D\u63DB\u3048\u4F8B: \u300CSELECT ${policy.migrationGroupingFields.join(", ")}, MIN(${dependencyLabel}) FROM ${policy.migrationSourceSql} GROUP BY ${policy.migrationGroupingFields.join(", ")}\u300D\u3002` : ` \u5B9F\u884C\u53EF\u80FD\u306A\u66F8\u304D\u63DB\u3048\u4F8B: \u300CSELECT MIN(${dependencyLabel}) FROM ${policy.migrationSourceSql}\u300D\u3002` : "";
|
|
5932
|
+
return new Error(
|
|
5933
|
+
`ArgumentError: ${clause} \u5F0F\u300C${expressionLabel}\u300D\u306F\u96C6\u8A08\u3082\u30B0\u30EB\u30FC\u30D7\u5316\u3082\u3055\u308C\u3066\u3044\u307E\u305B\u3093\uFF08${policy.sourceLabel}\u3001\u975E\u30B0\u30EB\u30FC\u30D7\u5316\u4F9D\u5B58: ${dependencyLabel}\uFF09\u3002${groupText}\u3001\u3069\u306E\u884C\u306E\u5024\u3092\u8FD4\u3059\u304B\u6C7A\u307E\u308A\u307E\u305B\u3093\u3002${migration}${concreteMigration} (reason=${NON_GROUPED_DEPENDENCY_REASON})`
|
|
5934
|
+
);
|
|
5935
|
+
}
|
|
5936
|
+
function walkDependency(node, context) {
|
|
5937
|
+
if (node === null || typeof node !== "object") return;
|
|
5938
|
+
if (Array.isArray(node)) {
|
|
5939
|
+
for (const child of node) walkDependency(child, context);
|
|
5940
|
+
return;
|
|
5941
|
+
}
|
|
5942
|
+
const value = node;
|
|
5943
|
+
if (isQueryBoundary(value) || isAggregateBoundary(value) || isWindowBoundary(value)) return;
|
|
5944
|
+
if (value["type"] === "GROUPING_REF" || value["type"] === "GROUPING_FIELD" || value["type"] === "GROUPING_COL" || value["type"] === "GROUPING_KEY") return;
|
|
5945
|
+
if (value["type"] === "WILDCARD" || value["type"] === "PARENT_WILDCARD") {
|
|
5946
|
+
throw dependencyError(context.clause, context.expression, "WILDCARD", context.policy);
|
|
5947
|
+
}
|
|
5948
|
+
const ref = fieldRefFromNode(value);
|
|
5949
|
+
if (ref !== null) {
|
|
5950
|
+
if (context.clause !== "SELECT" && ref.tableAlias === null && AGGREGATE_SYNTHETIC_REFERENCE.test(ref.field)) return;
|
|
5951
|
+
if (context.clause !== "SELECT" && ref.tableAlias === null) {
|
|
5952
|
+
const targets = context.aliases.get(ref.field) ?? [];
|
|
5953
|
+
if (targets.length === 1 && !context.resolvingAliases.has(ref.field)) {
|
|
5954
|
+
const resolvingAliases = new Set(context.resolvingAliases);
|
|
5955
|
+
resolvingAliases.add(ref.field);
|
|
5956
|
+
walkDependency(targets[0], { ...context, resolvingAliases });
|
|
5957
|
+
return;
|
|
5958
|
+
}
|
|
5959
|
+
}
|
|
5960
|
+
const canonical2 = canonicalExpression(value, context.policy.resolveField);
|
|
5961
|
+
if (canonical2 !== null && context.policy.identities.has(canonical2)) return;
|
|
5962
|
+
const identity = `FIELD:${context.policy.resolveField(ref)}`;
|
|
5963
|
+
if (!context.policy.identities.has(identity)) {
|
|
5964
|
+
throw dependencyError(context.clause, context.expression, ref, context.policy);
|
|
5965
|
+
}
|
|
5966
|
+
return;
|
|
5967
|
+
}
|
|
5968
|
+
const canonical = canonicalExpression(value, context.policy.resolveField);
|
|
5969
|
+
if (canonical !== null && context.policy.identities.has(canonical)) return;
|
|
5970
|
+
const wrapper = typeof value["type"] === "string" ? WRAPPER_EXPR.get(value["type"]) : void 0;
|
|
5971
|
+
if (wrapper !== void 0) {
|
|
5972
|
+
walkDependency(value[wrapper], context);
|
|
5973
|
+
return;
|
|
5974
|
+
}
|
|
5975
|
+
for (const key of Object.keys(value)) {
|
|
5976
|
+
if (key === "type" || key === "alias" || key === "aliasDisplay" || key === "raw") continue;
|
|
5977
|
+
walkDependency(value[key], context);
|
|
5978
|
+
}
|
|
5979
|
+
}
|
|
5980
|
+
function validateAggregateDependencies(stmt, policy) {
|
|
5981
|
+
const aliases = aliasesByName(stmt.columns);
|
|
5982
|
+
for (const column of stmt.columns) {
|
|
5983
|
+
if (column.type === "WINDOW_COL") continue;
|
|
5984
|
+
walkDependency(column, {
|
|
5985
|
+
clause: "SELECT",
|
|
5986
|
+
expression: column,
|
|
5987
|
+
policy,
|
|
5988
|
+
aliases,
|
|
5989
|
+
resolvingAliases: /* @__PURE__ */ new Set()
|
|
5990
|
+
});
|
|
5991
|
+
}
|
|
5992
|
+
if (stmt.having !== null) {
|
|
5993
|
+
walkDependency(stmt.having, {
|
|
5994
|
+
clause: "HAVING",
|
|
5995
|
+
expression: stmt.having,
|
|
5996
|
+
policy,
|
|
5997
|
+
aliases,
|
|
5998
|
+
resolvingAliases: /* @__PURE__ */ new Set()
|
|
5999
|
+
});
|
|
6000
|
+
}
|
|
6001
|
+
for (const order of stmt.orderBy) {
|
|
6002
|
+
const key = order.key.type === "FIELD_NAME" ? refFromName(order.key.name) : order.key;
|
|
6003
|
+
walkDependency(key, {
|
|
6004
|
+
clause: "ORDER BY",
|
|
6005
|
+
expression: key,
|
|
6006
|
+
policy,
|
|
6007
|
+
aliases,
|
|
6008
|
+
resolvingAliases: /* @__PURE__ */ new Set()
|
|
6009
|
+
});
|
|
6010
|
+
}
|
|
6011
|
+
}
|
|
6012
|
+
function hasAggregateNode(node) {
|
|
6013
|
+
if (node === null || typeof node !== "object") return false;
|
|
6014
|
+
if (Array.isArray(node)) return node.some(hasAggregateNode);
|
|
6015
|
+
const value = node;
|
|
6016
|
+
if (isQueryBoundary(value) || isWindowBoundary(value)) return false;
|
|
6017
|
+
if (isAggregateBoundary(value) || value["type"] === "ARITH_AGG_COL") return true;
|
|
6018
|
+
return Object.values(value).some(hasAggregateNode);
|
|
6019
|
+
}
|
|
6020
|
+
function isAggregateQueryBlock(stmt) {
|
|
6021
|
+
return normalizeGroupingSpec(stmt).type !== "NONE" || stmt.columns.some((column) => column.type !== "WINDOW_COL" && hasAggregateNode(column));
|
|
6022
|
+
}
|
|
6023
|
+
function groupByKeyNode(key) {
|
|
6024
|
+
if (key.type === "FIELD_NAME") return refFromName(key.name);
|
|
6025
|
+
return key.expr;
|
|
6026
|
+
}
|
|
6027
|
+
function buildOrdinaryDependencyPolicy(stmt, plan, schemas) {
|
|
6028
|
+
const normalized = normalizeGroupingSpec(stmt);
|
|
6029
|
+
if (normalized.type !== "PLAIN") {
|
|
6030
|
+
throw new Error("InternalError: ordinary dependency policy requires plain GROUP BY.");
|
|
6031
|
+
}
|
|
6032
|
+
const groupBy = normalized.allItems;
|
|
6033
|
+
const resolveField2 = (ref) => {
|
|
6034
|
+
const resolution = resolvePlainFieldReference(ref, schemas);
|
|
6035
|
+
if (resolution.kind === "AMBIGUOUS") {
|
|
6036
|
+
throw new Error(`ArgumentError: field ${resolution.name} is ambiguous across multiple sources.`);
|
|
6037
|
+
}
|
|
6038
|
+
if (resolution.kind === "UNKNOWN") return `unknown:${resolution.name}`;
|
|
6039
|
+
return `source:${resolution.sourceIndex}:${resolution.fieldCode}`;
|
|
6040
|
+
};
|
|
6041
|
+
const identities = /* @__PURE__ */ new Set();
|
|
6042
|
+
plan.items.forEach((item, index) => {
|
|
6043
|
+
if (item.kind === "PHYSICAL") {
|
|
6044
|
+
identities.add(`FIELD:source:${item.sourceIndex}:${item.fieldCode}`);
|
|
6045
|
+
return;
|
|
6046
|
+
}
|
|
6047
|
+
if (item.kind === "ALIAS_SAFE") {
|
|
6048
|
+
const key = canonicalExpression(stmt.columns[item.columnIndex], resolveField2);
|
|
6049
|
+
if (key !== null) identities.add(key);
|
|
6050
|
+
return;
|
|
6051
|
+
}
|
|
6052
|
+
if (item.kind === "EXPRESSION") {
|
|
6053
|
+
const key = canonicalExpression(groupByKeyNode(groupBy[index]), resolveField2);
|
|
6054
|
+
if (key !== null) identities.add(key);
|
|
6055
|
+
}
|
|
6056
|
+
});
|
|
6057
|
+
const sources = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
6058
|
+
const sourceSql = (source) => `APP${source.appId}${source.subtableCode != null ? `$${source.subtableCode}` : ""}`;
|
|
6059
|
+
const sourceLabel = sources.map((source) => source.cteName ?? sourceSql(source)).join(" / ");
|
|
6060
|
+
const groupingLabel = `GROUP BY ${groupBy.map(
|
|
6061
|
+
(key) => key.type === "FIELD_NAME" ? key.name : displayExpression(key)
|
|
6062
|
+
).join(", ")}`;
|
|
6063
|
+
const directAppSource = sources.length === 1 && sources[0].cteName === null ? `${sourceSql(sources[0])}${sources[0].alias && sources[0].alias !== sourceSql(sources[0]) ? ` ${sources[0].alias}` : ""}` : void 0;
|
|
6064
|
+
const migrationGroupingFields = groupBy.every(
|
|
6065
|
+
(key, index) => key.type === "FIELD_NAME" && plan.items[index]?.kind === "PHYSICAL"
|
|
6066
|
+
) ? groupBy.map((key) => key.name) : void 0;
|
|
6067
|
+
return {
|
|
6068
|
+
identities,
|
|
6069
|
+
resolveField: resolveField2,
|
|
6070
|
+
sourceLabel,
|
|
6071
|
+
groupingLabel,
|
|
6072
|
+
migrationSourceSql: directAppSource,
|
|
6073
|
+
migrationGroupingFields
|
|
6074
|
+
};
|
|
6075
|
+
}
|
|
6076
|
+
function validateAggregateDependenciesStatic(stmt) {
|
|
6077
|
+
if (normalizeGroupingSpec(stmt).type !== "NONE" || !isAggregateQueryBlock(stmt)) return;
|
|
6078
|
+
const policy = {
|
|
6079
|
+
identities: /* @__PURE__ */ new Set(),
|
|
6080
|
+
resolveField: (ref) => `ast:${displayField(ref)}`,
|
|
6081
|
+
sourceLabel: stmt.from.cteName ?? `APP${stmt.from.appId}`,
|
|
6082
|
+
groupingLabel: null,
|
|
6083
|
+
migrationSourceSql: stmt.from.cteName === null && stmt.joins.length === 0 ? `APP${stmt.from.appId}${stmt.from.alias && stmt.from.alias !== `APP${stmt.from.appId}` ? ` ${stmt.from.alias}` : ""}` : void 0
|
|
6084
|
+
};
|
|
6085
|
+
validateAggregateDependencies(stmt, policy);
|
|
6086
|
+
}
|
|
6087
|
+
function canonicalGroupingFieldIdentity(canonicalId) {
|
|
6088
|
+
return `FIELD:${canonicalId}`;
|
|
6089
|
+
}
|
|
6090
|
+
|
|
5625
6091
|
// src/core/groupingValidation.ts
|
|
5626
6092
|
var enforceGroupingPlanningCandidateLimits = (facts) => {
|
|
5627
6093
|
if (facts.expandedSetCount > B65_MAX_GROUPING_SETS) {
|
|
5628
6094
|
throw new Error(
|
|
5629
|
-
`ArgumentError:
|
|
6095
|
+
`ArgumentError: expanded grouping set count ${facts.expandedSetCount} exceeds limit ${B65_MAX_GROUPING_SETS} (reason=GROUPING_SET_LIMIT_EXCEEDED).`
|
|
5630
6096
|
);
|
|
5631
6097
|
}
|
|
5632
6098
|
if (facts.canonicalItemCount > B65_MAX_GROUPING_ITEMS) {
|
|
5633
6099
|
throw new Error(
|
|
5634
|
-
`ArgumentError:
|
|
6100
|
+
`ArgumentError: canonical grouping item count ${facts.canonicalItemCount} exceeds limit ${B65_MAX_GROUPING_ITEMS} (reason=GROUPING_ITEM_LIMIT_EXCEEDED).`
|
|
5635
6101
|
);
|
|
5636
6102
|
}
|
|
5637
6103
|
};
|
|
5638
|
-
function
|
|
6104
|
+
function displayField2(field) {
|
|
5639
6105
|
return field.tableAlias ? `${field.tableAlias}.${field.field}` : field.field;
|
|
5640
6106
|
}
|
|
5641
|
-
function refFromName(name) {
|
|
5642
|
-
const dot = name.indexOf(".");
|
|
5643
|
-
return dot > 0 ? { type: "FIELD", tableAlias: name.slice(0, dot), field: name.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field: name };
|
|
5644
|
-
}
|
|
5645
6107
|
function collectGroupingRefs(node, out) {
|
|
5646
6108
|
if (node === null || typeof node !== "object") return;
|
|
5647
6109
|
if (Array.isArray(node)) {
|
|
@@ -5670,30 +6132,6 @@ function collectAggregateArgumentGroupingRefs(node, out) {
|
|
|
5670
6132
|
}
|
|
5671
6133
|
Object.values(value).forEach((item) => collectAggregateArgumentGroupingRefs(item, out));
|
|
5672
6134
|
}
|
|
5673
|
-
function collectNonAggregateFieldRefs(node, out) {
|
|
5674
|
-
if (node === null || typeof node !== "object") return;
|
|
5675
|
-
if (Array.isArray(node)) {
|
|
5676
|
-
node.forEach((item) => collectNonAggregateFieldRefs(item, out));
|
|
5677
|
-
return;
|
|
5678
|
-
}
|
|
5679
|
-
const value = node;
|
|
5680
|
-
const type = value["type"];
|
|
5681
|
-
if (type === "SELECT" || type === "SCALAR_SUBQUERY" || type === "GROUPING_REF" || type === "AGG_REF" || type === "AGG_ARITH") return;
|
|
5682
|
-
if (type === "FIELD" && value["aggregateRef"] !== void 0) return;
|
|
5683
|
-
if (type === "FIELD" && typeof value["field"] === "string") {
|
|
5684
|
-
out.push({
|
|
5685
|
-
type: "FIELD",
|
|
5686
|
-
tableAlias: typeof value["tableAlias"] === "string" ? value["tableAlias"] : null,
|
|
5687
|
-
field: value["field"]
|
|
5688
|
-
});
|
|
5689
|
-
return;
|
|
5690
|
-
}
|
|
5691
|
-
if (type === "FIELD_REF" && typeof value["field"] === "string") {
|
|
5692
|
-
out.push(refFromName(value["field"]));
|
|
5693
|
-
return;
|
|
5694
|
-
}
|
|
5695
|
-
Object.values(value).forEach((item) => collectNonAggregateFieldRefs(item, out));
|
|
5696
|
-
}
|
|
5697
6135
|
function containsAggregate2(node) {
|
|
5698
6136
|
if (node === null || typeof node !== "object") return false;
|
|
5699
6137
|
if (Array.isArray(node)) return node.some(containsAggregate2);
|
|
@@ -5710,41 +6148,18 @@ function isAggregateMaterializedAlias(column) {
|
|
|
5710
6148
|
}
|
|
5711
6149
|
return false;
|
|
5712
6150
|
}
|
|
5713
|
-
function outputAliases(columns) {
|
|
5714
|
-
return new Set(columns.flatMap(
|
|
5715
|
-
(column) => "alias" in column && typeof column.alias === "string" ? [column.alias] : []
|
|
5716
|
-
));
|
|
5717
|
-
}
|
|
5718
|
-
function isAggregateSyntheticReference(ref) {
|
|
5719
|
-
return ref.tableAlias === null && /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/.test(ref.field);
|
|
5720
|
-
}
|
|
5721
6151
|
function validateGroupingRefMembership(ref, resolve2, canonicalItems) {
|
|
5722
6152
|
const resolved = resolve2(ref.field);
|
|
5723
6153
|
if (!resolved.physical) {
|
|
5724
|
-
throw new Error(`ArgumentError:
|
|
6154
|
+
throw new Error(`ArgumentError: grouping reference ${displayField2(ref.field)} must resolve to a physical APP field.`);
|
|
5725
6155
|
}
|
|
5726
6156
|
if (!canonicalItems.has(resolved.canonicalId)) {
|
|
5727
6157
|
throw new Error(
|
|
5728
|
-
`ArgumentError:
|
|
6158
|
+
`ArgumentError: GROUPING argument ${displayField2(ref.field)} is not present in grouping allItems (reason=B65_GROUPING_ARG_NOT_ITEM).`
|
|
5729
6159
|
);
|
|
5730
6160
|
}
|
|
5731
6161
|
bindGroupingRefCanonicalId(ref, resolved.canonicalId);
|
|
5732
6162
|
}
|
|
5733
|
-
function validateDependency(ref, resolve2, canonicalItems, context) {
|
|
5734
|
-
const resolved = resolve2(ref);
|
|
5735
|
-
if (!resolved.physical || !canonicalItems.has(resolved.canonicalId)) {
|
|
5736
|
-
throw new Error(
|
|
5737
|
-
`ArgumentError: B65 non-aggregate field ${displayField(ref)} in ${context} is not a grouping item (reason=B65_NON_GROUPED_DEPENDENCY).`
|
|
5738
|
-
);
|
|
5739
|
-
}
|
|
5740
|
-
}
|
|
5741
|
-
function keyDependencies(key) {
|
|
5742
|
-
if (key.type === "GROUPING_KEY") return [];
|
|
5743
|
-
if (key.type === "FIELD_NAME") return [refFromName(key.name)];
|
|
5744
|
-
const refs = [];
|
|
5745
|
-
collectNonAggregateFieldRefs(key, refs);
|
|
5746
|
-
return refs;
|
|
5747
|
-
}
|
|
5748
6163
|
function validateGroupingStatic(stmt) {
|
|
5749
6164
|
const normalized = normalizeGroupingSpec(stmt);
|
|
5750
6165
|
const groupingRefs = [];
|
|
@@ -5763,25 +6178,28 @@ function validateGroupingStatic(stmt) {
|
|
|
5763
6178
|
}
|
|
5764
6179
|
if (forbiddenGroupingRefs.length > 0) {
|
|
5765
6180
|
throw new Error(
|
|
5766
|
-
"ArgumentError:
|
|
6181
|
+
"ArgumentError: GROUPING() is not allowed in WHERE, JOIN, window, aggregate arguments, or DML expressions."
|
|
5767
6182
|
);
|
|
5768
6183
|
}
|
|
5769
6184
|
if (normalized.type !== "GROUPING_SETS") {
|
|
5770
6185
|
if (groupingRefs.length > 0) {
|
|
5771
|
-
throw new Error("ArgumentError:
|
|
6186
|
+
throw new Error("ArgumentError: GROUPING() requires GROUP BY ROLLUP or GROUPING SETS.");
|
|
5772
6187
|
}
|
|
6188
|
+
validateAggregateDependenciesStatic(stmt);
|
|
5773
6189
|
return;
|
|
5774
6190
|
}
|
|
5775
6191
|
if (stmt.orderMode === "KINTONE_NATIVE") {
|
|
5776
|
-
throw new Error("ArgumentError:
|
|
6192
|
+
throw new Error("ArgumentError: KORDER BY is not supported with extended grouping.");
|
|
5777
6193
|
}
|
|
5778
6194
|
if (stmt.columns.some((column) => column.type === "WINDOW_COL")) {
|
|
5779
|
-
throw new Error("ArgumentError:
|
|
6195
|
+
throw new Error("ArgumentError: window functions are not supported with extended grouping.");
|
|
5780
6196
|
}
|
|
5781
6197
|
if (stmt.columns.some(
|
|
5782
6198
|
(column) => column.type === "WILDCARD" || column.type === "PARENT_WILDCARD"
|
|
5783
6199
|
)) {
|
|
5784
|
-
throw new Error(
|
|
6200
|
+
throw new Error(
|
|
6201
|
+
"ArgumentError: SELECT wildcard \u306F\u96C6\u8A08 query \u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u5FC5\u8981\u306A grouping \u5217\u3092\u660E\u793A\u3057\u3066\u304F\u3060\u3055\u3044 (reason=B65_NON_GROUPED_DEPENDENCY)."
|
|
6202
|
+
);
|
|
5785
6203
|
}
|
|
5786
6204
|
}
|
|
5787
6205
|
function validateGroupingPlanning(stmt, resolve2, planningGuardHook = () => void 0) {
|
|
@@ -5802,7 +6220,7 @@ function validateGroupingPlanning(stmt, resolve2, planningGuardHook = () => void
|
|
|
5802
6220
|
for (const item of resolvedSpec.allItems) {
|
|
5803
6221
|
const resolved = item;
|
|
5804
6222
|
if (!resolved.physical) {
|
|
5805
|
-
throw new Error(`ArgumentError:
|
|
6223
|
+
throw new Error(`ArgumentError: grouping item ${displayField2(item.field)} must resolve to a physical APP field.`);
|
|
5806
6224
|
}
|
|
5807
6225
|
if (!canonicalItems.has(resolved.canonicalId)) {
|
|
5808
6226
|
canonicalItems.add(resolved.canonicalId);
|
|
@@ -5816,28 +6234,12 @@ function validateGroupingPlanning(stmt, resolve2, planningGuardHook = () => void
|
|
|
5816
6234
|
for (const ref of groupingRefs) {
|
|
5817
6235
|
validateGroupingRefMembership(ref, resolve2, canonicalItems);
|
|
5818
6236
|
}
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
for (const ref of refs) validateDependency(ref, resolve2, canonicalItems, "SELECT");
|
|
5826
|
-
}
|
|
5827
|
-
if (stmt.having) {
|
|
5828
|
-
const refs = [];
|
|
5829
|
-
collectNonAggregateFieldRefs(stmt.having, refs);
|
|
5830
|
-
for (const ref of refs) {
|
|
5831
|
-
if (ref.tableAlias === null && aliases.has(ref.field) || isAggregateSyntheticReference(ref)) continue;
|
|
5832
|
-
validateDependency(ref, resolve2, canonicalItems, "HAVING");
|
|
5833
|
-
}
|
|
5834
|
-
}
|
|
5835
|
-
for (const order of stmt.orderBy) {
|
|
5836
|
-
for (const ref of keyDependencies(order.key)) {
|
|
5837
|
-
if (ref.tableAlias === null && aliases.has(ref.field) || isAggregateSyntheticReference(ref)) continue;
|
|
5838
|
-
validateDependency(ref, resolve2, canonicalItems, "ORDER BY");
|
|
5839
|
-
}
|
|
5840
|
-
}
|
|
6237
|
+
validateAggregateDependencies(stmt, {
|
|
6238
|
+
identities: new Set([...canonicalItems].map(canonicalGroupingFieldIdentity)),
|
|
6239
|
+
resolveField: (ref) => resolve2(ref).canonicalId,
|
|
6240
|
+
sourceLabel: stmt.from.cteName ?? `APP${stmt.from.appId}`,
|
|
6241
|
+
groupingLabel: `GROUP BY ${normalized.source}`
|
|
6242
|
+
});
|
|
5841
6243
|
const collisionKeys = /* @__PURE__ */ new Set();
|
|
5842
6244
|
for (const item of resolvedItems) {
|
|
5843
6245
|
collisionKeys.add(item.directKey);
|
|
@@ -5849,7 +6251,7 @@ function validateGroupingPlanning(stmt, resolve2, planningGuardHook = () => void
|
|
|
5849
6251
|
if (alias === null) continue;
|
|
5850
6252
|
if (collisionKeys.has(alias)) {
|
|
5851
6253
|
throw new Error(
|
|
5852
|
-
`ArgumentError:
|
|
6254
|
+
`ArgumentError: aggregate alias ${alias} collides with a grouping runtime key (reason=B65_AGGREGATE_ALIAS_COLLISION).`
|
|
5853
6255
|
);
|
|
5854
6256
|
}
|
|
5855
6257
|
}
|
|
@@ -10378,11 +10780,11 @@ function validatePostImage(record, fieldIndex, numberPrecision, statementNumber,
|
|
|
10378
10780
|
else normalizedRecord[field.code] = { value: preserveCodeObjects(raw, field.fieldType, result.value) };
|
|
10379
10781
|
}
|
|
10380
10782
|
for (const [tableCode, children] of fieldIndex.subtables) {
|
|
10381
|
-
const
|
|
10382
|
-
if (!Array.isArray(
|
|
10783
|
+
const sourceRows2 = record[tableCode]?.value;
|
|
10784
|
+
if (!Array.isArray(sourceRows2)) continue;
|
|
10383
10785
|
const normalizedRows = normalizedRecord[tableCode]?.value;
|
|
10384
|
-
for (let rowIndex = 0; rowIndex <
|
|
10385
|
-
const sourceRow =
|
|
10786
|
+
for (let rowIndex = 0; rowIndex < sourceRows2.length; rowIndex++) {
|
|
10787
|
+
const sourceRow = sourceRows2[rowIndex];
|
|
10386
10788
|
const normalizedRow = normalizedRows[rowIndex];
|
|
10387
10789
|
for (const field of children) {
|
|
10388
10790
|
const raw = sourceRow.value?.[field.code]?.value;
|
|
@@ -13077,148 +13479,6 @@ function buildKorderCursorQuery(stmt) {
|
|
|
13077
13479
|
return parts.join(" ");
|
|
13078
13480
|
}
|
|
13079
13481
|
|
|
13080
|
-
// src/core/systemFields.ts
|
|
13081
|
-
var APP_SYSTEM_FIELD_CODES = [
|
|
13082
|
-
"$id",
|
|
13083
|
-
"$revision",
|
|
13084
|
-
"\u30EC\u30B3\u30FC\u30C9\u756A\u53F7",
|
|
13085
|
-
"\u4F5C\u6210\u8005",
|
|
13086
|
-
"\u4F5C\u6210\u65E5\u6642",
|
|
13087
|
-
"\u66F4\u65B0\u8005",
|
|
13088
|
-
"\u66F4\u65B0\u65E5\u6642",
|
|
13089
|
-
"\u30B9\u30C6\u30FC\u30BF\u30B9",
|
|
13090
|
-
"\u4F5C\u696D\u8005"
|
|
13091
|
-
];
|
|
13092
|
-
function isSystemLikeFieldCode(code) {
|
|
13093
|
-
return code.startsWith("_") || code.startsWith("$");
|
|
13094
|
-
}
|
|
13095
|
-
|
|
13096
|
-
// src/core/optimization/plainGroupByPlan.ts
|
|
13097
|
-
var AGGREGATE_REFERENCE_PREFIX = /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT|STDDEV_POP|STDDEV_SAMP|VAR_POP|VAR_SAMP|MEDIAN|MODE)\(/;
|
|
13098
|
-
function containsAggregateColumnNode(node) {
|
|
13099
|
-
if (node === null || typeof node !== "object") return false;
|
|
13100
|
-
if (Array.isArray(node)) return node.some(containsAggregateColumnNode);
|
|
13101
|
-
const value = node;
|
|
13102
|
-
if (value["type"] === "AGGREGATE" || value["type"] === "ARITH_AGG_COL") return true;
|
|
13103
|
-
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return false;
|
|
13104
|
-
if (value["type"] === "FIELD" && typeof value["field"] === "string") {
|
|
13105
|
-
return AGGREGATE_REFERENCE_PREFIX.test(value["field"]);
|
|
13106
|
-
}
|
|
13107
|
-
return Object.values(value).some(containsAggregateColumnNode);
|
|
13108
|
-
}
|
|
13109
|
-
function classifyPreGroupAlias(column) {
|
|
13110
|
-
switch (column.type) {
|
|
13111
|
-
case "AGGREGATE":
|
|
13112
|
-
case "ARITH_AGG_COL":
|
|
13113
|
-
return "AGGREGATE_DEPENDENT";
|
|
13114
|
-
case "GROUPING_COL":
|
|
13115
|
-
case "WINDOW_COL":
|
|
13116
|
-
return "POST_GROUP_ONLY";
|
|
13117
|
-
case "VARIABLE_COL":
|
|
13118
|
-
throw new Error("InternalError: unresolved VARIABLE_COL reached GROUP BY alias planning.");
|
|
13119
|
-
case "WILDCARD":
|
|
13120
|
-
case "PARENT_WILDCARD":
|
|
13121
|
-
case "FIELD":
|
|
13122
|
-
case "LITERAL_COL":
|
|
13123
|
-
case "ARITH_COL":
|
|
13124
|
-
case "CASE_COL":
|
|
13125
|
-
case "STRFUNC_COL":
|
|
13126
|
-
case "SCALAR_VALUE_COL":
|
|
13127
|
-
case "SCALAR_SUBQUERY_COL":
|
|
13128
|
-
return containsAggregate2(column) || containsAggregateColumnNode(column) ? "AGGREGATE_DEPENDENT" : "SAFE";
|
|
13129
|
-
}
|
|
13130
|
-
}
|
|
13131
|
-
var SUBTABLE_SYSTEM_COLUMNS = ["_pid", "_rid", "_idx"];
|
|
13132
|
-
function unique(values) {
|
|
13133
|
-
return [...new Set(values)];
|
|
13134
|
-
}
|
|
13135
|
-
function sourceColumns(input) {
|
|
13136
|
-
switch (input.kind) {
|
|
13137
|
-
case "APP":
|
|
13138
|
-
return unique([
|
|
13139
|
-
...input.fieldCodes,
|
|
13140
|
-
...APP_SYSTEM_FIELD_CODES
|
|
13141
|
-
]);
|
|
13142
|
-
case "SUBTABLE":
|
|
13143
|
-
return unique([
|
|
13144
|
-
...input.childFieldCodes,
|
|
13145
|
-
...SUBTABLE_SYSTEM_COLUMNS,
|
|
13146
|
-
...input.parentFieldCodes.map((field) => `_p.${field}`)
|
|
13147
|
-
]);
|
|
13148
|
-
case "MATERIALIZED":
|
|
13149
|
-
return unique(input.columns);
|
|
13150
|
-
}
|
|
13151
|
-
}
|
|
13152
|
-
function resolvePlainGroupBySourceSchemas(stmt, lookup) {
|
|
13153
|
-
const sources = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
13154
|
-
return sources.map((source, sourceIndex) => ({
|
|
13155
|
-
sourceIndex,
|
|
13156
|
-
qualifier: source.alias ?? source.cteName,
|
|
13157
|
-
columns: sourceColumns(lookup(source, sourceIndex))
|
|
13158
|
-
}));
|
|
13159
|
-
}
|
|
13160
|
-
function parseGroupName(name) {
|
|
13161
|
-
if (name.startsWith("_p.")) return { qualifier: null, fieldCode: name };
|
|
13162
|
-
const dot = name.indexOf(".");
|
|
13163
|
-
if (dot <= 0 || dot === name.length - 1) {
|
|
13164
|
-
return { qualifier: null, fieldCode: name };
|
|
13165
|
-
}
|
|
13166
|
-
return { qualifier: name.slice(0, dot), fieldCode: name.slice(dot + 1) };
|
|
13167
|
-
}
|
|
13168
|
-
function runtimeKey(source, fieldCode) {
|
|
13169
|
-
return source.qualifier === null ? fieldCode : `${source.qualifier}.${fieldCode}`;
|
|
13170
|
-
}
|
|
13171
|
-
function explicitAlias(column) {
|
|
13172
|
-
return "alias" in column && typeof column.alias === "string" ? column.alias : null;
|
|
13173
|
-
}
|
|
13174
|
-
function resolveFieldName(name, columns, schemas) {
|
|
13175
|
-
const parsed = parseGroupName(name);
|
|
13176
|
-
const candidateSources = parsed.qualifier === null ? schemas : schemas.filter((source) => source.qualifier === parsed.qualifier);
|
|
13177
|
-
const physical = candidateSources.filter((source) => source.columns.includes(parsed.fieldCode));
|
|
13178
|
-
if (physical.length > 1) {
|
|
13179
|
-
throw new Error(
|
|
13180
|
-
`ArgumentError: GROUP BY field ${name} is ambiguous across multiple sources (reason=GROUP_BY_FIELD_AMBIGUOUS).`
|
|
13181
|
-
);
|
|
13182
|
-
}
|
|
13183
|
-
if (physical.length === 1) {
|
|
13184
|
-
const source = physical[0];
|
|
13185
|
-
return {
|
|
13186
|
-
kind: "PHYSICAL",
|
|
13187
|
-
sourceIndex: source.sourceIndex,
|
|
13188
|
-
fieldCode: parsed.fieldCode,
|
|
13189
|
-
runtimeKey: runtimeKey(source, parsed.fieldCode)
|
|
13190
|
-
};
|
|
13191
|
-
}
|
|
13192
|
-
if (parsed.qualifier !== null) return { kind: "UNKNOWN", name };
|
|
13193
|
-
const aliases = columns.flatMap(
|
|
13194
|
-
(column, columnIndex) => explicitAlias(column) === name ? [{ column, columnIndex }] : []
|
|
13195
|
-
);
|
|
13196
|
-
if (aliases.length > 1) return { kind: "ALIAS_REJECT", reason: "DUPLICATE" };
|
|
13197
|
-
if (aliases.length === 1) {
|
|
13198
|
-
const candidate = aliases[0];
|
|
13199
|
-
const classification = classifyPreGroupAlias(candidate.column);
|
|
13200
|
-
if (classification === "SAFE") {
|
|
13201
|
-
return { kind: "ALIAS_SAFE", columnIndex: candidate.columnIndex };
|
|
13202
|
-
}
|
|
13203
|
-
return {
|
|
13204
|
-
kind: "ALIAS_REJECT",
|
|
13205
|
-
reason: classification === "AGGREGATE_DEPENDENT" ? "AGGREGATE" : "POST_GROUP_ONLY"
|
|
13206
|
-
};
|
|
13207
|
-
}
|
|
13208
|
-
const aggregateSyntheticMatch = columns.some(
|
|
13209
|
-
(column) => column.type === "AGGREGATE" && column.alias === null && aggregateSyntheticName(column.func, column.distinct, column.arg) === name
|
|
13210
|
-
);
|
|
13211
|
-
if (aggregateSyntheticMatch) return { kind: "ALIAS_REJECT", reason: "AGGREGATE" };
|
|
13212
|
-
return { kind: "UNKNOWN", name };
|
|
13213
|
-
}
|
|
13214
|
-
function planPlainGroupByResolution(groupBy, columns, schemas) {
|
|
13215
|
-
return {
|
|
13216
|
-
items: groupBy.map(
|
|
13217
|
-
(key) => key.type === "FIELD_NAME" ? resolveFieldName(key.name, columns, schemas) : { kind: "EXPRESSION" }
|
|
13218
|
-
)
|
|
13219
|
-
};
|
|
13220
|
-
}
|
|
13221
|
-
|
|
13222
13482
|
// src/core/emptyWildcardSchema.ts
|
|
13223
13483
|
var EMPTY_WILDCARD_FIELD_TYPE_POLICY = {
|
|
13224
13484
|
CALC: "RECORD",
|
|
@@ -13279,6 +13539,65 @@ async function deriveEmptyWildcardColumns(fields, subtableCode, loadProcessStatu
|
|
|
13279
13539
|
}
|
|
13280
13540
|
|
|
13281
13541
|
// src/engine/process.ts
|
|
13542
|
+
var materializedSelectValues = /* @__PURE__ */ new WeakMap();
|
|
13543
|
+
var sourceRows = /* @__PURE__ */ new WeakMap();
|
|
13544
|
+
function asProcessingRow(source) {
|
|
13545
|
+
if (sourceRows.has(source)) return source;
|
|
13546
|
+
let row;
|
|
13547
|
+
row = new Proxy(source, {
|
|
13548
|
+
get(target, property, receiver) {
|
|
13549
|
+
if (typeof property !== "string" || Object.prototype.hasOwnProperty.call(target, property)) {
|
|
13550
|
+
return Reflect.get(target, property, receiver);
|
|
13551
|
+
}
|
|
13552
|
+
return getMaterializedLookupValue(row, property);
|
|
13553
|
+
},
|
|
13554
|
+
has(target, property) {
|
|
13555
|
+
return Reflect.has(target, property) || typeof property === "string" && getMaterializedLookupValue(row, property) !== void 0;
|
|
13556
|
+
},
|
|
13557
|
+
getOwnPropertyDescriptor(target, property) {
|
|
13558
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(target, property);
|
|
13559
|
+
if (descriptor || typeof property !== "string") return descriptor;
|
|
13560
|
+
const value = getMaterializedLookupValue(row, property);
|
|
13561
|
+
return value === void 0 ? void 0 : { configurable: true, enumerable: false, writable: false, value };
|
|
13562
|
+
}
|
|
13563
|
+
});
|
|
13564
|
+
sourceRows.set(row, source);
|
|
13565
|
+
return row;
|
|
13566
|
+
}
|
|
13567
|
+
function sourceRowForEvaluation(row) {
|
|
13568
|
+
return sourceRows.get(row) ?? row;
|
|
13569
|
+
}
|
|
13570
|
+
function materializedValuesFor(row) {
|
|
13571
|
+
let values = materializedSelectValues.get(row);
|
|
13572
|
+
if (!values) {
|
|
13573
|
+
values = { byColumn: /* @__PURE__ */ new Map(), byLookupKey: /* @__PURE__ */ new Map() };
|
|
13574
|
+
materializedSelectValues.set(row, values);
|
|
13575
|
+
}
|
|
13576
|
+
return values;
|
|
13577
|
+
}
|
|
13578
|
+
function setMaterializedSelectValue(row, columnIndex, value, lookupKeys = []) {
|
|
13579
|
+
const values = materializedValuesFor(row);
|
|
13580
|
+
values.byColumn.set(columnIndex, value);
|
|
13581
|
+
for (const key of lookupKeys) values.byLookupKey.set(key, value);
|
|
13582
|
+
}
|
|
13583
|
+
function getMaterializedSelectValue(row, columnIndex) {
|
|
13584
|
+
return materializedSelectValues.get(row)?.byColumn.get(columnIndex);
|
|
13585
|
+
}
|
|
13586
|
+
function getMaterializedLookupValue(row, key) {
|
|
13587
|
+
return materializedSelectValues.get(row)?.byLookupKey.get(key);
|
|
13588
|
+
}
|
|
13589
|
+
function getLegacyMaterializedValue(row, key) {
|
|
13590
|
+
return materializedSelectValues.has(row) ? void 0 : row[key];
|
|
13591
|
+
}
|
|
13592
|
+
function havingEvaluationRow(row) {
|
|
13593
|
+
const lookups = materializedSelectValues.get(row)?.byLookupKey;
|
|
13594
|
+
if (!lookups || lookups.size === 0) return row;
|
|
13595
|
+
const evaluationRow = { ...row };
|
|
13596
|
+
for (const [key, value] of lookups) evaluationRow[key] = value;
|
|
13597
|
+
const groupingMeta = getGroupingRowMeta(row);
|
|
13598
|
+
if (groupingMeta) attachGroupingRowMeta(evaluationRow, groupingMeta.includedCanonicalIds);
|
|
13599
|
+
return evaluationRow;
|
|
13600
|
+
}
|
|
13282
13601
|
function flatten(record, alias) {
|
|
13283
13602
|
const row = {};
|
|
13284
13603
|
for (const [field, fv] of Object.entries(record)) {
|
|
@@ -13383,7 +13702,7 @@ function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind, resolution
|
|
|
13383
13702
|
}
|
|
13384
13703
|
const result = [];
|
|
13385
13704
|
for (const groupRows of groups.values()) {
|
|
13386
|
-
const outRow = { ...groupRows[0] };
|
|
13705
|
+
const outRow = asProcessingRow({ ...groupRows[0] });
|
|
13387
13706
|
for (const k of groupByKeys) {
|
|
13388
13707
|
if (k.type === "ARITH_KEY") {
|
|
13389
13708
|
outRow[arithColDefaultKey(k.expr)] = String(evalArithExpr(k.expr, groupRows[0]));
|
|
@@ -13435,7 +13754,7 @@ function applyGroupingSets(rows, spec, columns, resolveAggSortKind, limits = {})
|
|
|
13435
13754
|
}
|
|
13436
13755
|
const includedCanonicalIds = new Set(set.items.map((item) => item.canonicalId));
|
|
13437
13756
|
for (const groupRows of buckets) {
|
|
13438
|
-
const outRow = { ...groupRows[0] };
|
|
13757
|
+
const outRow = asProcessingRow({ ...groupRows[0] });
|
|
13439
13758
|
const includedValues = /* @__PURE__ */ new Map();
|
|
13440
13759
|
for (const item of set.items) {
|
|
13441
13760
|
if (!includedValues.has(item.canonicalId)) {
|
|
@@ -13465,32 +13784,52 @@ function materializeAggregateColumns(outRow, groupRows, columns, resolveAggSortK
|
|
|
13465
13784
|
if (col.type === "AGGREGATE") {
|
|
13466
13785
|
const syntheticKey = aggregateSyntheticName(col.func, col.distinct, col.arg);
|
|
13467
13786
|
const value = String(evalAggregate(col.func, col.distinct, col.arg, col.separator, groupRows, resolveAggSortKind));
|
|
13468
|
-
|
|
13469
|
-
|
|
13787
|
+
setMaterializedSelectValue(
|
|
13788
|
+
outRow,
|
|
13789
|
+
columnIndex,
|
|
13790
|
+
value,
|
|
13791
|
+
col.alias ? [col.alias, syntheticKey] : [syntheticKey]
|
|
13792
|
+
);
|
|
13470
13793
|
} else if (col.type === "ARITH_AGG_COL") {
|
|
13471
13794
|
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
13472
13795
|
const outputKey = col.alias ?? aggArithDefaultKey(col.expr);
|
|
13473
|
-
|
|
13796
|
+
setMaterializedSelectValue(
|
|
13797
|
+
outRow,
|
|
13798
|
+
columnIndex,
|
|
13799
|
+
String(evalAggArithExpr(col.expr, groupRows, resolveAggSortKind)),
|
|
13800
|
+
[outputKey]
|
|
13801
|
+
);
|
|
13474
13802
|
} else if (col.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(col.expr)) {
|
|
13475
13803
|
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
13476
13804
|
const outputKey = col.alias ?? stringFuncDefaultKey(col.expr);
|
|
13477
13805
|
const resolvedExpr = resolveAggInStringFuncExpr(col.expr, groupRows, resolveAggSortKind);
|
|
13478
|
-
outRow
|
|
13806
|
+
setMaterializedSelectValue(outRow, columnIndex, evalStringFunc(resolvedExpr, outRow), [outputKey]);
|
|
13479
13807
|
} else if (col.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate2(col.expr)) {
|
|
13480
13808
|
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
13481
13809
|
const outputKey = col.alias ?? scalarValueDefaultKey(col.expr);
|
|
13482
13810
|
const resolvedExpr = resolveAggInScalarValue(col.expr, groupRows, resolveAggSortKind);
|
|
13483
|
-
|
|
13811
|
+
setMaterializedSelectValue(
|
|
13812
|
+
outRow,
|
|
13813
|
+
columnIndex,
|
|
13814
|
+
String(evalScalarValueExpr(resolvedExpr, outRow)),
|
|
13815
|
+
[outputKey]
|
|
13816
|
+
);
|
|
13484
13817
|
} else if (col.type === "CASE_COL" && containsAggregate2(col.expr)) {
|
|
13485
13818
|
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
13486
13819
|
const resolvedExpr = resolveAggInCaseExpr(col.expr, groupRows, resolveAggSortKind);
|
|
13487
13820
|
const resolveAggregateSemantics = (field) => field.aggregateRef ? aggregateResultSemantics(field.aggregateRef, resolveAggSortKind) : void 0;
|
|
13488
|
-
|
|
13821
|
+
const value = evalCaseWhen(
|
|
13489
13822
|
resolvedExpr,
|
|
13490
13823
|
outRow,
|
|
13491
13824
|
void 0,
|
|
13492
13825
|
resolveAggregateSemantics
|
|
13493
13826
|
);
|
|
13827
|
+
setMaterializedSelectValue(
|
|
13828
|
+
outRow,
|
|
13829
|
+
columnIndex,
|
|
13830
|
+
value,
|
|
13831
|
+
[caseMaterializedKey(col.alias, columnIndex)]
|
|
13832
|
+
);
|
|
13494
13833
|
}
|
|
13495
13834
|
}
|
|
13496
13835
|
}
|
|
@@ -13516,8 +13855,8 @@ function materializeAggregateDependencies(outRow, rows, node, resolveAggSortKind
|
|
|
13516
13855
|
collectAggregateRefs(node, refs);
|
|
13517
13856
|
for (const ref of refs) {
|
|
13518
13857
|
const key = aggregateSyntheticName(ref.func, ref.distinct, ref.arg);
|
|
13519
|
-
if (outRow
|
|
13520
|
-
|
|
13858
|
+
if (getMaterializedLookupValue(outRow, key) !== void 0) continue;
|
|
13859
|
+
const value = String(evalAggregate(
|
|
13521
13860
|
ref.func,
|
|
13522
13861
|
ref.distinct,
|
|
13523
13862
|
ref.arg,
|
|
@@ -13525,6 +13864,7 @@ function materializeAggregateDependencies(outRow, rows, node, resolveAggSortKind
|
|
|
13525
13864
|
rows,
|
|
13526
13865
|
resolveAggSortKind
|
|
13527
13866
|
));
|
|
13867
|
+
materializedValuesFor(outRow).byLookupKey.set(key, value);
|
|
13528
13868
|
}
|
|
13529
13869
|
}
|
|
13530
13870
|
function evalGroupByKey(key, row, resolution, columns, aliasEvaluationContext) {
|
|
@@ -13639,7 +13979,8 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
|
|
|
13639
13979
|
}
|
|
13640
13980
|
}
|
|
13641
13981
|
function aggregateRowValues(func, arg, rows) {
|
|
13642
|
-
return rows.map((
|
|
13982
|
+
return rows.map((processingRow) => {
|
|
13983
|
+
const row = sourceRowForEvaluation(processingRow);
|
|
13643
13984
|
let strVal;
|
|
13644
13985
|
if (arg.type === "FIELD_REF") {
|
|
13645
13986
|
const raw = row[arg.field];
|
|
@@ -13720,7 +14061,13 @@ function aggregateResultSemantics(ref, resolver) {
|
|
|
13720
14061
|
}
|
|
13721
14062
|
function applyHaving(rows, having, resolveFieldType, resolveFieldSemantics2) {
|
|
13722
14063
|
if (having === null) return rows;
|
|
13723
|
-
return rows.filter((row) => evalWhere(
|
|
14064
|
+
return rows.filter((row) => evalWhere(
|
|
14065
|
+
having,
|
|
14066
|
+
havingEvaluationRow(row),
|
|
14067
|
+
resolveFieldType,
|
|
14068
|
+
void 0,
|
|
14069
|
+
resolveFieldSemantics2
|
|
14070
|
+
));
|
|
13724
14071
|
}
|
|
13725
14072
|
function applyDistinct(rows, columns, scalarCache, resolveFieldType, resolveFieldSemantics2) {
|
|
13726
14073
|
if (rows.length === 0) return rows;
|
|
@@ -13832,13 +14179,14 @@ var NUMERIC_ORDER_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
|
13832
14179
|
"WEEK"
|
|
13833
14180
|
]);
|
|
13834
14181
|
function evalOrderKey(key, row, aliasEvaluator) {
|
|
14182
|
+
const sourceRow = sourceRowForEvaluation(row);
|
|
13835
14183
|
switch (key.type) {
|
|
13836
14184
|
case "FIELD_NAME":
|
|
13837
|
-
return aliasEvaluator?.(key.name, row) ?? row[key.name] ?? "";
|
|
14185
|
+
return aliasEvaluator?.(key.name, row) ?? getMaterializedLookupValue(row, key.name) ?? sourceRow[key.name] ?? "";
|
|
13838
14186
|
case "ARITH_KEY":
|
|
13839
|
-
return String(evalArithExpr(key.expr,
|
|
14187
|
+
return String(evalArithExpr(key.expr, sourceRow));
|
|
13840
14188
|
case "FUNC_KEY":
|
|
13841
|
-
return evalStringFunc(key.expr,
|
|
14189
|
+
return evalStringFunc(key.expr, sourceRow);
|
|
13842
14190
|
case "GROUPING_KEY":
|
|
13843
14191
|
return evalGroupingRef(key.ref, row);
|
|
13844
14192
|
}
|
|
@@ -13850,38 +14198,41 @@ function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, reso
|
|
|
13850
14198
|
const alias = column.alias;
|
|
13851
14199
|
switch (column.type) {
|
|
13852
14200
|
case "FIELD":
|
|
13853
|
-
evaluators.set(alias, (row) => resolveFieldRef(row, column.field));
|
|
14201
|
+
evaluators.set(alias, (row) => resolveFieldRef(sourceRowForEvaluation(row), column.field));
|
|
13854
14202
|
break;
|
|
13855
14203
|
case "LITERAL_COL":
|
|
13856
14204
|
evaluators.set(alias, () => column.value);
|
|
13857
14205
|
break;
|
|
13858
14206
|
case "AGGREGATE": {
|
|
13859
|
-
|
|
13860
|
-
evaluators.set(alias, (row) => row[alias] ?? row[source] ?? "0");
|
|
14207
|
+
evaluators.set(alias, (row) => getMaterializedSelectValue(row, columnIndex) ?? "0");
|
|
13861
14208
|
break;
|
|
13862
14209
|
}
|
|
13863
14210
|
case "ARITH_AGG_COL": {
|
|
13864
|
-
|
|
13865
|
-
evaluators.set(alias, (row) => row[alias] ?? row[source] ?? "0");
|
|
14211
|
+
evaluators.set(alias, (row) => getMaterializedSelectValue(row, columnIndex) ?? "0");
|
|
13866
14212
|
break;
|
|
13867
14213
|
}
|
|
13868
14214
|
case "WINDOW_COL":
|
|
13869
|
-
evaluators.set(alias, (row) => row
|
|
14215
|
+
evaluators.set(alias, (row) => getMaterializedSelectValue(row, columnIndex) ?? "");
|
|
13870
14216
|
break;
|
|
13871
14217
|
case "ARITH_COL":
|
|
13872
|
-
evaluators.set(alias, (row) => String(evalArithExpr(column.expr, row)));
|
|
14218
|
+
evaluators.set(alias, (row) => String(evalArithExpr(column.expr, sourceRowForEvaluation(row))));
|
|
13873
14219
|
break;
|
|
13874
14220
|
case "STRFUNC_COL": {
|
|
13875
14221
|
const source = stringFuncDefaultKey(column.expr);
|
|
13876
|
-
evaluators.set(alias, (row) => hasAggregateInStringFuncExpr2(column.expr) ? row
|
|
14222
|
+
evaluators.set(alias, (row) => hasAggregateInStringFuncExpr2(column.expr) ? getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, source) ?? evalStringFunc(column.expr, sourceRowForEvaluation(row), resolveFieldType, resolveFieldSemantics2) : evalStringFunc(column.expr, sourceRowForEvaluation(row), resolveFieldType, resolveFieldSemantics2));
|
|
13877
14223
|
break;
|
|
13878
14224
|
}
|
|
13879
14225
|
case "CASE_COL":
|
|
13880
|
-
evaluators.set(alias, (row) => containsAggregate2(column.expr) ? row
|
|
14226
|
+
evaluators.set(alias, (row) => containsAggregate2(column.expr) ? getMaterializedSelectValue(row, columnIndex) ?? "" : evalCaseWhen(column.expr, sourceRowForEvaluation(row), resolveFieldType, resolveFieldSemantics2));
|
|
13881
14227
|
break;
|
|
13882
14228
|
case "SCALAR_VALUE_COL": {
|
|
13883
14229
|
const source = scalarValueDefaultKey(column.expr);
|
|
13884
|
-
evaluators.set(alias, (row) => scalarValueHasAggregate2(column.expr) ? row
|
|
14230
|
+
evaluators.set(alias, (row) => scalarValueHasAggregate2(column.expr) ? getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, source) ?? "" : String(evalScalarValueExpr(
|
|
14231
|
+
column.expr,
|
|
14232
|
+
sourceRowForEvaluation(row),
|
|
14233
|
+
resolveFieldType,
|
|
14234
|
+
resolveFieldSemantics2
|
|
14235
|
+
)));
|
|
13885
14236
|
break;
|
|
13886
14237
|
}
|
|
13887
14238
|
case "SCALAR_SUBQUERY_COL":
|
|
@@ -13897,9 +14248,10 @@ function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, reso
|
|
|
13897
14248
|
return (name, row) => evaluators.get(name)?.(row);
|
|
13898
14249
|
}
|
|
13899
14250
|
function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2, resolveAggSortKind) {
|
|
13900
|
-
const windows = columns.
|
|
14251
|
+
const windows = columns.map((column, columnIndex) => ({ column, columnIndex })).filter((item) => item.column.type === "WINDOW_COL");
|
|
13901
14252
|
if (rows.length === 0 || windows.length === 0) return rows;
|
|
13902
|
-
for (
|
|
14253
|
+
for (let index = 0; index < rows.length; index++) rows[index] = asProcessingRow(rows[index]);
|
|
14254
|
+
for (const { column: window, columnIndex } of windows) {
|
|
13903
14255
|
const partitions = /* @__PURE__ */ new Map();
|
|
13904
14256
|
for (const row of rows) {
|
|
13905
14257
|
const key = JSON.stringify(window.partitionBy.map((ref) => resolveWindowField(row, ref)));
|
|
@@ -13911,11 +14263,11 @@ function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2, re
|
|
|
13911
14263
|
const sortedResult = sortDecoratedRows(partition, window.orderBy, optionOrders, sortKinds, fieldSemantics2);
|
|
13912
14264
|
const sorted = sortedResult.rows;
|
|
13913
14265
|
if (isAggregateWindow(window)) {
|
|
13914
|
-
applyAggregateWindow(window, sortedResult, resolveAggSortKind);
|
|
14266
|
+
applyAggregateWindow(window, columnIndex, sortedResult, resolveAggSortKind);
|
|
13915
14267
|
continue;
|
|
13916
14268
|
}
|
|
13917
14269
|
if (isValueWindow(window)) {
|
|
13918
|
-
applyValueWindow(window, sorted);
|
|
14270
|
+
applyValueWindow(window, columnIndex, sorted);
|
|
13919
14271
|
continue;
|
|
13920
14272
|
}
|
|
13921
14273
|
if (!isRankingWindow(window)) {
|
|
@@ -13929,27 +14281,32 @@ function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2, re
|
|
|
13929
14281
|
denseRank++;
|
|
13930
14282
|
}
|
|
13931
14283
|
const value = window.func === "ROW_NUMBER" ? index + 1 : window.func === "RANK" ? rank : denseRank;
|
|
13932
|
-
sorted[index].row
|
|
14284
|
+
setMaterializedSelectValue(sorted[index].row, columnIndex, String(value), [window.alias]);
|
|
13933
14285
|
}
|
|
13934
14286
|
}
|
|
13935
14287
|
}
|
|
13936
14288
|
return rows;
|
|
13937
14289
|
}
|
|
13938
14290
|
function evaluateValueWindowArg(arg, row) {
|
|
13939
|
-
const value = evalScalarValueExprNullable(arg, row);
|
|
14291
|
+
const value = evalScalarValueExprNullable(arg, sourceRowForEvaluation(row));
|
|
13940
14292
|
if (value === null || value === void 0) return "";
|
|
13941
14293
|
if (typeof value === "number" && !Number.isFinite(value)) return "";
|
|
13942
14294
|
return String(value);
|
|
13943
14295
|
}
|
|
13944
|
-
function applyValueWindow(window, sorted) {
|
|
14296
|
+
function applyValueWindow(window, columnIndex, sorted) {
|
|
13945
14297
|
const values = sorted.map((item) => evaluateValueWindowArg(window.arg, item.row));
|
|
13946
14298
|
const direction = window.valueFunc === "LAG" ? -1 : 1;
|
|
13947
14299
|
for (let index = 0; index < sorted.length; index++) {
|
|
13948
14300
|
const target = index + direction * window.offset;
|
|
13949
|
-
|
|
14301
|
+
setMaterializedSelectValue(
|
|
14302
|
+
sorted[index].row,
|
|
14303
|
+
columnIndex,
|
|
14304
|
+
target >= 0 && target < values.length ? values[target] : "",
|
|
14305
|
+
[window.alias]
|
|
14306
|
+
);
|
|
13950
14307
|
}
|
|
13951
14308
|
}
|
|
13952
|
-
function applyAggregateWindow(window, sortedResult, resolveAggSortKind) {
|
|
14309
|
+
function applyAggregateWindow(window, columnIndex, sortedResult, resolveAggSortKind) {
|
|
13953
14310
|
const sorted = sortedResult.rows;
|
|
13954
14311
|
const values = window.arg.type === "WILDCARD" ? null : aggregateRowValues(window.aggFunc, window.arg, sorted.map((item) => item.row));
|
|
13955
14312
|
const comparison = window.arg.type === "WILDCARD" ? void 0 : resolveAggregateArgSemantics(window.arg, resolveAggSortKind);
|
|
@@ -13982,23 +14339,29 @@ function applyAggregateWindow(window, sortedResult, resolveAggSortKind) {
|
|
|
13982
14339
|
}
|
|
13983
14340
|
if (window.frame === null) {
|
|
13984
14341
|
const finalValue = output[output.length - 1];
|
|
13985
|
-
for (const item of sorted)
|
|
14342
|
+
for (const item of sorted) {
|
|
14343
|
+
setMaterializedSelectValue(item.row, columnIndex, finalValue, [window.alias]);
|
|
14344
|
+
}
|
|
13986
14345
|
return;
|
|
13987
14346
|
}
|
|
13988
14347
|
if (window.frame.unit === "RANGE") {
|
|
13989
14348
|
for (let start = 0; start < sorted.length; ) {
|
|
13990
14349
|
let end = start;
|
|
13991
14350
|
while (end + 1 < sorted.length && sortedResult.compare(sorted[end], sorted[end + 1]) === 0) end++;
|
|
13992
|
-
for (let index = start; index <= end; index++)
|
|
14351
|
+
for (let index = start; index <= end; index++) {
|
|
14352
|
+
setMaterializedSelectValue(sorted[index].row, columnIndex, output[end], [window.alias]);
|
|
14353
|
+
}
|
|
13993
14354
|
start = end + 1;
|
|
13994
14355
|
}
|
|
13995
14356
|
return;
|
|
13996
14357
|
}
|
|
13997
|
-
for (let index = 0; index < sorted.length; index++)
|
|
14358
|
+
for (let index = 0; index < sorted.length; index++) {
|
|
14359
|
+
setMaterializedSelectValue(sorted[index].row, columnIndex, output[index], [window.alias]);
|
|
14360
|
+
}
|
|
13998
14361
|
}
|
|
13999
14362
|
function resolveWindowField(row, ref) {
|
|
14000
14363
|
const name = ref.tableAlias ? `${ref.tableAlias}.${ref.field}` : ref.field;
|
|
14001
|
-
return resolveFieldRef(row, name);
|
|
14364
|
+
return resolveFieldRef(sourceRowForEvaluation(row), name);
|
|
14002
14365
|
}
|
|
14003
14366
|
function applyLimit(rows, limit, offset) {
|
|
14004
14367
|
const start = offset ?? 0;
|
|
@@ -14006,41 +14369,42 @@ function applyLimit(rows, limit, offset) {
|
|
|
14006
14369
|
return rows.slice(start, start + limit);
|
|
14007
14370
|
}
|
|
14008
14371
|
function evaluateSelectColumnValue(column, row, columnIndex, context = {}) {
|
|
14372
|
+
const sourceRow = sourceRowForEvaluation(row);
|
|
14009
14373
|
switch (column.type) {
|
|
14010
14374
|
case "VARIABLE_COL":
|
|
14011
14375
|
throw new Error(`internal error: unresolved SELECT variable @${column.name}`);
|
|
14012
14376
|
case "WILDCARD": {
|
|
14013
|
-
const keys = context.wildcardKeys ?? Object.keys(
|
|
14377
|
+
const keys = context.wildcardKeys ?? Object.keys(sourceRow);
|
|
14014
14378
|
return {
|
|
14015
14379
|
kind: "EXPANDED",
|
|
14016
|
-
entries: keys.map((key) => [key,
|
|
14380
|
+
entries: keys.map((key) => [key, sourceRow[key] !== void 0 ? sourceRow[key] : null])
|
|
14017
14381
|
};
|
|
14018
14382
|
}
|
|
14019
14383
|
case "PARENT_WILDCARD": {
|
|
14020
|
-
const keys = context.parentWildcardKeys ?? Object.keys(
|
|
14384
|
+
const keys = context.parentWildcardKeys ?? Object.keys(sourceRow).filter((key) => key.startsWith("_p.")).sort();
|
|
14021
14385
|
return {
|
|
14022
14386
|
kind: "EXPANDED",
|
|
14023
|
-
entries: keys.map((key) => [key,
|
|
14387
|
+
entries: keys.map((key) => [key, sourceRow[key] !== void 0 ? sourceRow[key] : null])
|
|
14024
14388
|
};
|
|
14025
14389
|
}
|
|
14026
14390
|
case "FIELD":
|
|
14027
|
-
return resolveFieldRef(
|
|
14391
|
+
return resolveFieldRef(sourceRow, column.field);
|
|
14028
14392
|
case "LITERAL_COL":
|
|
14029
14393
|
return column.value;
|
|
14030
14394
|
case "AGGREGATE": {
|
|
14031
14395
|
const source = aggregateSyntheticName(column.func, column.distinct, column.arg);
|
|
14032
|
-
return row
|
|
14396
|
+
return getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, column.alias ?? source) ?? getMaterializedLookupValue(row, source) ?? getLegacyMaterializedValue(row, column.alias ?? source) ?? getLegacyMaterializedValue(row, source) ?? "0";
|
|
14033
14397
|
}
|
|
14034
14398
|
case "ARITH_AGG_COL": {
|
|
14035
14399
|
const source = column.alias ?? aggArithDefaultKey(column.expr);
|
|
14036
|
-
return row
|
|
14400
|
+
return getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, source) ?? getLegacyMaterializedValue(row, source) ?? "0";
|
|
14037
14401
|
}
|
|
14038
14402
|
case "ARITH_COL":
|
|
14039
|
-
return String(evalArithExpr(column.expr,
|
|
14403
|
+
return String(evalArithExpr(column.expr, sourceRow));
|
|
14040
14404
|
case "CASE_COL":
|
|
14041
|
-
return containsAggregate2(column.expr) ? row
|
|
14405
|
+
return containsAggregate2(column.expr) ? getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, caseMaterializedKey(column.alias, columnIndex)) ?? getLegacyMaterializedValue(row, caseMaterializedKey(column.alias, columnIndex)) ?? "" : evalCaseWhen(
|
|
14042
14406
|
column.expr,
|
|
14043
|
-
|
|
14407
|
+
sourceRow,
|
|
14044
14408
|
context.resolveFieldType,
|
|
14045
14409
|
context.resolveFieldSemantics
|
|
14046
14410
|
);
|
|
@@ -14048,23 +14412,23 @@ function evaluateSelectColumnValue(column, row, columnIndex, context = {}) {
|
|
|
14048
14412
|
return evalGroupingRef(column.ref, row);
|
|
14049
14413
|
case "STRFUNC_COL": {
|
|
14050
14414
|
const source = stringFuncDefaultKey(column.expr);
|
|
14051
|
-
return hasAggregateInStringFuncExpr2(column.expr) ? row
|
|
14415
|
+
return hasAggregateInStringFuncExpr2(column.expr) ? getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, column.alias ?? source) ?? getMaterializedLookupValue(row, source) ?? getLegacyMaterializedValue(row, column.alias ?? source) ?? getLegacyMaterializedValue(row, source) ?? evalStringFunc(
|
|
14052
14416
|
column.expr,
|
|
14053
|
-
|
|
14417
|
+
sourceRow,
|
|
14054
14418
|
context.resolveFieldType,
|
|
14055
14419
|
context.resolveFieldSemantics
|
|
14056
14420
|
) : evalStringFunc(
|
|
14057
14421
|
column.expr,
|
|
14058
|
-
|
|
14422
|
+
sourceRow,
|
|
14059
14423
|
context.resolveFieldType,
|
|
14060
14424
|
context.resolveFieldSemantics
|
|
14061
14425
|
);
|
|
14062
14426
|
}
|
|
14063
14427
|
case "SCALAR_VALUE_COL": {
|
|
14064
14428
|
const source = scalarValueDefaultKey(column.expr);
|
|
14065
|
-
return scalarValueHasAggregate2(column.expr) ? row
|
|
14429
|
+
return scalarValueHasAggregate2(column.expr) ? getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, column.alias ?? source) ?? getMaterializedLookupValue(row, source) ?? getLegacyMaterializedValue(row, column.alias ?? source) ?? getLegacyMaterializedValue(row, source) ?? "" : String(evalScalarValueExpr(
|
|
14066
14430
|
column.expr,
|
|
14067
|
-
|
|
14431
|
+
sourceRow,
|
|
14068
14432
|
context.resolveFieldType,
|
|
14069
14433
|
context.resolveFieldSemantics
|
|
14070
14434
|
));
|
|
@@ -14072,7 +14436,7 @@ function evaluateSelectColumnValue(column, row, columnIndex, context = {}) {
|
|
|
14072
14436
|
case "SCALAR_SUBQUERY_COL":
|
|
14073
14437
|
return context.scalarCache?.get(columnIndex) ?? "";
|
|
14074
14438
|
case "WINDOW_COL":
|
|
14075
|
-
return row
|
|
14439
|
+
return getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, column.alias) ?? getLegacyMaterializedValue(row, column.alias) ?? "";
|
|
14076
14440
|
}
|
|
14077
14441
|
}
|
|
14078
14442
|
function buildDistinctTuple(columns, row, context = {}) {
|
|
@@ -16166,9 +16530,9 @@ function render(value) {
|
|
|
16166
16530
|
function buildImportRecordPayload(top, subtables, rowIdMode) {
|
|
16167
16531
|
const record = {};
|
|
16168
16532
|
for (const [code, value] of top) record[code] = { value };
|
|
16169
|
-
for (const [tableCode,
|
|
16533
|
+
for (const [tableCode, sourceRows2] of subtables) {
|
|
16170
16534
|
record[tableCode] = {
|
|
16171
|
-
value:
|
|
16535
|
+
value: sourceRows2.map((sourceRow) => ({
|
|
16172
16536
|
...rowIdMode === "PRESERVE" && sourceRow.rowId ? { id: sourceRow.rowId } : {},
|
|
16173
16537
|
value: Object.fromEntries([...sourceRow.values].map(([childCode, value]) => [childCode, { value }]))
|
|
16174
16538
|
}))
|
|
@@ -17189,7 +17553,13 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
17189
17553
|
return { tempTable: stmt.name };
|
|
17190
17554
|
}
|
|
17191
17555
|
if (stmt.type === "EXPLAIN") {
|
|
17192
|
-
|
|
17556
|
+
const explainStmt = resolvedStmt;
|
|
17557
|
+
explainMaterializedTables.set(explainStmt, tempTables);
|
|
17558
|
+
try {
|
|
17559
|
+
return { result: await executeParsedStatement(explainStmt, client, options, cacheContext) };
|
|
17560
|
+
} finally {
|
|
17561
|
+
explainMaterializedTables.delete(explainStmt);
|
|
17562
|
+
}
|
|
17193
17563
|
}
|
|
17194
17564
|
if (resolvedStmt.type === "ASSERT") {
|
|
17195
17565
|
await executeAssert(resolvedStmt, client, options, cacheContext, tempTables);
|
|
@@ -17725,7 +18095,7 @@ function canProveTotalWindowOrder(stmt, orderBy, resolveField2, context) {
|
|
|
17725
18095
|
}
|
|
17726
18096
|
function tieBreakAdvice(context, kind) {
|
|
17727
18097
|
if (context !== "DIRECT") {
|
|
17728
|
-
return "\u305D\u306E\u8868\u306E\u4E2D\u3067\u4E00\u610F\u306B\u306A\u308B\u5217\uFF08\u5143\u306E\u96C6\u7D04\u306E\u30AD\u30FC\u306A\u3069\uFF09\u3092 ORDER BY \u306B\u542B\u3081\u3066\u304F\u3060\u3055\u3044\u3002\u96C6\u7D04\u7D50\u679C\u306E\u5217\u306F\u4E00\u610F\u3067\u3082\u8A3C\u660E\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u3059\u3067\u306B\u4E00\u610F\u306A\u5834\u5408\u3082\u3053\u306E\u8B66\u544A\u304C\u51FA\u307E\u3059\u3002";
|
|
18098
|
+
return "\u305D\u306E\u8868\u306E\u4E2D\u3067\u4E00\u610F\u306B\u306A\u308B\u5217\uFF08\u5143\u306E\u96C6\u7D04\u306E\u30AD\u30FC\u306A\u3069\uFF09\u3092 ORDER BY \u306B\u542B\u3081\u3066\u304F\u3060\u3055\u3044\u3002\u96C6\u7D04\u7D50\u679C\u306E\u5217\u306F\u4E00\u610F\u3067\u3082\u8A3C\u660E\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u3059\u3067\u306B\u4E00\u610F\u306A\u5834\u5408\u3082\u3053\u306E\u8B66\u544A\u304C\u51FA\u307E\u3059\u3002\u5143\u306E\u96C6\u7D04\u306E\u30AD\u30FC\u3092\u3059\u3079\u3066 ORDER BY \u306B\u542B\u3081\u3066\u3044\u308B\u306A\u3089\u3001\u3053\u306E\u8B66\u544A\u306F\u7121\u8996\u3057\u3066\u69CB\u3044\u307E\u305B\u3093\u3002";
|
|
17729
18099
|
}
|
|
17730
18100
|
return kind === "RANGE" ? "ORDER BY \u306B\u30EC\u30B3\u30FC\u30C9\u756A\u53F7\u306A\u3069\u306E\u30BF\u30A4\u30D6\u30EC\u30FC\u30AF\u30AD\u30FC\u3092\u8DB3\u3057\u3066\u304F\u3060\u3055\u3044\u3002" : "\u30EC\u30B3\u30FC\u30C9\u756A\u53F7\u7B49\u3092 ORDER BY \u306B\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044\u3002";
|
|
17731
18101
|
}
|
|
@@ -17998,7 +18368,12 @@ function dedupeSubtableOwners(owners) {
|
|
|
17998
18368
|
return result;
|
|
17999
18369
|
}
|
|
18000
18370
|
async function buildRuntimePlainGroupByPlan(stmt, client, cacheContext, materializedTables) {
|
|
18001
|
-
|
|
18371
|
+
const normalized = normalizeGroupingSpec(stmt);
|
|
18372
|
+
if (!isAggregateQueryBlock(stmt) || normalized.type === "GROUPING_SETS") {
|
|
18373
|
+
return void 0;
|
|
18374
|
+
}
|
|
18375
|
+
if (normalized.type === "NONE") return void 0;
|
|
18376
|
+
const groupBy = normalized.allItems;
|
|
18002
18377
|
const sources = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
18003
18378
|
const subtableOwners = /* @__PURE__ */ new Map();
|
|
18004
18379
|
const inputs = await Promise.all(sources.map(async (source) => {
|
|
@@ -18036,9 +18411,9 @@ async function buildRuntimePlainGroupByPlan(stmt, client, cacheContext, material
|
|
|
18036
18411
|
stmt,
|
|
18037
18412
|
(_source, sourceIndex) => inputs[sourceIndex]
|
|
18038
18413
|
);
|
|
18039
|
-
const groupBy = stmt.groupBy;
|
|
18040
18414
|
const plan = planPlainGroupByResolution(groupBy, stmt.columns, schemas);
|
|
18041
18415
|
assertRuntimePlainGroupByPlan(stmt, groupBy, plan, subtableOwners);
|
|
18416
|
+
validateAggregateDependencies(stmt, buildOrdinaryDependencyPolicy(stmt, plan, schemas));
|
|
18042
18417
|
return plan;
|
|
18043
18418
|
}
|
|
18044
18419
|
function assertRuntimePlainGroupByPlan(stmt, groupBy, plan, subtableOwners) {
|
|
@@ -18095,7 +18470,9 @@ async function validateStatementGroupingPlanning(statement, client, cacheContext
|
|
|
18095
18470
|
}
|
|
18096
18471
|
const value = node;
|
|
18097
18472
|
if (value["type"] === "SELECT") {
|
|
18473
|
+
for (const child of Object.values(value)) await visit(child);
|
|
18098
18474
|
await validateSelectGroupingPlanning(node, client, cacheContext);
|
|
18475
|
+
return;
|
|
18099
18476
|
}
|
|
18100
18477
|
for (const child of Object.values(value)) await visit(child);
|
|
18101
18478
|
};
|
|
@@ -18143,12 +18520,12 @@ async function buildGroupingFieldResolver(stmt, client, cacheContext, materializ
|
|
|
18143
18520
|
if (field.tableAlias !== null) {
|
|
18144
18521
|
const tableIndex = tables.findIndex((table2) => effectiveTableAlias(table2) === field.tableAlias);
|
|
18145
18522
|
if (tableIndex < 0) {
|
|
18146
|
-
throw new Error(`ArgumentError:
|
|
18523
|
+
throw new Error(`ArgumentError: field ${field.tableAlias}.${field.field} has an unknown table alias.`);
|
|
18147
18524
|
}
|
|
18148
18525
|
const table = tables[tableIndex];
|
|
18149
18526
|
if (table.cteName !== null) {
|
|
18150
18527
|
throw new Error(
|
|
18151
|
-
`ArgumentError:
|
|
18528
|
+
`ArgumentError: field ${field.tableAlias}.${field.field} resolves to materialized source ${table.cteName}; physical APP fields are required.`
|
|
18152
18529
|
);
|
|
18153
18530
|
}
|
|
18154
18531
|
const code = physicalMatch(table, field.field);
|
|
@@ -18157,7 +18534,7 @@ async function buildGroupingFieldResolver(stmt, client, cacheContext, materializ
|
|
|
18157
18534
|
if (owner !== null && owner !== "") {
|
|
18158
18535
|
throw new Error(subtableGroupingAdvice(field.field, [{ appId: table.appId, owner }]));
|
|
18159
18536
|
}
|
|
18160
|
-
throw new Error(`ArgumentError:
|
|
18537
|
+
throw new Error(`ArgumentError: field ${field.tableAlias}.${field.field} does not exist in APP${table.appId}.`);
|
|
18161
18538
|
}
|
|
18162
18539
|
return resolved(table, tableIndex, field, code);
|
|
18163
18540
|
}
|
|
@@ -18168,7 +18545,7 @@ async function buildGroupingFieldResolver(stmt, client, cacheContext, materializ
|
|
|
18168
18545
|
});
|
|
18169
18546
|
const materializedMatches = tables.filter((table) => materializedHas(table, field.field));
|
|
18170
18547
|
if (physicalMatches.length + materializedMatches.length > 1) {
|
|
18171
|
-
throw new Error(`ArgumentError:
|
|
18548
|
+
throw new Error(`ArgumentError: field ${field.field} is ambiguous across multiple sources.`);
|
|
18172
18549
|
}
|
|
18173
18550
|
if (physicalMatches.length === 1 && materializedMatches.length === 0) {
|
|
18174
18551
|
const match = physicalMatches[0];
|
|
@@ -18176,7 +18553,7 @@ async function buildGroupingFieldResolver(stmt, client, cacheContext, materializ
|
|
|
18176
18553
|
}
|
|
18177
18554
|
if (materializedMatches.length === 1) {
|
|
18178
18555
|
throw new Error(
|
|
18179
|
-
`ArgumentError:
|
|
18556
|
+
`ArgumentError: field ${field.field} resolves to a materialized CTE/temp column; physical APP fields are required.`
|
|
18180
18557
|
);
|
|
18181
18558
|
}
|
|
18182
18559
|
const owners = tables.flatMap((table) => {
|
|
@@ -18188,21 +18565,34 @@ async function buildGroupingFieldResolver(stmt, client, cacheContext, materializ
|
|
|
18188
18565
|
if (uniqueOwners.length > 0) {
|
|
18189
18566
|
throw new Error(subtableGroupingAdvice(field.field, uniqueOwners));
|
|
18190
18567
|
}
|
|
18191
|
-
throw new Error(`ArgumentError:
|
|
18568
|
+
throw new Error(`ArgumentError: field ${field.field} does not exist in a physical APP source.`);
|
|
18192
18569
|
};
|
|
18193
18570
|
}
|
|
18194
18571
|
async function validateSelectGroupingPlanning(stmt, client, cacheContext, materializedTables) {
|
|
18195
18572
|
resolvedGroupingSpecs.delete(stmt);
|
|
18196
18573
|
const normalized = normalizeGroupingSpec(stmt);
|
|
18197
18574
|
const hasGroupingNodes = JSON.stringify(stmt.columns).includes('"GROUPING_') || JSON.stringify(stmt.orderBy).includes('"GROUPING_');
|
|
18198
|
-
if (normalized.type === "
|
|
18199
|
-
|
|
18200
|
-
|
|
18201
|
-
|
|
18202
|
-
|
|
18203
|
-
|
|
18575
|
+
if (normalized.type === "GROUPING_SETS" || hasGroupingNodes) {
|
|
18576
|
+
const resolver = await buildGroupingFieldResolver(stmt, client, cacheContext, materializedTables);
|
|
18577
|
+
const resolvedSpec = validateGroupingPlanning(
|
|
18578
|
+
stmt,
|
|
18579
|
+
resolver,
|
|
18580
|
+
enforceGroupingPlanningCandidateLimits
|
|
18581
|
+
);
|
|
18582
|
+
if (resolvedSpec) resolvedGroupingSpecs.set(stmt, resolvedSpec);
|
|
18583
|
+
return;
|
|
18584
|
+
}
|
|
18585
|
+
if (!isAggregateQueryBlock(stmt)) return;
|
|
18586
|
+
if (normalized.type === "NONE") {
|
|
18587
|
+
validateAggregateDependenciesStatic(stmt);
|
|
18588
|
+
return;
|
|
18589
|
+
}
|
|
18590
|
+
const sources = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
18591
|
+
const hasUnavailableMaterializedSource = sources.some(
|
|
18592
|
+
(source) => source.cteName !== null && !materializedTables?.has(source.cteName)
|
|
18204
18593
|
);
|
|
18205
|
-
if (
|
|
18594
|
+
if (hasUnavailableMaterializedSource) return;
|
|
18595
|
+
await buildRuntimePlainGroupByPlan(stmt, client, cacheContext, materializedTables);
|
|
18206
18596
|
}
|
|
18207
18597
|
function completeInputErrorPrefix(reasons) {
|
|
18208
18598
|
const reasonList = [...reasons].join(", ");
|
|
@@ -19316,7 +19706,7 @@ function mergeUnionColumnMeta(left, right) {
|
|
|
19316
19706
|
function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
|
|
19317
19707
|
const tables = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
19318
19708
|
const physicalTables = tables.filter((table) => table.cteName === null);
|
|
19319
|
-
const
|
|
19709
|
+
const outputAliases = new Set(
|
|
19320
19710
|
stmt.columns.map((column) => "alias" in column ? column.alias : null).filter((alias) => alias !== null)
|
|
19321
19711
|
);
|
|
19322
19712
|
const row = (field) => {
|
|
@@ -19340,7 +19730,7 @@ function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
|
|
|
19340
19730
|
return matches.length === 1 ? matches[0] : void 0;
|
|
19341
19731
|
};
|
|
19342
19732
|
const having = (field) => {
|
|
19343
|
-
if (field.tableAlias === null &&
|
|
19733
|
+
if (field.tableAlias === null && outputAliases.has(field.field)) return void 0;
|
|
19344
19734
|
return row(field);
|
|
19345
19735
|
};
|
|
19346
19736
|
return { row, having };
|
|
@@ -20084,10 +20474,10 @@ async function tryFetchJoinRecordsBySourceKeys(stmt, join2, tables, client, maxR
|
|
|
20084
20474
|
} else {
|
|
20085
20475
|
return null;
|
|
20086
20476
|
}
|
|
20087
|
-
const
|
|
20088
|
-
if (!
|
|
20477
|
+
const sourceRows2 = tables.get(sourceAlias);
|
|
20478
|
+
if (!sourceRows2) return null;
|
|
20089
20479
|
const keys = /* @__PURE__ */ new Set();
|
|
20090
|
-
for (const row of
|
|
20480
|
+
for (const row of sourceRows2) {
|
|
20091
20481
|
const raw = row[sourceField]?.value;
|
|
20092
20482
|
const txt = toScalarText(raw).trim();
|
|
20093
20483
|
if (txt.length > 0) keys.add(txt);
|
|
@@ -20997,7 +21387,7 @@ async function materializeValidationCandidates(stmt, operation, client, options,
|
|
|
20997
21387
|
);
|
|
20998
21388
|
}
|
|
20999
21389
|
let rows;
|
|
21000
|
-
let
|
|
21390
|
+
let sourceRows2;
|
|
21001
21391
|
let sourcePresence;
|
|
21002
21392
|
let sourceRowErrors;
|
|
21003
21393
|
let evaluationTypes;
|
|
@@ -21018,7 +21408,7 @@ async function materializeValidationCandidates(stmt, operation, client, options,
|
|
|
21018
21408
|
throw customCheckParseError("CHECK \u4ED8\u304D DML \u30BD\u30FC\u30B9 SELECT \u306E\u51FA\u529B\u540D\u306F\u4E00\u610F\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059");
|
|
21019
21409
|
}
|
|
21020
21410
|
assertInsertCheckRefs(stmt, selectResult.columns);
|
|
21021
|
-
|
|
21411
|
+
sourceRows2 = selectResult.rows;
|
|
21022
21412
|
sourcePresence = selectResult.importPresence;
|
|
21023
21413
|
sourceRowErrors = selectResult.importRowErrors;
|
|
21024
21414
|
const meta = selectResult.columnMeta;
|
|
@@ -21039,7 +21429,7 @@ async function materializeValidationCandidates(stmt, operation, client, options,
|
|
|
21039
21429
|
)),
|
|
21040
21430
|
preErrors: [...sourceRowErrors?.[index] ?? []],
|
|
21041
21431
|
record: {},
|
|
21042
|
-
evaluationRow:
|
|
21432
|
+
evaluationRow: sourceRows2?.[index] ?? Object.fromEntries(
|
|
21043
21433
|
stmt.fields.map((field, i) => [field, renderValidationValue(values[i])])
|
|
21044
21434
|
),
|
|
21045
21435
|
evaluationFieldTypes: evaluationTypes
|
|
@@ -21335,7 +21725,7 @@ async function resolveUpdateFromMatchedRecords(stmt, from, client, options, cach
|
|
|
21335
21725
|
const checkScope = await resolveUpdateFromCheckScope(stmt, from, client, cacheContext, tempTables);
|
|
21336
21726
|
const sourceFields = [...new Set(stmt.assignments.filter((a) => a.value.type === "SOURCE_FIELD").map((a) => a.value.type === "SOURCE_FIELD" ? a.value.field : "").concat(checkScope.sourceFields))];
|
|
21337
21727
|
const requiredSourceFields = [.../* @__PURE__ */ new Set([from.joinKeyField, ...sourceFields])];
|
|
21338
|
-
const
|
|
21728
|
+
const sourceRows2 = await loadUpdateFromSourceRows(
|
|
21339
21729
|
from,
|
|
21340
21730
|
requiredSourceFields,
|
|
21341
21731
|
sourceFields,
|
|
@@ -21346,7 +21736,7 @@ async function resolveUpdateFromMatchedRecords(stmt, from, client, options, cach
|
|
|
21346
21736
|
);
|
|
21347
21737
|
const sourceByKey = /* @__PURE__ */ new Map();
|
|
21348
21738
|
const sourceQueryByKey = /* @__PURE__ */ new Map();
|
|
21349
|
-
for (const row of
|
|
21739
|
+
for (const row of sourceRows2) {
|
|
21350
21740
|
if (!Object.prototype.hasOwnProperty.call(row, from.joinKeyField)) {
|
|
21351
21741
|
throw new Error(`ArgumentError: UPDATE ... FROM source column ${from.joinKeyField} does not exist.`);
|
|
21352
21742
|
}
|
|
@@ -23359,7 +23749,7 @@ var explainJoinPushdownPlans = /* @__PURE__ */ new WeakMap();
|
|
|
23359
23749
|
var explainChoiceEqualityRewrites = /* @__PURE__ */ new WeakMap();
|
|
23360
23750
|
var validateExplainInfo = /* @__PURE__ */ new WeakMap();
|
|
23361
23751
|
var applyParentExplainPlan = /* @__PURE__ */ new WeakMap();
|
|
23362
|
-
async function buildExplainWhereAnalysis(query, client, cacheContext, maxRecords = 1e4, relativeDatePlan) {
|
|
23752
|
+
async function buildExplainWhereAnalysis(query, client, cacheContext, maxRecords = 1e4, relativeDatePlan, initialRelations) {
|
|
23363
23753
|
const fieldApps = /* @__PURE__ */ new Set();
|
|
23364
23754
|
const processStatusApps = /* @__PURE__ */ new Set();
|
|
23365
23755
|
const numberPrecisionApps = /* @__PURE__ */ new Set();
|
|
@@ -23386,6 +23776,119 @@ async function buildExplainWhereAnalysis(query, client, cacheContext, maxRecords
|
|
|
23386
23776
|
const relativeNodeFor = (source) => sharedRelativeDatePlan.nodes.find(
|
|
23387
23777
|
(node) => node.source === source || JSON.stringify(node.source) === JSON.stringify(source)
|
|
23388
23778
|
);
|
|
23779
|
+
const explainRelations = new Map(initialRelations ?? []);
|
|
23780
|
+
const explainSourceColumns = async (select) => {
|
|
23781
|
+
const tables = [select.from, ...select.joins.map((join2) => join2.table)];
|
|
23782
|
+
if (tables.length > 1 && select.columns.some(
|
|
23783
|
+
(column) => column.type === "WILDCARD" || column.type === "PARENT_WILDCARD"
|
|
23784
|
+
)) {
|
|
23785
|
+
throw new Error(
|
|
23786
|
+
"ArgumentError: EXPLAIN could not determine the relation output schema for a multi-source wildcard SELECT."
|
|
23787
|
+
);
|
|
23788
|
+
}
|
|
23789
|
+
const columns = [];
|
|
23790
|
+
for (const table of tables) {
|
|
23791
|
+
if (table.cteName !== null) {
|
|
23792
|
+
if (table.cteName === NO_FROM_CTE_NAME) continue;
|
|
23793
|
+
const relation = explainRelations.get(table.cteName);
|
|
23794
|
+
if (!relation) {
|
|
23795
|
+
throw new Error(
|
|
23796
|
+
`ArgumentError: EXPLAIN could not determine the relation output schema for ${table.cteName}.`
|
|
23797
|
+
);
|
|
23798
|
+
}
|
|
23799
|
+
columns.push(...relation.columns);
|
|
23800
|
+
continue;
|
|
23801
|
+
}
|
|
23802
|
+
const fields = await getFieldsCached(table.appId, tracedClient, cacheContext);
|
|
23803
|
+
if (table.subtableCode) {
|
|
23804
|
+
columns.push(...fields.filter(
|
|
23805
|
+
(field) => field.inSubtable && (field.subtableCode === table.subtableCode || field.subtableCode === void 0)
|
|
23806
|
+
).map((field) => field.code));
|
|
23807
|
+
columns.push("_pid", "_rid", "_idx");
|
|
23808
|
+
columns.push(...fields.filter((field) => !field.inSubtable).map((field) => `_p.${field.code}`));
|
|
23809
|
+
} else {
|
|
23810
|
+
columns.push(...fields.filter((field) => !field.inSubtable).map((field) => field.code));
|
|
23811
|
+
columns.push(...APP_SYSTEM_FIELD_CODES);
|
|
23812
|
+
}
|
|
23813
|
+
}
|
|
23814
|
+
return [...new Set(columns)];
|
|
23815
|
+
};
|
|
23816
|
+
const inferExplainRelationColumns = async (node) => {
|
|
23817
|
+
if (node === null || typeof node !== "object") {
|
|
23818
|
+
throw new Error("ArgumentError: EXPLAIN could not determine the relation output schema.");
|
|
23819
|
+
}
|
|
23820
|
+
const typed = node;
|
|
23821
|
+
if (typed["type"] === "SELECT") {
|
|
23822
|
+
const select = node;
|
|
23823
|
+
const sourceColumns2 = await explainSourceColumns(select);
|
|
23824
|
+
if (select.columns.length === 1 && select.columns[0].type === "WILDCARD") {
|
|
23825
|
+
return sourceColumns2;
|
|
23826
|
+
}
|
|
23827
|
+
const output = [];
|
|
23828
|
+
for (const column of select.columns) {
|
|
23829
|
+
if (column.type === "WILDCARD") output.push(...sourceColumns2);
|
|
23830
|
+
else if (column.type === "PARENT_WILDCARD") {
|
|
23831
|
+
output.push(...sourceColumns2.filter((name) => name.startsWith("_p.")));
|
|
23832
|
+
} else {
|
|
23833
|
+
output.push(...project([], [column]).columns);
|
|
23834
|
+
}
|
|
23835
|
+
}
|
|
23836
|
+
return output;
|
|
23837
|
+
}
|
|
23838
|
+
if (typed["type"] === "UNION") {
|
|
23839
|
+
return inferExplainRelationColumns(typed["left"]);
|
|
23840
|
+
}
|
|
23841
|
+
if (typed["type"] === "SHOW_APPS") return [...SHOW_APPS_COLUMNS];
|
|
23842
|
+
if (typed["type"] === "DESCRIBE") return [...DESCRIBE_COLUMNS];
|
|
23843
|
+
throw new Error("ArgumentError: EXPLAIN could not determine the relation output schema.");
|
|
23844
|
+
};
|
|
23845
|
+
const preflightExplainRelations = async (node) => {
|
|
23846
|
+
if (node === null || typeof node !== "object") return;
|
|
23847
|
+
if (Array.isArray(node)) {
|
|
23848
|
+
for (const child of node) await preflightExplainRelations(child);
|
|
23849
|
+
return;
|
|
23850
|
+
}
|
|
23851
|
+
const typed = node;
|
|
23852
|
+
if (typed["type"] === "WITH") {
|
|
23853
|
+
const withStatement = node;
|
|
23854
|
+
for (const cte of withStatement.ctes) {
|
|
23855
|
+
await preflightExplainRelations(cte.query);
|
|
23856
|
+
const columns = await inferExplainRelationColumns(cte.query);
|
|
23857
|
+
explainRelations.set(cte.name, { rows: [], columns });
|
|
23858
|
+
}
|
|
23859
|
+
await preflightExplainRelations(withStatement.query);
|
|
23860
|
+
return;
|
|
23861
|
+
}
|
|
23862
|
+
if (typed["type"] === "UNION") {
|
|
23863
|
+
await preflightExplainRelations(typed["left"]);
|
|
23864
|
+
await preflightExplainRelations(typed["right"]);
|
|
23865
|
+
return;
|
|
23866
|
+
}
|
|
23867
|
+
if (typed["type"] === "SELECT") {
|
|
23868
|
+
const select = node;
|
|
23869
|
+
for (const column of select.columns) {
|
|
23870
|
+
if (column.type === "SCALAR_SUBQUERY_COL") await preflightExplainRelations(column.query);
|
|
23871
|
+
}
|
|
23872
|
+
await preflightExplainRelations(select.where);
|
|
23873
|
+
await preflightExplainRelations(select.having);
|
|
23874
|
+
await validateSelectGroupingPlanning(
|
|
23875
|
+
select,
|
|
23876
|
+
tracedClient,
|
|
23877
|
+
cacheContext,
|
|
23878
|
+
explainRelations
|
|
23879
|
+
);
|
|
23880
|
+
const plainPlan = await buildRuntimePlainGroupByPlan(
|
|
23881
|
+
select,
|
|
23882
|
+
tracedClient,
|
|
23883
|
+
cacheContext,
|
|
23884
|
+
explainRelations
|
|
23885
|
+
);
|
|
23886
|
+
if (plainPlan) plainGroupByPlans.set(select, plainPlan);
|
|
23887
|
+
return;
|
|
23888
|
+
}
|
|
23889
|
+
for (const child of Object.values(typed)) await preflightExplainRelations(child);
|
|
23890
|
+
};
|
|
23891
|
+
await preflightExplainRelations(query);
|
|
23389
23892
|
const visit = async (node) => {
|
|
23390
23893
|
if (node === null || typeof node !== "object") return;
|
|
23391
23894
|
if (seen.has(node)) return;
|
|
@@ -24057,6 +24560,7 @@ function buildPlanForBatchQuery(query, info, capabilities, orderPlans, collector
|
|
|
24057
24560
|
lines.push(" note: \u4E00\u6642\u30C6\u30FC\u30D6\u30EB\u3078\u306E WHERE \u30D7\u30C3\u30B7\u30E5\u30C0\u30A6\u30F3\u306F\u884C\u308F\u308C\u306A\u3044");
|
|
24058
24561
|
return lines;
|
|
24059
24562
|
}
|
|
24563
|
+
var explainMaterializedTables = /* @__PURE__ */ new WeakMap();
|
|
24060
24564
|
async function executeExplain(stmt, client, cacheContext, maxRecords, cursorMaxActive, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, relativeDatePlan) {
|
|
24061
24565
|
const sharedPlan = relativeDatePlan ?? await resolveRelativeDateExecutionPlan(stmt.query, client, cacheContext);
|
|
24062
24566
|
const analysis = await buildExplainWhereAnalysis(
|
|
@@ -24064,7 +24568,8 @@ async function executeExplain(stmt, client, cacheContext, maxRecords, cursorMaxA
|
|
|
24064
24568
|
client,
|
|
24065
24569
|
cacheContext,
|
|
24066
24570
|
maxRecords,
|
|
24067
|
-
sharedPlan
|
|
24571
|
+
sharedPlan,
|
|
24572
|
+
explainMaterializedTables.get(stmt)
|
|
24068
24573
|
);
|
|
24069
24574
|
const fetchCollector = { sources: [] };
|
|
24070
24575
|
const relativeLines = relativeDateExplainLines(sharedPlan);
|
|
@@ -24358,6 +24863,12 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlan
|
|
|
24358
24863
|
lines.push(
|
|
24359
24864
|
` group key ${key.name}: PHYSICAL (source=${item.sourceIndex}, field=${item.fieldCode})`
|
|
24360
24865
|
);
|
|
24866
|
+
} else if (item.kind === "ALIAS_SAFE") {
|
|
24867
|
+
lines.push(
|
|
24868
|
+
` group key ${key.name}: ALIAS_SAFE (column=${item.columnIndex})`
|
|
24869
|
+
);
|
|
24870
|
+
} else if (item.kind === "EXPRESSION") {
|
|
24871
|
+
lines.push(` group key ${key.name}: EXPRESSION`);
|
|
24361
24872
|
}
|
|
24362
24873
|
});
|
|
24363
24874
|
} else if ([stmt.from, ...stmt.joins.map((join2) => join2.table)].some((table) => table.cteName !== null)) {
|