このコミットが含まれているのは:
2026-10-31 13:50:10 +09:00
コミット dba409c3e8
33個のファイルの変更、1490行の追加、236行の削除
+14 -7
ファイルの表示
@@ -1,4 +1,4 @@
# Re-aggregate the population, never add up already grouped cells (multi-value axes overlap).
# Re-aggregate distinct membership; tag row tuples alone use additive contributions.
class CountsPivotTotals
def initialize(population, axes, row_headers, column_headers)
@population = population
@@ -8,8 +8,12 @@ class CountsPivotTotals
end
def call
# MySQL's unlimited LIMIT prevents CTE merging: authorise once for all branches.
basis = @population.scope.except(:select, :order).select('v.*')
# Materialise full-cell membership once, including omitted multi-value axes.
membership = @population.scope.except(:select, :order)
joins = @axes.joins
membership = membership.joins(joins) unless joins.empty?
# Retain exactly the records contributing a full cell, including changed_field.
basis = membership.select('v.*').distinct
.limit(18_446_744_073_709_551_615).to_sql
queries = @rows.flat_map do |row_depth, headers|
@columns.filter_map do |column_depth, columns|
@@ -18,7 +22,7 @@ class CountsPivotTotals
indexes = (0...row_depth).to_a +
(0...column_depth).map { @axes.rows.length + _1 }
expressions = indexes.map { @axes.expressions[_1] }
scope = @population.scope.except(:select, :order, :where, :from).from('authorised v')
scope = @population.scope.except(:select, :order, :where, :from).from('population_members v')
additive = @axes.rows.any? { _1['field'] == 'tags' }
retained = additive ? (0...@axes.rows.length).to_a | indexes : indexes
joins = @axes.joins(retained.map { @axes.all[_1].fetch('field') })
@@ -47,9 +51,12 @@ class CountsPivotTotals
if additive
# Sum full row tuples, not page cells; preserve DISTINCT inside each tuple.
leaf = retained.map { @axes.expressions[_1] }
selected = leaf.each_with_index.map { |expression, index| "#{ expression } AS k#{ index }" }
selected = leaf.each_with_index.map do |expression, index|
"#{ expression } AS k#{ index }"
end
selected << "#{ @axes.count_expression } AS count"
inner = scope.group(*leaf.map { Arel.sql(_1) })
.select(Arel.sql((selected + ["#{ @axes.count_expression } AS count"]).join(', '))).to_sql
.select(Arel.sql(selected.join(', '))).to_sql
coordinates = indexes.map { "k#{ retained.index(_1) }" }
projected = coordinates.each_with_index.map { |key, index| "#{ key } AS v#{ index }" }
output = ["#{ row_depth } AS row_depth", "#{ column_depth } AS column_depth"] +
@@ -67,7 +74,7 @@ class CountsPivotTotals
sql = queries.map { "(#{ _1 })" }.join(' UNION ALL ')
@population.definition.model.connection.select_all(
"WITH authorised AS (#{ basis }) " +
"WITH population_members AS (#{ basis }) " +
"SELECT /*+ MAX_EXECUTION_TIME(10000) */ * FROM (#{ sql }) totals").map do |record|
row_depth = record['row_depth'].to_i
column_depth = record['column_depth'].to_i