Class: QueryBuilder::Query
- Inherits:
-
Object
- Object
- QueryBuilder::Query
- Defined in:
- lib/query_builder/query.rb
Constant Summary collapse
- SELECT_WITH_TYPE_REGEX =
/^(.*):(.*)$/
Instance Attribute Summary collapse
-
#attributes_alias ⇒ Object
Returns the value of attribute attributes_alias.
-
#context ⇒ Object
Returns the value of attribute context.
-
#distinct ⇒ Object
Returns the value of attribute distinct.
-
#error ⇒ Object
Returns the value of attribute error.
-
#group ⇒ Object
Returns the value of attribute group.
-
#having ⇒ Object
Returns the value of attribute having.
-
#key_value_tables ⇒ Object
Returns the value of attribute key_value_tables.
-
#limit ⇒ Object
Returns the value of attribute limit.
-
#main_class ⇒ Object
Return the class of resulting objects (different from default_class if the value has been changed by the query building process).
-
#offset ⇒ Object
Returns the value of attribute offset.
-
#order ⇒ Object
Returns the value of attribute order.
-
#page_size ⇒ Object
Returns the value of attribute page_size.
-
#pagination_key ⇒ Object
Returns the value of attribute pagination_key.
-
#processor_class ⇒ Object
Returns the value of attribute processor_class.
-
#select ⇒ Object
Returns the value of attribute select.
-
#table_alias ⇒ Object
Returns the value of attribute table_alias.
-
#tables ⇒ Object
Returns the value of attribute tables.
-
#types ⇒ Object
Returns the value of attribute types.
-
#unique_alias ⇒ Object
Returns the value of attribute unique_alias.
-
#where ⇒ Object
Returns the value of attribute where.
Class Method Summary collapse
Instance Method Summary collapse
- #add_filter(filter) ⇒ Object
-
#add_key_value_table(use_name, index_table, key, &block) ⇒ Object
Add a table to ‘import’ a key/value based field.
- #add_select(field, fname) ⇒ Object
-
#add_table(use_name, table_name = nil, avoid_alias = true, type = nil, &block) ⇒ Object
‘avoid_alias’ is used when parsing the last element so that it takes the real table name (nodes, not no1).
-
#default_class ⇒ Object
Return the default class of resulting objects (usually the base class).
-
#dup ⇒ Object
Duplicate query, avoiding sharing some arrays and hash.
- #filter ⇒ Object
-
#initialize(processor_class) ⇒ Query
constructor
A new instance of Query.
- #main_table ⇒ Object
- #master_class(after_class = ActiveRecord::Base) ⇒ Object
-
#needs_join_table(table_name1, type, table_name2, clause, join_name = nil) ⇒ Object
Use this method to add a join to another table (added only once for each join name).
- #quote_column_name(name) ⇒ Object
- #rebuild_attributes_hash! ⇒ Object
-
#rebuild_tables! ⇒ Object
Used after setting @tables from custom query.
-
#select_keys ⇒ Object
Return all explicit selected keys For example, sql such as “SELECT form.*, MAX(form.date) AS last_date” would provice ‘last_date’ key.
-
#sql(bindings, type = :find) ⇒ Object
Convert the query object into an SQL query.
- #table(table_name = main_table, index = 0) ⇒ Object
-
#to_s(type = :find) ⇒ Object
Convert query object to a string.
Constructor Details
#initialize(processor_class) ⇒ Query
Returns a new instance of Query.
16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/query_builder/query.rb', line 16 def initialize(processor_class) @processor_class = processor_class @tables = [] @table_alias = {} @unique_alias = {} @join_tables = {} @needed_join_tables = {} @attributes_alias = {} # Custom select foo as bar:time or 'types:' field in custom query. @types = {} @key_value_tables = {} @where = [] end |
Instance Attribute Details
#attributes_alias ⇒ Object
Returns the value of attribute attributes_alias.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def attributes_alias @attributes_alias end |
#context ⇒ Object
Returns the value of attribute context.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def context @context end |
#distinct ⇒ Object
Returns the value of attribute distinct.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def distinct @distinct end |
#error ⇒ Object
Returns the value of attribute error.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def error @error end |
#group ⇒ Object
Returns the value of attribute group.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def group @group end |
#having ⇒ Object
Returns the value of attribute having.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def having @having end |
#key_value_tables ⇒ Object
Returns the value of attribute key_value_tables.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def key_value_tables @key_value_tables end |
#limit ⇒ Object
Returns the value of attribute limit.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def limit @limit end |
#main_class ⇒ Object
Return the class of resulting objects (different from default_class if the value has been changed by the query building process).
37 38 39 |
# File 'lib/query_builder/query.rb', line 37 def main_class @main_class end |
#offset ⇒ Object
Returns the value of attribute offset.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def offset @offset end |
#order ⇒ Object
Returns the value of attribute order.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def order @order end |
#page_size ⇒ Object
Returns the value of attribute page_size.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def page_size @page_size end |
#pagination_key ⇒ Object
Returns the value of attribute pagination_key.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def pagination_key @pagination_key end |
#processor_class ⇒ Object
Returns the value of attribute processor_class.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def processor_class @processor_class end |
#select ⇒ Object
Returns the value of attribute select.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def select @select end |
#table_alias ⇒ Object
Returns the value of attribute table_alias.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def table_alias @table_alias end |
#tables ⇒ Object
Returns the value of attribute tables.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def tables @tables end |
#types ⇒ Object
Returns the value of attribute types.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def types @types end |
#unique_alias ⇒ Object
Returns the value of attribute unique_alias.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def unique_alias @unique_alias end |
#where ⇒ Object
Returns the value of attribute where.
6 7 8 |
# File 'lib/query_builder/query.rb', line 6 def where @where end |
Class Method Details
.adapter ⇒ Object
11 12 13 |
# File 'lib/query_builder/query.rb', line 11 def adapter @adapter ||= ActiveRecord::Base.connection.class.name.split('::').last[/(.+)Adapter/,1].downcase end |
Instance Method Details
#add_filter(filter) ⇒ Object
59 60 61 |
# File 'lib/query_builder/query.rb', line 59 def add_filter(filter) @where << filter end |
#add_key_value_table(use_name, index_table, key, &block) ⇒ Object
Add a table to ‘import’ a key/value based field. This method ensures that a given field is only included once for each context.
130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/query_builder/query.rb', line 130 def add_key_value_table(use_name, index_table, key, &block) key_tables = (@key_value_tables[table] ||= {}) key_table = (key_tables[use_name] ||= {}) if alias_table = key_table[key] # done, the index_table has been used for the given key in the current context alias_table else # insert the new table # Let caller configure the filter with &block. key_table[key] = add_table(use_name + "_#{key}", index_table, false, :left, &block) end end |
#add_select(field, fname) ⇒ Object
143 144 145 146 147 148 149 150 151 |
# File 'lib/query_builder/query.rb', line 143 def add_select(field, fname) if fname =~ SELECT_WITH_TYPE_REGEX fname, type = $1, $2 @types[fname] = type.to_sym end @select ||= ["#{main_table}.*"] @select << "#{field} AS #{quote_column_name(fname)}" @attributes_alias[fname] = field end |
#add_table(use_name, table_name = nil, avoid_alias = true, type = nil, &block) ⇒ Object
‘avoid_alias’ is used when parsing the last element so that it takes the real table name (nodes, not no1). We need this because we can use ‘OR’ between parts and we thus need the same table reference.
123 124 125 126 |
# File 'lib/query_builder/query.rb', line 123 def add_table(use_name, table_name = nil, avoid_alias = true, type = nil, &block) alias_name = get_alias(use_name, table_name, avoid_alias) add_alias_to_tables(table_name || use_name, alias_name, type, &block) end |
#default_class ⇒ Object
Return the default class of resulting objects (usually the base class).
52 53 54 55 56 57 |
# File 'lib/query_builder/query.rb', line 52 def default_class @default_class ||= begin klass = @processor_class.main_class QueryBuilder.resolve_const(klass) end end |
#dup ⇒ Object
Duplicate query, avoiding sharing some arrays and hash
179 180 181 182 183 184 185 |
# File 'lib/query_builder/query.rb', line 179 def dup other = super %w{tables table_alias unique_alias where tables key_value_tables}.each do |k| other.send("#{k}=", other.send(k).dup) end other end |
#filter ⇒ Object
220 221 222 |
# File 'lib/query_builder/query.rb', line 220 def filter @where.reverse.join(' AND ') end |
#main_table ⇒ Object
30 31 32 33 |
# File 'lib/query_builder/query.rb', line 30 def main_table # @main_table is only used in custom queries @main_table || processor_class.main_table end |
#master_class(after_class = ActiveRecord::Base) ⇒ Object
41 42 43 44 45 46 47 48 49 |
# File 'lib/query_builder/query.rb', line 41 def master_class(after_class = ActiveRecord::Base) klass = main_class klass = klass.first if klass.kind_of?(Array) begin up = klass.superclass return klass if up == after_class end while klass = up return main_class end |
#needs_join_table(table_name1, type, table_name2, clause, join_name = nil) ⇒ Object
Use this method to add a join to another table (added only once for each join name). nodes JOIN idx_nodes_string AS id1 ON … FIXME: can we remove this ? It seems buggy (JOIN in or clauses)
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/query_builder/query.rb', line 160 def needs_join_table(table_name1, type, table_name2, clause, join_name = nil) join_name ||= "#{table_name1}=#{type}=#{table_name2}" @needed_join_tables[join_name] ||= {} @needed_join_tables[join_name][table] ||= begin # define join for this part ('table' = unique for each part) # don't add to list of tables, just get unique alias name second_table = get_alias(table_name2) # create join first_table = table(table_name1) @join_tables[first_table] ||= [] @join_tables[first_table] << "#{type} JOIN #{second_table} ON #{clause.gsub('TABLE1',first_table).gsub('TABLE2',second_table)}" second_table end end |
#quote_column_name(name) ⇒ Object
224 225 226 |
# File 'lib/query_builder/query.rb', line 224 def quote_column_name(name) connection.quote_column_name(name) end |
#rebuild_attributes_hash! ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/query_builder/query.rb', line 201 def rebuild_attributes_hash! @attributes_alias = {} (@select || []).each do |field| if field =~ %r{\A(.*)\s+AS\s+(.+)\Z}i key, value = $2, $1 if key =~ /('|"|`)(.*)\1/ # TODO: is this clean enough unquoting ? key = $2 end @attributes_alias[key] = value elsif field =~ %r{^(\w+\.|)([^\*]+)$} @attributes_alias[$2] = field end end # Force rebuild @select_keys = nil end |
#rebuild_tables! ⇒ Object
Used after setting @tables from custom query.
188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/query_builder/query.rb', line 188 def rebuild_tables! @table_alias = {} @tables.each do |t| if t =~ /\A(.+)\s+AS\s+(.+)\Z/ base, use_name = $1, $2 else base = use_name = t end @table_alias[base] ||= [] @table_alias[base] << use_name end end |
#select_keys ⇒ Object
Return all explicit selected keys For example, sql such as “SELECT form.*, MAX(form.date) AS last_date” would provice ‘last_date’ key.
65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/query_builder/query.rb', line 65 def select_keys @select_keys ||= begin keys = @attributes_alias.keys.compact # When rebuilding select_keys, we rebuild @types keys.each do |k| # Default type is string @types[k] ||= :string end keys end end |
#sql(bindings, type = :find) ⇒ Object
Convert the query object into an SQL query.
Parameters
- bindings<Binding>
-
Binding context in which to evaluate bind clauses (query arguments).
- type<Symbol>
-
Type of SQL query (:find or :count)
Returns
- NilClass
-
If the query is not valid and “ignore_warnings” was not set to true during initialize.
- String
-
An SQL query, ready for execution (no more bind variables).
Examples
query.sql(binding)
> “SELECT objects.* FROM objects WHERE objects.project_id = 12489”
query.sql(bindings, :count)
> “SELECT COUNT(*) FROM objects WHERE objects.project_id = 12489”
116 117 118 119 |
# File 'lib/query_builder/query.rb', line 116 def sql(bindings, type = :find) statement, bind_values = build_statement(type) statement.gsub('?') { eval_bound_value(bind_values.shift, connection, bindings) } end |
#table(table_name = main_table, index = 0) ⇒ Object
153 154 155 |
# File 'lib/query_builder/query.rb', line 153 def table(table_name = main_table, index = 0) @table_alias[table_name] ? @table_alias[table_name][index - 1] : nil end |
#to_s(type = :find) ⇒ Object
Convert query object to a string. This string should then be evaluated.
Parameters
- type<Symbol>
-
Type of query to build (:find or :count).
Returns
- NilClass
-
If the query is not valid and “ignore_warnings” was not set to true during initialize.
- String
-
A string representing the query with its bind parameters.
Examples
query.to_s
> “[%Qobjects.* FROM objects WHERE objects.project_id = ?, project_id]”
DummyQuery.new(“nodes in site”).to_s
> “%Qobjects.* FROM objects”
query.to_s(:count)
> “[%QCOUNT(*) FROM objects WHERE objects.project_id = ?, project_id]”
95 96 97 98 |
# File 'lib/query_builder/query.rb', line 95 def to_s(type = :find) statement, bind_values = build_statement(type) bind_values.empty? ? "%Q{#{statement}}" : "[#{[["%Q{#{statement}}"] + bind_values].join(', ')}]" end |