@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 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: B65 expanded grouping set count ${rejectedSetCount} exceeds limit ${B65_MAX_GROUPING_SETS} (reason=GROUPING_SET_LIMIT_EXCEEDED).`
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: B65 expanded grouping set count ${facts.expandedSetCount} exceeds limit ${B65_MAX_GROUPING_SETS} (reason=GROUPING_SET_LIMIT_EXCEEDED).`
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: B65 canonical grouping item count ${facts.canonicalItemCount} exceeds limit ${B65_MAX_GROUPING_ITEMS} (reason=GROUPING_ITEM_LIMIT_EXCEEDED).`
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 displayField(field) {
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: B65 grouping reference ${displayField(ref.field)} must resolve to a physical APP field.`);
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: B65 GROUPING argument ${displayField(ref.field)} is not present in grouping allItems (reason=B65_GROUPING_ARG_NOT_ITEM).`
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: B65 GROUPING() is not allowed in WHERE, JOIN, window, aggregate arguments, or DML expressions."
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: B65 GROUPING() requires GROUP BY ROLLUP or GROUPING SETS.");
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: B65 KORDER BY is not supported in Phase1.");
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: B65 window functions are not supported in Phase1.");
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("ArgumentError: B65 wildcard projection is not supported in Phase1.");
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: B65 grouping item ${displayField(item.field)} must resolve to a physical APP field.`);
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
- const aliases = outputAliases(stmt.columns);
5820
- for (const column of stmt.columns) {
5821
- if (column.type === "GROUPING_COL" || column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL" || column.type === "LITERAL_COL" || column.type === "VARIABLE_COL" || column.type === "SCALAR_SUBQUERY_COL") continue;
5822
- const refs = [];
5823
- if (column.type === "FIELD") refs.push(refFromName(column.field));
5824
- else collectNonAggregateFieldRefs(column, refs);
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: B65 aggregate alias ${alias} collides with a grouping runtime key (reason=B65_AGGREGATE_ALIAS_COLLISION).`
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 sourceRows = record[tableCode]?.value;
10382
- if (!Array.isArray(sourceRows)) continue;
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 < sourceRows.length; rowIndex++) {
10385
- const sourceRow = sourceRows[rowIndex];
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
- outRow[col.alias ?? syntheticKey] = value;
13469
- if (col.alias) outRow[syntheticKey] = value;
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
- outRow[outputKey] = String(evalAggArithExpr(col.expr, groupRows, resolveAggSortKind));
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[outputKey] = evalStringFunc(resolvedExpr, 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
- outRow[outputKey] = String(evalScalarValueExpr(resolvedExpr, outRow));
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
- outRow[caseMaterializedKey(col.alias, columnIndex)] = evalCaseWhen(
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[key] !== void 0) continue;
13520
- outRow[key] = String(evalAggregate(
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((row) => {
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(having, row, resolveFieldType, void 0, resolveFieldSemantics2));
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, row));
14187
+ return String(evalArithExpr(key.expr, sourceRow));
13840
14188
  case "FUNC_KEY":
13841
- return evalStringFunc(key.expr, row);
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
- const source = aggregateSyntheticName(column.func, column.distinct, column.arg);
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
- const source = aggArithDefaultKey(column.expr);
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[alias] ?? "");
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[alias] ?? row[source] ?? evalStringFunc(column.expr, row, resolveFieldType, resolveFieldSemantics2) : evalStringFunc(column.expr, row, resolveFieldType, resolveFieldSemantics2));
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[alias] ?? "" : evalCaseWhen(column.expr, row, resolveFieldType, resolveFieldSemantics2));
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[alias] ?? row[source] ?? "" : String(evalScalarValueExpr(column.expr, row, resolveFieldType, resolveFieldSemantics2)));
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.filter((column) => column.type === "WINDOW_COL");
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 (const window of windows) {
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[window.alias] = String(value);
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
- sorted[index].row[window.alias] = target >= 0 && target < values.length ? values[target] : "";
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) item.row[window.alias] = finalValue;
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++) sorted[index].row[window.alias] = output[end];
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++) sorted[index].row[window.alias] = output[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(row);
14377
+ const keys = context.wildcardKeys ?? Object.keys(sourceRow);
14014
14378
  return {
14015
14379
  kind: "EXPANDED",
14016
- entries: keys.map((key) => [key, row[key] !== void 0 ? row[key] : null])
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(row).filter((key) => key.startsWith("_p.")).sort();
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, row[key] !== void 0 ? row[key] : null])
14387
+ entries: keys.map((key) => [key, sourceRow[key] !== void 0 ? sourceRow[key] : null])
14024
14388
  };
14025
14389
  }
14026
14390
  case "FIELD":
14027
- return resolveFieldRef(row, column.field);
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[column.alias ?? source] ?? row[source] ?? "0";
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[source] ?? "0";
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, row));
14403
+ return String(evalArithExpr(column.expr, sourceRow));
14040
14404
  case "CASE_COL":
14041
- return containsAggregate2(column.expr) ? row[caseMaterializedKey(column.alias, columnIndex)] ?? "" : evalCaseWhen(
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
- row,
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[column.alias ?? source] ?? row[source] ?? evalStringFunc(
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
- row,
14417
+ sourceRow,
14054
14418
  context.resolveFieldType,
14055
14419
  context.resolveFieldSemantics
14056
14420
  ) : evalStringFunc(
14057
14421
  column.expr,
14058
- row,
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[column.alias ?? source] ?? row[source] ?? "" : String(evalScalarValueExpr(
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
- row,
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[column.alias] ?? "";
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, sourceRows] of subtables) {
16533
+ for (const [tableCode, sourceRows2] of subtables) {
16170
16534
  record[tableCode] = {
16171
- value: sourceRows.map((sourceRow) => ({
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
- return { result: await executeParsedStatement(resolvedStmt, client, options, cacheContext) };
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
- if (stmt.groupBy.length === 0) return void 0;
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: B65 field ${field.tableAlias}.${field.field} has an unknown table alias.`);
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: B65 field ${field.tableAlias}.${field.field} resolves to materialized source ${table.cteName}; physical APP fields are required.`
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: B65 field ${field.tableAlias}.${field.field} does not exist in APP${table.appId}.`);
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: B65 field ${field.field} is ambiguous across multiple sources.`);
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: B65 field ${field.field} resolves to a materialized CTE/temp column; physical APP fields are required.`
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: B65 field ${field.field} does not exist in a physical APP source.`);
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 === "NONE" && !hasGroupingNodes) return;
18199
- const resolver = await buildGroupingFieldResolver(stmt, client, cacheContext, materializedTables);
18200
- const resolvedSpec = validateGroupingPlanning(
18201
- stmt,
18202
- resolver,
18203
- enforceGroupingPlanningCandidateLimits
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 (resolvedSpec) resolvedGroupingSpecs.set(stmt, resolvedSpec);
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 outputAliases2 = new Set(
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 && outputAliases2.has(field.field)) return void 0;
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 sourceRows = tables.get(sourceAlias);
20088
- if (!sourceRows) return null;
20477
+ const sourceRows2 = tables.get(sourceAlias);
20478
+ if (!sourceRows2) return null;
20089
20479
  const keys = /* @__PURE__ */ new Set();
20090
- for (const row of sourceRows) {
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 sourceRows;
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
- sourceRows = selectResult.rows;
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: sourceRows?.[index] ?? Object.fromEntries(
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 sourceRows = await loadUpdateFromSourceRows(
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 sourceRows) {
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)) {