Module: ActiveRecord::ConnectionAdapters::ClickHouse::RelationMethods

Defined in:
lib/active_record/connection_adapters/clickhouse/querying.rb

Overview

Relation methods for the ClickHouse query surface. Injected via extending (public Relation API) by ClickHouse::Querying — no reopens.

Constant Summary collapse

GROUP_BY_PERIODS =

toStartOfInterval buckets any period the server knows; grouping and ordering by the same expression makes .count come back as a chronological series.

%w[minute hour day week month quarter year].freeze

Instance Method Summary collapse

Instance Method Details

#array_join(*columns, left: false, as: nil) ⇒ Object

Unnests array columns into one row per element; as: names the element so the original array column stays addressable. left: true keeps empty-array rows.



108
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 108

def array_join(*columns, left: false, as: nil) = spawn.array_join!(*columns, left: left, as: as)

#array_join!(*columns, left: false, as: nil) ⇒ Object

Raises:

  • (ArgumentError)


110
111
112
113
114
115
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 110

def array_join!(*columns, left: false, as: nil)
  raise ArgumentError, "as: names a single element, so array_join takes one column with it" if
    as && columns.many?

  assign_clickhouse_dialect(array_join: { columns: columns.flatten, left: left, as: as })
end

#clickhouse_dialectObject



127
128
129
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 127

def clickhouse_dialect
  @clickhouse_dialect ||= {}
end

#fill(step: nil) ⇒ Object



100
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 100

def fill(step: nil) = spawn.fill!(step: step)

#fill!(step: nil) ⇒ Object



102
103
104
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 102

def fill!(step: nil)
  assign_clickhouse_dialect(fill: { step: fill_step_sql(step) })
end

#finalObject



52
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 52

def final = spawn.final!

#final!Object



54
55
56
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 54

def final!
  assign_clickhouse_dialect(final: true)
end

#group_by_period(period, column) ⇒ Object



87
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 87

def group_by_period(period, column) = spawn.group_by_period!(period, column)

#group_by_period!(period, column) ⇒ Object



89
90
91
92
93
94
95
96
97
98
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 89

def group_by_period!(period, column)
  unless GROUP_BY_PERIODS.include?(period.to_s)
    raise ArgumentError, "unknown period #{period.inspect}; use one of #{GROUP_BY_PERIODS.join(", ")}"
  end

  bucket = ::Arel::Nodes::NamedFunction.new(
    "toStartOfInterval", [klass.arel_table[column], ::Arel.sql("INTERVAL 1 #{period}")]
  )
  group!(bucket).order!(bucket)
end

#limit_by(count, *columns) ⇒ Object



77
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 77

def limit_by(count, *columns) = spawn.limit_by!(count, *columns)

#limit_by!(count, *columns) ⇒ Object



79
80
81
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 79

def limit_by!(count, *columns)
  assign_clickhouse_dialect(limit_by: [Integer(count), columns.flatten])
end

#prewhere(condition) ⇒ Object



64
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 64

def prewhere(condition) = spawn.prewhere!(condition)

#prewhere!(condition) ⇒ Object



66
67
68
69
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 66

def prewhere!(condition)
  sanitized = klass.send(:sanitize_sql_for_conditions, condition)
  assign_clickhouse_dialect(prewhere: [*clickhouse_dialect[:prewhere], sanitized])
end

#rollupObject

ClickHouse renders WITH TOTALS out-of-band, which the row-stream wire format drops (probed 2026-07-13) — ROLLUP delivers totals as ordinary rows instead, keyed nil thanks to group_by_use_nulls.



120
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 120

def rollup = spawn.rollup!

#rollup!Object



122
123
124
125
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 122

def rollup!
  settings!(group_by_use_nulls: 1)
  assign_clickhouse_dialect(rollup: true)
end

#sample(fraction) ⇒ Object



58
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 58

def sample(fraction) = spawn.sample!(fraction)

#sample!(fraction) ⇒ Object



60
61
62
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 60

def sample!(fraction)
  assign_clickhouse_dialect(sample: Float(fraction))
end

#settings(values) ⇒ Object



71
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 71

def settings(values) = spawn.settings!(values)

#settings!(values) ⇒ Object



73
74
75
# File 'lib/active_record/connection_adapters/clickhouse/querying.rb', line 73

def settings!(values)
  assign_clickhouse_dialect(settings: (clickhouse_dialect[:settings] || {}).merge(values))
end