Method: Og::SqlStore#resolve_options

Defined in:
lib/og/store/sql.rb

#resolve_options(klass, options) ⇒ Object

Resolve the finder options. Also takes scope into account. This method handles among other the following cases:

User.find :condition => “name LIKE ‘g%’”, :order => ‘name ASC’ User.find :where => “name LIKE ‘g%’”, :order => ‘name ASC’ User.find :sql => “WHERE name LIKE ‘g%’ ORDER BY name ASC” User.find :condition => [ ‘name LIKE ?’, ‘g%’ ], :order => ‘name ASC’, :limit => 10

If an array is passed as a condition, use prepared statement style escaping. For example:

User.find :condition => [ ‘name = ? AND age > ?’, ‘gmosx’, 12 ]

Proper escaping is performed to avoid SQL injection attacks. – FIXME: cleanup/refactor, this is an IMPORTANT method. ++



511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
# File 'lib/og/store/sql.rb', line 511

def resolve_options(klass, options)
  # Factor in scope.
  
  if scope = klass.get_scope
    scope = scope.dup
    scond = scope.delete(:condition)
    scope.update(options)
    options = scope
  end

  if sql = options[:sql]
    sql = "SELECT * FROM #{klass.table} " + sql unless sql =~ /SELECT/i
    return sql
  end

  tables = [klass::OGTABLE]

  if included = options[:include]
    join_conditions = []

    for name in [included].flatten
      if rel = klass.relation(name)
        target_table = rel[:target_class]::OGTABLE
        tables << target_table

        if rel.is_a?(JoinsMany)
          tables << rel[:join_table]
          owner_key, target_key = klass.ogmanager.store.join_table_keys(klass, rel[:target_class])
          join_conditions << "#{rel.join_table}.#{owner_key}=#{klass::OGTABLE}.#{rel.owner_class.primary_key} AND \
                              #{rel.join_table}.#{target_key}=#{rel.target_class::OGTABLE}.#{rel.target_class.primary_key}"
        else
          join_conditions << "#{klass::OGTABLE}.#{rel.foreign_key}=#{target_table}.#{rel.target_class.primary_key}"
        end
      else
        raise 'Unknown relation name'
      end
    end

    fields = tables.collect { |t| "#{t}.*" }.join(',')

    update_condition options, join_conditions.join(' AND ')
  elsif fields = options[:select]
    # query the provided fields.
  else
    fields = '*'
  end

  if join_table = options[:join_table]
    tables << join_table
    update_condition options, options[:join_condition]
  end

  # Factor in scope in the conditions.
  
  update_condition(options, scond) if scond

  # rp: type is not set in all instances such as Class.first 
  # so this fix goes here for now.
  
  if ogtype = options[:type] || (klass.schema_inheritance_child? ? "#{klass}" : nil)
    update_condition options, "ogtype='#{ogtype}'"
  end

  sql = "SELECT #{fields} FROM #{tables.join(',')}"

  if condition = options[:condition] || options[:where]
    # If an array is passed as a condition, use prepared 
    # statement style escaping. 
           
    if condition.is_a?(Array)
      condition = prepare_statement(condition)
    end

    sql << " WHERE #{condition}"
  end
  
  if group = options[:group] || options[:group_by]
    sql << " GROUP BY #{group}"
  end

  if order = options[:order] || options[:order_by]
    sql << " ORDER BY #{order}"
  end

  resolve_limit_options(options, sql)

  if extra = options[:extra] || options[:extra_sql]
    sql << " #{extra}"
  end

  return sql
end