Class: ClickHouse::QueryBuilder

Inherits:
Client::QueryLike
  • Object
show all
Defined in:
lib/click_house/query_builder.rb

Constant Summary collapse

VALID_NODES =
[
  Arel::Nodes::In,
  Arel::Nodes::Equality,
  Arel::Nodes::LessThan,
  Arel::Nodes::LessThanOrEqual,
  Arel::Nodes::GreaterThan,
  Arel::Nodes::GreaterThanOrEqual
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(table_name) ⇒ QueryBuilder

Returns a new instance of QueryBuilder.



18
19
20
21
22
# File 'lib/click_house/query_builder.rb', line 18

def initialize(table_name)
  @table = Arel::Table.new(table_name)
  @manager = Arel::SelectManager.new(Arel::Table.engine).from(@table).project(Arel.star)
  @conditions = []
end

Instance Attribute Details

#conditionsObject

Returns the value of attribute conditions.



7
8
9
# File 'lib/click_house/query_builder.rb', line 7

def conditions
  @conditions
end

#managerObject

Returns the value of attribute manager.



7
8
9
# File 'lib/click_house/query_builder.rb', line 7

def manager
  @manager
end

#tableObject (readonly)

Returns the value of attribute table.



6
7
8
# File 'lib/click_house/query_builder.rb', line 6

def table
  @table
end

Instance Method Details

#limit(count) ⇒ Object



81
82
83
84
# File 'lib/click_house/query_builder.rb', line 81

def limit(count)
  manager.take(count)
  self
end

#offset(count) ⇒ Object



86
87
88
89
# File 'lib/click_house/query_builder.rb', line 86

def offset(count)
  manager.skip(count)
  self
end

#order(field, direction = :asc) ⇒ Object



70
71
72
73
74
75
76
77
78
79
# File 'lib/click_house/query_builder.rb', line 70

def order(field, direction = :asc)
  validate_order_direction!(direction)

  new_instance = deep_clone

  new_order = new_instance.table[field].public_send(direction.to_s.downcase) # rubocop:disable GitlabSecurity/PublicSend
  new_instance.manager.order(new_order)

  new_instance
end

#select(*fields) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/click_house/query_builder.rb', line 53

def select(*fields)
  new_instance = deep_clone

  existing_fields = new_instance.manager.projections.filter_map do |projection|
    if projection.is_a?(Arel::Attributes::Attribute)
      projection.name.to_s
    elsif projection.to_s == '*'
      nil
    end
  end

  new_projections = existing_fields + fields.map(&:to_s)

  new_instance.manager.projections = new_projections.uniq.map { |field| new_instance.table[field] }
  new_instance
end

#to_redacted_sql(bind_index_manager = ClickHouse::Client::BindIndexManager.new) ⇒ Object



96
97
98
# File 'lib/click_house/query_builder.rb', line 96

def to_redacted_sql(bind_index_manager = ClickHouse::Client::BindIndexManager.new)
  ::ClickHouse::Redactor.redact(self, bind_index_manager)
end

#to_sqlObject



91
92
93
94
# File 'lib/click_house/query_builder.rb', line 91

def to_sql
  apply_conditions!
  manager.to_sql
end

#where(conditions) ⇒ ClickHouse::QueryBuilder

The ‘where` method currently does only supports IN and equal to queries along with above listed VALID_NODES. For example, using a range (start_date..end_date) will result in incorrect SQL. If you need to query a range, use greater than and less than conditions with Arel.

Correct usage:

query.where(query.table[:created_at].lteq(Date.today)).to_sql
"SELECT * FROM \"table\" WHERE \"table\".\"created_at\" <= '2023-08-01'"

This also supports array conditions which will result in an IN query.

query.where(entity_id: [1,2,3]).to_sql
"SELECT * FROM \"table\" WHERE \"table\".\"entity_id\" IN (1, 2, 3)"

Range support and more ‘Arel::Nodes` could be considered for future iterations.

Returns:



39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/click_house/query_builder.rb', line 39

def where(conditions)
  validate_condition_type!(conditions)

  new_instance = deep_clone

  if conditions.is_a?(Arel::Nodes::Node)
    new_instance.conditions << conditions
  else
    add_conditions_to(new_instance, conditions)
  end

  new_instance
end