Class: SimpleQuery::Builder
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#avg(column, alias_name: nil) ⇒ Object
-
#build_query ⇒ Object
-
#bulk_update(set:) ⇒ Object
-
#count(column = nil, alias_name: nil) ⇒ Object
-
#custom_aggregation(expression, alias_name) ⇒ Object
-
#distinct ⇒ Object
-
#execute ⇒ Object
-
#first_by(column, alias_name: nil) ⇒ Object
Method to get first/top record by column.
-
#full_join(table1, table2, foreign_key:, primary_key:) ⇒ Object
-
#group(*fields) ⇒ Object
-
#group_concat(column, separator: ",", alias_name: nil) ⇒ Object
-
#having(condition) ⇒ Object
-
#initialize(source) ⇒ Builder
constructor
A new instance of Builder.
-
#join(table1, table2, foreign_key:, primary_key:, type: :inner) ⇒ Object
-
#last_by(column, alias_name: nil) ⇒ Object
Method to get last/bottom record by column.
-
#lazy_execute ⇒ Object
-
#left_join(table1, table2, foreign_key:, primary_key:) ⇒ Object
-
#limit(number) ⇒ Object
-
#map_to(klass) ⇒ Object
-
#max(column, alias_name: nil) ⇒ Object
-
#min(column, alias_name: nil) ⇒ Object
-
#offset(number) ⇒ Object
-
#order(order_conditions) ⇒ Object
-
#percentage_of_total(column, alias_name: nil) ⇒ Object
-
#right_join(table1, table2, foreign_key:, primary_key:) ⇒ Object
-
#select(*fields) ⇒ Object
-
#stats(column, alias_prefix: nil) ⇒ Object
-
#stddev(column, alias_name: nil) ⇒ Object
-
#stream_each(batch_size: 1000, &block) ⇒ Object
-
#sum(column, alias_name: nil) ⇒ Object
-
#total_count(alias_name: "total") ⇒ Object
Convenience methods for common aggregation patterns.
-
#variance(column, alias_name: nil) ⇒ Object
-
#where(condition) ⇒ Object
#stream_each_mysql
#stream_each_postgres
Constructor Details
#initialize(source) ⇒ Builder
Returns a new instance of Builder.
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
395
396
397
398
399
400
401
402
|
# File 'lib/simple_query/builder.rb', line 395
def method_missing(method_name, *args, &block)
if (scope_block = find_scope(method_name))
instance_exec(*args, &scope_block)
self
else
super
end
end
|
Instance Attribute Details
#arel_table ⇒ Object
Returns the value of attribute arel_table.
8
9
10
|
# File 'lib/simple_query/builder.rb', line 8
def arel_table
@arel_table
end
|
#model ⇒ Object
Returns the value of attribute model.
8
9
10
|
# File 'lib/simple_query/builder.rb', line 8
def model
@model
end
|
Instance Method Details
#avg(column, alias_name: nil) ⇒ Object
108
109
110
111
112
|
# File 'lib/simple_query/builder.rb', line 108
def avg(column, alias_name: nil)
@aggregations.avg(column, alias_name: alias_name)
reset_query
self
end
|
#build_query ⇒ Object
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
|
# File 'lib/simple_query/builder.rb', line 236
def build_query
return @query if @query_built
@query = Arel::SelectManager.new(Arel::Table.engine)
@query.from(@arel_table)
all_selects = build_select_expressions
@query.project(*all_selects)
apply_distinct
apply_where_conditions
apply_joins
apply_group_and_having
apply_order_conditions
apply_limit_and_offset
@query_built = true
@query
end
|
#bulk_update(set:) ⇒ Object
193
194
195
196
197
198
199
200
201
202
203
204
|
# File 'lib/simple_query/builder.rb', line 193
def bulk_update(set:)
table_name = @arel_table.name
set_sql = SetClause.new(set).to_sql
raise ArgumentError, "No columns to update" if set_sql.empty?
where_sql = build_where_sql
sql = "UPDATE #{table_name} SET #{set_sql}"
sql += " WHERE #{where_sql}" unless where_sql.nil? || where_sql.empty?
ActiveRecord::Base.connection.execute(sql)
end
|
#count(column = nil, alias_name: nil) ⇒ Object
96
97
98
99
100
|
# File 'lib/simple_query/builder.rb', line 96
def count(column = nil, alias_name: nil)
@aggregations.count(column, alias_name: alias_name)
reset_query
self
end
|
#custom_aggregation(expression, alias_name) ⇒ Object
144
145
146
147
148
|
# File 'lib/simple_query/builder.rb', line 144
def custom_aggregation(expression, alias_name)
@aggregations.custom(expression, alias_name)
reset_query
self
end
|
#distinct ⇒ Object
77
78
79
80
81
|
# File 'lib/simple_query/builder.rb', line 77
def distinct
@distinct_flag.set_distinct
reset_query
self
end
|
#execute ⇒ Object
217
218
219
220
|
# File 'lib/simple_query/builder.rb', line 217
def execute
records = ActiveRecord::Base.connection.select_all(cached_sql)
build_result_objects_from_rows(records)
end
|
#first_by(column, alias_name: nil) ⇒ Object
Method to get first/top record by column
166
167
168
169
170
|
# File 'lib/simple_query/builder.rb', line 166
def first_by(column, alias_name: nil)
alias_name ||= "first_#{column}"
custom_aggregation("FIRST_VALUE(#{resolve_column_name(column)}) OVER (ORDER BY #{resolve_column_name(column)})",
alias_name)
end
|
#full_join(table1, table2, foreign_key:, primary_key:) ⇒ Object
55
56
57
|
# File 'lib/simple_query/builder.rb', line 55
def full_join(table1, table2, foreign_key:, primary_key:)
join(table1, table2, foreign_key: foreign_key, primary_key: primary_key, type: :full)
end
|
#group(*fields) ⇒ Object
83
84
85
86
87
|
# File 'lib/simple_query/builder.rb', line 83
def group(*fields)
@group_having.add_group(*fields)
reset_query
self
end
|
#group_concat(column, separator: ",", alias_name: nil) ⇒ Object
138
139
140
141
142
|
# File 'lib/simple_query/builder.rb', line 138
def group_concat(column, separator: ",", alias_name: nil)
@aggregations.group_concat(column, separator: separator, alias_name: alias_name)
reset_query
self
end
|
#having(condition) ⇒ Object
89
90
91
92
93
|
# File 'lib/simple_query/builder.rb', line 89
def having(condition)
@group_having.add_having(condition)
reset_query
self
end
|
#join(table1, table2, foreign_key:, primary_key:, type: :inner) ⇒ Object
41
42
43
44
45
|
# File 'lib/simple_query/builder.rb', line 41
def join(table1, table2, foreign_key:, primary_key:, type: :inner)
@joins.add(table1, table2, foreign_key: foreign_key, primary_key: primary_key, join_type: type)
reset_query
self
end
|
#last_by(column, alias_name: nil) ⇒ Object
Method to get last/bottom record by column
173
174
175
176
177
|
# File 'lib/simple_query/builder.rb', line 173
def last_by(column, alias_name: nil)
alias_name ||= "last_#{column}"
custom_aggregation("LAST_VALUE(#{resolve_column_name(column)}) OVER (ORDER BY #{resolve_column_name(column)})",
alias_name)
end
|
#lazy_execute ⇒ Object
222
223
224
225
226
227
228
229
230
231
232
233
234
|
# File 'lib/simple_query/builder.rb', line 222
def lazy_execute
Enumerator.new do |yielder|
records = ActiveRecord::Base.connection.select_all(cached_sql)
if @read_model_class
build_read_models_enumerator(records, yielder)
else
struct = result_struct(records.columns)
records.rows.each do |row_array|
yielder << struct.new(*row_array)
end
end
end
end
|
#left_join(table1, table2, foreign_key:, primary_key:) ⇒ Object
47
48
49
|
# File 'lib/simple_query/builder.rb', line 47
def left_join(table1, table2, foreign_key:, primary_key:)
join(table1, table2, foreign_key: foreign_key, primary_key: primary_key, type: :left)
end
|
#limit(number) ⇒ Object
65
66
67
68
69
|
# File 'lib/simple_query/builder.rb', line 65
def limit(number)
@limits.with_limit(number)
reset_query
self
end
|
#map_to(klass) ⇒ Object
187
188
189
190
191
|
# File 'lib/simple_query/builder.rb', line 187
def map_to(klass)
@read_model_class = klass
reset_query
self
end
|
#max(column, alias_name: nil) ⇒ Object
120
121
122
123
124
|
# File 'lib/simple_query/builder.rb', line 120
def max(column, alias_name: nil)
@aggregations.max(column, alias_name: alias_name)
reset_query
self
end
|
#min(column, alias_name: nil) ⇒ Object
114
115
116
117
118
|
# File 'lib/simple_query/builder.rb', line 114
def min(column, alias_name: nil)
@aggregations.min(column, alias_name: alias_name)
reset_query
self
end
|
#offset(number) ⇒ Object
71
72
73
74
75
|
# File 'lib/simple_query/builder.rb', line 71
def offset(number)
@limits.with_offset(number)
reset_query
self
end
|
#order(order_conditions) ⇒ Object
59
60
61
62
63
|
# File 'lib/simple_query/builder.rb', line 59
def order(order_conditions)
@orders.add(order_conditions)
reset_query
self
end
|
#percentage_of_total(column, alias_name: nil) ⇒ Object
180
181
182
183
184
185
|
# File 'lib/simple_query/builder.rb', line 180
def percentage_of_total(column, alias_name: nil)
alias_name ||= "#{column}_percentage"
column_expr = resolve_column_name(column)
expression = "ROUND((#{column_expr} * 100.0 / SUM(#{column_expr}) OVER ()), 2)"
custom_aggregation(expression, alias_name)
end
|
#right_join(table1, table2, foreign_key:, primary_key:) ⇒ Object
51
52
53
|
# File 'lib/simple_query/builder.rb', line 51
def right_join(table1, table2, foreign_key:, primary_key:)
join(table1, table2, foreign_key: foreign_key, primary_key: primary_key, type: :right)
end
|
#select(*fields) ⇒ Object
29
30
31
32
33
|
# File 'lib/simple_query/builder.rb', line 29
def select(*fields)
@selects.concat(fields.map { |field| parse_select_field(field) })
reset_query
self
end
|
#stats(column, alias_prefix: nil) ⇒ Object
155
156
157
158
159
160
161
162
163
|
# File 'lib/simple_query/builder.rb', line 155
def stats(column, alias_prefix: nil)
prefix = alias_prefix || column.to_s
count(alias_name: "#{prefix}_count")
sum(column, alias_name: "#{prefix}_sum")
avg(column, alias_name: "#{prefix}_avg")
min(column, alias_name: "#{prefix}_min")
max(column, alias_name: "#{prefix}_max")
self
end
|
#stddev(column, alias_name: nil) ⇒ Object
132
133
134
135
136
|
# File 'lib/simple_query/builder.rb', line 132
def stddev(column, alias_name: nil)
@aggregations.stddev(column, alias_name: alias_name)
reset_query
self
end
|
#stream_each(batch_size: 1000, &block) ⇒ Object
206
207
208
209
210
211
212
213
214
215
|
# File 'lib/simple_query/builder.rb', line 206
def stream_each(batch_size: 1000, &block)
adapter = ActiveRecord::Base.connection.adapter_name.downcase
if adapter.include?("postgres")
stream_each_postgres(batch_size, &block)
elsif adapter.include?("mysql")
stream_each_mysql(&block)
else
raise "stream_each is only implemented for Postgres and MySQL."
end
end
|
#sum(column, alias_name: nil) ⇒ Object
102
103
104
105
106
|
# File 'lib/simple_query/builder.rb', line 102
def sum(column, alias_name: nil)
@aggregations.sum(column, alias_name: alias_name)
reset_query
self
end
|
#total_count(alias_name: "total") ⇒ Object
Convenience methods for common aggregation patterns
151
152
153
|
# File 'lib/simple_query/builder.rb', line 151
def total_count(alias_name: "total")
count(alias_name: alias_name)
end
|
#variance(column, alias_name: nil) ⇒ Object
126
127
128
129
130
|
# File 'lib/simple_query/builder.rb', line 126
def variance(column, alias_name: nil)
@aggregations.variance(column, alias_name: alias_name)
reset_query
self
end
|
#where(condition) ⇒ Object
35
36
37
38
39
|
# File 'lib/simple_query/builder.rb', line 35
def where(condition)
@wheres.add(condition)
reset_query
self
end
|