Class: Lafcadio::Query
- Inherits:
-
Object
- Object
- Lafcadio::Query
- Defined in:
- lib/lafcadio/query.rb
Direct Known Subclasses
Defined Under Namespace
Modules: DomainObjectImpostor Classes: Compare, CompoundCondition, Condition, Equals, In, Include, Inferrer, Like, Max, Not, ObjectFieldImpostor
Instance Attribute Summary collapse
-
#condition ⇒ Object
readonly
Returns the value of attribute condition.
-
#domain_class ⇒ Object
readonly
Returns the value of attribute domain_class.
-
#include ⇒ Object
readonly
Returns the value of attribute include.
-
#limit ⇒ Object
Returns the value of attribute limit.
-
#order_by ⇒ Object
Returns the value of attribute order_by.
-
#order_by_order ⇒ Object
Returns the value of attribute order_by_order.
Class Method Summary collapse
-
.And(*conditions) ⇒ Object
:nodoc:.
-
.infer(*args, &action) ⇒ Object
Infers a query from a block.
-
.Or(*conditions) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#and(&action) ⇒ Object
Returns a new query representing the condition of the current query and the new inferred query.
-
#collect(coll) ⇒ Object
:nodoc:.
-
#compound(comp_type, action) ⇒ Object
:nodoc:.
-
#dobj_satisfies?(dobj) ⇒ Boolean
:nodoc:.
-
#eql?(other) ⇒ Boolean
:nodoc:.
-
#fields ⇒ Object
:nodoc:.
-
#hash ⇒ Object
:nodoc:.
-
#implies?(other_query) ⇒ Boolean
:nodoc:.
-
#initialize(domain_class, opts = {}) ⇒ Query
constructor
:nodoc:.
-
#limit_clause(db) ⇒ Object
:nodoc:.
- #one_pk_id? ⇒ Boolean
-
#or(&action) ⇒ Object
Returns a new query representing the condition of the current query and the new inferred query.
- #order_and_limit_collection(objects) ⇒ Object
-
#order_clause ⇒ Object
:nodoc:.
-
#result_row(row) ⇒ Object
:nodoc:.
-
#sql_primary_key_field(domain_class) ⇒ Object
:nodoc:.
-
#tables ⇒ Object
:nodoc:.
- #to_sql(db = 'Mysql') ⇒ Object
-
#where_clause ⇒ Object
:nodoc:.
Constructor Details
#initialize(domain_class, opts = {}) ⇒ Query
:nodoc:
174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/lafcadio/query.rb', line 174 def initialize(domain_class, opts = {} ) #:nodoc: @domain_class, @opts = domain_class, opts ( @condition, @order_by, @limit ) = [ nil, nil, nil ] if ( cond = opts[:condition] ) @condition = cond elsif ( pk_id = opts[:pk_id] ) @condition = Query::Equals.new( :pk_id, pk_id, domain_class ) end if ( @include = opts[:include] ) @include = [ @include ] unless @include.is_a?( Array ) end @order_by_order = :asc end |
Instance Attribute Details
#condition ⇒ Object (readonly)
Returns the value of attribute condition.
171 172 173 |
# File 'lib/lafcadio/query.rb', line 171 def condition @condition end |
#domain_class ⇒ Object (readonly)
Returns the value of attribute domain_class.
171 172 173 |
# File 'lib/lafcadio/query.rb', line 171 def domain_class @domain_class end |
#include ⇒ Object (readonly)
Returns the value of attribute include.
171 172 173 |
# File 'lib/lafcadio/query.rb', line 171 def include @include end |
#limit ⇒ Object
Returns the value of attribute limit.
171 172 173 |
# File 'lib/lafcadio/query.rb', line 171 def limit @limit end |
#order_by ⇒ Object
Returns the value of attribute order_by.
171 172 173 |
# File 'lib/lafcadio/query.rb', line 171 def order_by @order_by end |
#order_by_order ⇒ Object
Returns the value of attribute order_by_order.
172 173 174 |
# File 'lib/lafcadio/query.rb', line 172 def order_by_order @order_by_order end |
Class Method Details
.And(*conditions) ⇒ Object
:nodoc:
144 145 146 |
# File 'lib/lafcadio/query.rb', line 144 def self.And( *conditions ) #:nodoc: CompoundCondition.new( *conditions ) end |
.infer(*args, &action) ⇒ Object
Infers a query from a block. The first required argument is the domain class. Other optional arguments should be passed in hash form:
- :order_by
-
An array of fields to order the results by.
- :order_by_order
-
Possible values are :asc or :desc. Defaults to :desc.
qry = Query.infer( User ) { |u| u.lname.equals( 'Hwang' ) }
qry.to_sql # => "select * from users where users.lname = 'Hwang'"
qry = Query.infer(
SKU,
:order_by => [ :standardPrice, :salePrice ],
:order_by_order => :desc
) { |s| s.sku.nil? }
qry.to_sql # => "select * from skus where skus.sku is null order by
standardPrice, salePrice desc"
161 162 163 164 |
# File 'lib/lafcadio/query.rb', line 161 def self.infer( *args, &action ) inferrer = Query::Inferrer.new( *args ) { |obj| action.call( obj ) } inferrer.execute end |
.Or(*conditions) ⇒ Object
:nodoc:
166 167 168 169 |
# File 'lib/lafcadio/query.rb', line 166 def self.Or( *conditions ) #:nodoc: conditions << :or CompoundCondition.new( *conditions) end |
Instance Method Details
#and(&action) ⇒ Object
Returns a new query representing the condition of the current query and the new inferred query.
qry = Query.infer( User ) { |u| u.lname.equals( 'Hwang' ) }
qry.to_sql # => "select * from users where users.lname = 'Hwang'"
qry = qry.and { |u| u.fname.equals( 'Francis' ) }
qry.to_sql # => "select * from users where (users.lname = 'Hwang' and
users.fname = 'Francis')"
195 |
# File 'lib/lafcadio/query.rb', line 195 def and( &action ); compound( :and, action ); end |
#collect(coll) ⇒ Object
:nodoc:
197 198 199 200 201 202 203 |
# File 'lib/lafcadio/query.rb', line 197 def collect( coll ) #:nodoc: if @opts[:group_functions] == [:count] [ result_row( [coll.size] ) ] else raise end end |
#compound(comp_type, action) ⇒ Object
:nodoc:
205 206 207 208 209 210 211 212 213 214 |
# File 'lib/lafcadio/query.rb', line 205 def compound( comp_type, action ) #:nodoc: rquery = Query.infer( @domain_class ) { |dobj| action.call( dobj ) } q = Query::CompoundCondition.new( @condition, rquery.condition, comp_type ).query [ :order_by, :order_by_order, :limit ].each do |attr| q.send( attr.to_s + '=', self.send( attr ) ) end q end |
#dobj_satisfies?(dobj) ⇒ Boolean
:nodoc:
216 217 218 |
# File 'lib/lafcadio/query.rb', line 216 def dobj_satisfies?( dobj ) #:nodoc: @condition.nil? or @condition.dobj_satisfies?( dobj ) end |
#eql?(other) ⇒ Boolean
:nodoc:
220 221 222 |
# File 'lib/lafcadio/query.rb', line 220 def eql?( other ) #:nodoc: other.is_a?( Query ) && other.to_sql == to_sql end |
#fields ⇒ Object
:nodoc:
224 225 226 |
# File 'lib/lafcadio/query.rb', line 224 def fields #:nodoc: @opts[:group_functions] == [:count] ? 'count(*)' : '*' end |
#hash ⇒ Object
:nodoc:
228 229 230 |
# File 'lib/lafcadio/query.rb', line 228 def hash #:nodoc: to_sql.hash end |
#implies?(other_query) ⇒ Boolean
:nodoc:
232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/lafcadio/query.rb', line 232 def implies?( other_query ) #:nodoc: if other_query == self true elsif @domain_class == other_query.domain_class if other_query.condition.nil? and !self.condition.nil? true else self.condition and self.condition.implies?( other_query.condition ) end end end |
#limit_clause(db) ⇒ Object
:nodoc:
248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/lafcadio/query.rb', line 248 def limit_clause( db ) #:nodoc: if @limit case db when 'Mysql' "limit #{ @limit.begin }, #{ @limit.end - @limit.begin + 1 }" when 'Pg' limit_clause = "limit #{ @limit.end - @limit.begin + 1 }" limit_clause += " offset #{ @limit.begin }" if @limit.begin > 0 limit_clause end end end |
#one_pk_id? ⇒ Boolean
261 |
# File 'lib/lafcadio/query.rb', line 261 def one_pk_id?; @condition and @condition.one_pk_id?; end |
#or(&action) ⇒ Object
Returns a new query representing the condition of the current query and the new inferred query.
qry = Query.infer( User ) { |u| u.lname.equals( 'Hwang' ) }
qry.to_sql # => "select * from users where users.lname = 'Hwang'"
qry = qry.or { |u| u.fname.equals( 'Francis' ) }
qry.to_sql # => "select * from users where (users.lname = 'Hwang' or
users.fname = 'Francis')"
270 |
# File 'lib/lafcadio/query.rb', line 270 def or( &action ); compound( :or, action ); end |
#order_and_limit_collection(objects) ⇒ Object
287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/lafcadio/query.rb', line 287 def order_and_limit_collection( objects ) objects = objects.sort_by { |dobj| if order_by.nil? dobj.pk_id elsif order_by.is_a?( Array ) order_by.map { |field_name| dobj.send( field_name ) } else dobj.send order_by end } objects.reverse! if order_by_order == :desc objects = objects[limit] if limit objects end |
#order_clause ⇒ Object
:nodoc:
276 277 278 279 280 281 282 283 284 285 |
# File 'lib/lafcadio/query.rb', line 276 def order_clause #:nodoc: if @order_by field_str = @order_by.map { |f_name| @domain_class.field( f_name.to_s ).db_field_name }.join( ', ' ) clause = "order by #{ field_str } " clause += @order_by_order == :asc ? 'asc' : 'desc' clause end end |
#result_row(row) ⇒ Object
:nodoc:
302 303 304 305 306 307 308 |
# File 'lib/lafcadio/query.rb', line 302 def result_row( row ) #:nodoc: if @opts[:group_functions] == [:count] { :count => row.first } else raise end end |
#sql_primary_key_field(domain_class) ⇒ Object
:nodoc:
310 311 312 |
# File 'lib/lafcadio/query.rb', line 310 def sql_primary_key_field(domain_class) #:nodoc: "#{ domain_class.table_name }.#{ domain_class.sql_primary_key_name }" end |
#tables ⇒ Object
:nodoc:
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/lafcadio/query.rb', line 314 def tables #:nodoc: concrete_classes = domain_class.self_and_concrete_superclasses.reverse sql = '' dclass = nil until concrete_classes.empty? prev_dclass = dclass dclass = concrete_classes.shift if sql == '' sql = dclass.table_name else sql += " inner join #{ dclass.table_name } on #{ sql_primary_key_field( prev_dclass ) } = #{ sql_primary_key_field( dclass ) }" end end if @include @include.each do |include_sym| field = dclass.field include_sym included_dclass = field.linked_type sql += " left outer join #{ included_dclass.table_name } on #{ dclass.table_name }.#{ field.db_field_name } = #{ sql_primary_key_field( included_dclass ) }" end end sql end |
#to_sql(db = 'Mysql') ⇒ Object
337 338 339 340 341 342 343 |
# File 'lib/lafcadio/query.rb', line 337 def to_sql( db = 'Mysql' ) clauses = [ "select #{ fields }", "from #{ tables }" ] clauses << where_clause if where_clause clauses << order_clause if order_clause clauses << limit_clause( db ) if limit_clause( db ) clauses.join ' ' end |
#where_clause ⇒ Object
:nodoc:
345 346 347 348 349 |
# File 'lib/lafcadio/query.rb', line 345 def where_clause #:nodoc: where_clauses = [] where_clauses << @condition.to_sql if @condition !where_clauses.empty? ? 'where ' + where_clauses.join( ' and ' ) : nil end |