Module: CoreExtensions::ActiveRecord::Relation

Defined in:
lib/core_extensions/active_record/relation.rb

Instance Method Summary collapse

Instance Method Details

#finalObject

When FINAL is specified, ClickHouse fully merges the data before returning the result and thus performs all data transformations that happen during merges for the given table engine. For example:

users = User.final.all
# SELECT users.* FROM users FINAL

An ActiveRecord::ActiveRecordError will be raised if database not ClickHouse.



40
41
42
# File 'lib/core_extensions/active_record/relation.rb', line 40

def final
  spawn.final!
end

#final!Object



44
45
46
47
48
# File 'lib/core_extensions/active_record/relation.rb', line 44

def final!
  check_command('FINAL')
  @values[:final] = true
  self
end

#group_by_grouping_sets(*grouping_sets) ⇒ Object

GROUPING SETS allows you to specify multiple groupings in the GROUP BY clause. Whereas GROUP BY CUBE generates all possible groupings, GROUP BY GROUPING SETS generates only the specified groupings. For example:

users = User.group_by_grouping_sets([], [:name], [:name, :age]).select(:name, :age, 'count(*)')
# SELECT name, age, count(*) FROM users GROUP BY GROUPING SETS ( (), (name), (name, age) )

which is generally equivalent to:

# SELECT NULL, NULL, count(*) FROM users
# UNION ALL
# SELECT name, NULL, count(*) FROM users GROUP BY name
# UNION ALL
# SELECT name, age, count(*) FROM users GROUP BY name, age

Raises ArgumentError if no grouping sets are specified are provided.

Raises:

  • (ArgumentError)


65
66
67
68
69
# File 'lib/core_extensions/active_record/relation.rb', line 65

def group_by_grouping_sets(*grouping_sets)
  raise ArgumentError, 'The method .group_by_grouping_sets() must contain arguments.' if grouping_sets.blank?

  spawn.group_by_grouping_sets!(*grouping_sets)
end

#group_by_grouping_sets!(*grouping_sets) ⇒ Object

:nodoc:



71
72
73
74
75
# File 'lib/core_extensions/active_record/relation.rb', line 71

def group_by_grouping_sets!(*grouping_sets) # :nodoc:
  grouping_sets = grouping_sets.map { |set| arel_columns(set) }
  self.group_values += [::Arel::Nodes::GroupingSets.new(grouping_sets)]
  self
end

#limit_by(*opts) ⇒ Object

The LIMIT BY clause permit to improve deduplication based on a unique key, it has better performances than the GROUP BY clause

users = User.limit_by(1, id)
# SELECT users.* FROM users LIMIT 1 BY id

An ActiveRecord::ActiveRecordError will be reaised if database is not Clickhouse.

Parameters:

  • opts (Array)


119
120
121
# File 'lib/core_extensions/active_record/relation.rb', line 119

def limit_by(*opts)
  spawn.limit_by!(*opts)
end

#limit_by!(*opts) ⇒ Object

Parameters:

  • opts (Array)


124
125
126
127
# File 'lib/core_extensions/active_record/relation.rb', line 124

def limit_by!(*opts)
  @values[:limit_by] = *opts
  self
end

#reverse_order!Object



4
5
6
7
8
9
10
11
12
# File 'lib/core_extensions/active_record/relation.rb', line 4

def reverse_order!
  return super unless connection.is_a?(::ActiveRecord::ConnectionAdapters::ClickhouseAdapter)

  orders = order_values.uniq.reject(&:blank?)
  return super unless orders.empty? && !primary_key

  self.order_values = (column_names & %w[date created_at]).map { |c| arel_table[c].desc }
  self
end

#settings(**opts) ⇒ Object

Define settings in the SETTINGS clause of the SELECT query. The setting value is applied only to that query and is reset to the default or previous value after the query is executed. For example:

users = User.settings(optimize_read_in_order: 1, cast_keep_nullable: 1).where(name: 'John')
# SELECT users.* FROM users WHERE users.name = 'John' SETTINGS optimize_read_in_order = 1, cast_keep_nullable = 1

An ActiveRecord::ActiveRecordError will be raised if database not ClickHouse.

Parameters:

  • opts (Hash)


22
23
24
# File 'lib/core_extensions/active_record/relation.rb', line 22

def settings(**opts)
  spawn.settings!(**opts)
end

#settings!(**opts) ⇒ Object

Parameters:

  • opts (Hash)


27
28
29
30
31
# File 'lib/core_extensions/active_record/relation.rb', line 27

def settings!(**opts)
  check_command('SETTINGS')
  @values[:settings] = (@values[:settings] || {}).merge opts
  self
end

#using(*opts) ⇒ Object

The USING clause specifies one or more columns to join, which establishes the equality of these columns. For example:

users = User.joins(:joins).using(:event_name, :date)
# SELECT users.* FROM users INNER JOIN joins USING event_name,date

An ActiveRecord::ActiveRecordError will be raised if database not ClickHouse.

Parameters:

  • opts (Array)


84
85
86
# File 'lib/core_extensions/active_record/relation.rb', line 84

def using(*opts)
  spawn.using!(*opts)
end

#using!(*opts) ⇒ Object

Parameters:

  • opts (Array)


89
90
91
92
# File 'lib/core_extensions/active_record/relation.rb', line 89

def using!(*opts)
  @values[:using] = opts
  self
end

#window(name, **opts) ⇒ Object

Windows functions let you perform calculations across a set of rows that are related to the current row. For example:

users = User.window('x', order: 'date', partition: 'name', rows: 'UNBOUNDED PRECEDING').select('sum(value) OVER x')
# SELECT sum(value) OVER x FROM users WINDOW x AS (PARTITION BY name ORDER BY date ROWS UNBOUNDED PRECEDING)

Parameters:

  • name (String)
  • opts (Hash)


101
102
103
# File 'lib/core_extensions/active_record/relation.rb', line 101

def window(name, **opts)
  spawn.window!(name, **opts)
end

#window!(name, **opts) ⇒ Object



105
106
107
108
109
# File 'lib/core_extensions/active_record/relation.rb', line 105

def window!(name, **opts)
  @values[:windows] = [] unless @values[:windows]
  @values[:windows] << [name, opts]
  self
end