sunstone 5.1.0.4 → 5.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
 - data/.travis.yml +5 -13
 - data/ext/active_record/associations.rb +2 -7
 - data/ext/active_record/associations/collection_association.rb +25 -18
 - data/ext/active_record/attribute_methods.rb +19 -35
 - data/ext/active_record/finder_methods.rb +138 -90
 - data/ext/active_record/persistence.rb +16 -11
 - data/ext/active_record/relation.rb +7 -47
 - data/ext/active_record/relation/calculations.rb +5 -3
 - data/ext/active_record/relation/query_methods.rb +9 -0
 - data/ext/active_record/statement_cache.rb +4 -6
 - data/ext/active_record/transactions.rb +9 -19
 - data/ext/arel/nodes/select_statement.rb +26 -12
 - data/lib/active_record/connection_adapters/sunstone/database_statements.rb +76 -25
 - data/lib/active_record/connection_adapters/sunstone/type/json.rb +1 -1
 - data/lib/active_record/connection_adapters/sunstone_adapter.rb +2 -3
 - data/lib/arel/collectors/sunstone.rb +21 -19
 - data/lib/arel/visitors/sunstone.rb +4 -8
 - data/lib/sunstone.rb +2 -3
 - data/lib/sunstone/connection.rb +2 -2
 - data/lib/sunstone/exception.rb +8 -1
 - data/lib/sunstone/version.rb +1 -1
 - data/sunstone.gemspec +3 -3
 - data/test/active_record/associations/has_many_test.rb +30 -2
 - data/test/active_record/eager_loading_test.rb +10 -0
 - data/test/active_record/persistance_test.rb +7 -7
 - data/test/active_record/query/count_test.rb +13 -0
 - data/test/active_record/query_test.rb +6 -6
 - data/test/sunstone/connection/send_request_test.rb +1 -1
 - data/test/test_helper.rb +1 -1
 - metadata +9 -10
 - data/ext/active_record/associations/association.rb +0 -16
 - data/ext/active_record/batches.rb +0 -12
 
| 
         @@ -14,12 +14,14 @@ module ActiveRecord 
     | 
|
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
                private
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                def create_or_update(*args)
         
     | 
| 
      
 17 
     | 
    
         
            +
                def create_or_update(*args, &block)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  _raise_readonly_record_error if readonly?
         
     | 
| 
      
 19 
     | 
    
         
            +
                  return false if destroyed?
         
     | 
| 
      
 20 
     | 
    
         
            +
                  
         
     | 
| 
       18 
21 
     | 
    
         
             
                  @updating = new_record? ? :creating : :updating
         
     | 
| 
       19 
22 
     | 
    
         
             
                  Thread.current[:sunstone_updating_model] = self
         
     | 
| 
       20 
23 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                   
     | 
| 
       22 
     | 
    
         
            -
                  result = new_record? ? _create_record : _update_record(*args)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  result = new_record? ? _create_record(&block) : _update_record(*args, &block)
         
     | 
| 
       23 
25 
     | 
    
         | 
| 
       24 
26 
     | 
    
         
             
                  if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && result != 0
         
     | 
| 
       25 
27 
     | 
    
         
             
                    row_hash = result.rows.first
         
     | 
| 
         @@ -61,9 +63,10 @@ module ActiveRecord 
     | 
|
| 
       61 
63 
     | 
    
         
             
                # Creates a record with values matching those of the instance attributes
         
     | 
| 
       62 
64 
     | 
    
         
             
                # and returns its id.
         
     | 
| 
       63 
65 
     | 
    
         
             
                def _create_record(attribute_names = self.attribute_names)
         
     | 
| 
       64 
     | 
    
         
            -
                   
     | 
| 
       65 
     | 
    
         
            -
                  
         
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
      
 66 
     | 
    
         
            +
                  attribute_names &= self.class.column_names
         
     | 
| 
      
 67 
     | 
    
         
            +
                  attributes_values = attributes_with_values_for_create(attribute_names)
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  new_id = self.class._insert_record(attributes_values)
         
     | 
| 
       67 
70 
     | 
    
         | 
| 
       68 
71 
     | 
    
         
             
                  @new_record = false
         
     | 
| 
       69 
72 
     | 
    
         | 
| 
         @@ -76,18 +79,20 @@ module ActiveRecord 
     | 
|
| 
       76 
79 
     | 
    
         
             
                end
         
     | 
| 
       77 
80 
     | 
    
         | 
| 
       78 
81 
     | 
    
         
             
                def _update_record(attribute_names = self.attribute_names)
         
     | 
| 
       79 
     | 
    
         
            -
                   
     | 
| 
      
 82 
     | 
    
         
            +
                  attribute_names &= self.class.column_names
         
     | 
| 
      
 83 
     | 
    
         
            +
                  attributes_values = attributes_with_values_for_update(attribute_names)
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
       80 
85 
     | 
    
         
             
                  if attributes_values.empty?
         
     | 
| 
       81 
     | 
    
         
            -
                     
     | 
| 
      
 86 
     | 
    
         
            +
                    affected_rows = 0
         
     | 
| 
       82 
87 
     | 
    
         
             
                    @_trigger_update_callback = true
         
     | 
| 
       83 
88 
     | 
    
         
             
                  else
         
     | 
| 
       84 
     | 
    
         
            -
                     
     | 
| 
       85 
     | 
    
         
            -
                    @_trigger_update_callback =  
     | 
| 
      
 89 
     | 
    
         
            +
                    affected_rows = self.class._update_record( attributes_values, self.class.primary_key => id_in_database )
         
     | 
| 
      
 90 
     | 
    
         
            +
                    @_trigger_update_callback = affected_rows == 1
         
     | 
| 
       86 
91 
     | 
    
         
             
                  end
         
     | 
| 
       87 
92 
     | 
    
         | 
| 
       88 
93 
     | 
    
         
             
                  yield(self) if block_given?
         
     | 
| 
       89 
94 
     | 
    
         | 
| 
       90 
     | 
    
         
            -
                   
     | 
| 
      
 95 
     | 
    
         
            +
                  affected_rows
         
     | 
| 
       91 
96 
     | 
    
         
             
                end
         
     | 
| 
       92 
97 
     | 
    
         | 
| 
       93 
98 
     | 
    
         
             
                #!!!! TODO: I am duplicated from finder_methods.....
         
     | 
| 
         @@ -1,59 +1,19 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Relation
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
                def to_sql
         
     | 
| 
       5 
     | 
    
         
            -
                  @to_sql ||= begin
         
     | 
| 
       6 
     | 
    
         
            -
                    relation   = self
         
     | 
| 
       7 
     | 
    
         
            -
                    
         
     | 
| 
       8 
     | 
    
         
            -
                    if eager_loading?
         
     | 
| 
       9 
     | 
    
         
            -
                      find_with_associations { |rel| relation = rel }
         
     | 
| 
       10 
     | 
    
         
            -
                    end
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                    conn = klass.connection
         
     | 
| 
       13 
     | 
    
         
            -
                    conn.unprepared_statement {
         
     | 
| 
       14 
     | 
    
         
            -
                      conn.to_sql(relation.arel, relation.bound_attributes)
         
     | 
| 
       15 
     | 
    
         
            -
                    }
         
     | 
| 
       16 
     | 
    
         
            -
                  end
         
     | 
| 
       17 
     | 
    
         
            -
                end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
4 
     | 
    
         
             
                def to_sar
         
     | 
| 
       20 
5 
     | 
    
         
             
                  @to_sar ||= begin
         
     | 
| 
       21 
     | 
    
         
            -
                    relation   = self
         
     | 
| 
       22 
     | 
    
         
            -
                    
         
     | 
| 
       23 
6 
     | 
    
         
             
                    if eager_loading?
         
     | 
| 
       24 
     | 
    
         
            -
                       
     | 
| 
      
 7 
     | 
    
         
            +
                      apply_join_dependency do |relation, join_dependency|
         
     | 
| 
      
 8 
     | 
    
         
            +
                        relation = join_dependency.apply_column_aliases(relation)
         
     | 
| 
      
 9 
     | 
    
         
            +
                        relation.to_sar
         
     | 
| 
      
 10 
     | 
    
         
            +
                      end
         
     | 
| 
      
 11 
     | 
    
         
            +
                    else
         
     | 
| 
      
 12 
     | 
    
         
            +
                      conn = klass.connection
         
     | 
| 
      
 13 
     | 
    
         
            +
                      conn.unprepared_statement { conn.to_sar(arel) }
         
     | 
| 
       25 
14 
     | 
    
         
             
                    end
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                    conn = klass.connection
         
     | 
| 
       28 
     | 
    
         
            -
                    conn.unprepared_statement {
         
     | 
| 
       29 
     | 
    
         
            -
                      conn.to_sar(relation.arel, relation.bound_attributes)
         
     | 
| 
       30 
     | 
    
         
            -
                    }
         
     | 
| 
       31 
15 
     | 
    
         
             
                  end
         
     | 
| 
       32 
16 
     | 
    
         
             
                end
         
     | 
| 
       33 
17 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
                def _update_record(values, id, id_was) # :nodoc:
         
     | 
| 
       35 
     | 
    
         
            -
                  substitutes, binds = substitute_values values
         
     | 
| 
       36 
     | 
    
         
            -
                  
         
     | 
| 
       37 
     | 
    
         
            -
                  scope = @klass.unscoped
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
                  if @klass.finder_needs_type_condition?
         
     | 
| 
       40 
     | 
    
         
            -
                    scope.unscope!(where: @klass.inheritance_column)
         
     | 
| 
       41 
     | 
    
         
            -
                  end
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                  relation = scope.where(@klass.primary_key => (id_was || id))
         
     | 
| 
       44 
     | 
    
         
            -
                  bvs = binds + relation.bound_attributes
         
     | 
| 
       45 
     | 
    
         
            -
                  um = relation
         
     | 
| 
       46 
     | 
    
         
            -
                    .arel
         
     | 
| 
       47 
     | 
    
         
            -
                    .compile_update(substitutes, @klass.primary_key)
         
     | 
| 
       48 
     | 
    
         
            -
                  um.table @klass.arel_table
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                  @klass.connection.update(
         
     | 
| 
       51 
     | 
    
         
            -
                    um,
         
     | 
| 
       52 
     | 
    
         
            -
                    'SQL',
         
     | 
| 
       53 
     | 
    
         
            -
                    bvs,
         
     | 
| 
       54 
     | 
    
         
            -
                  )
         
     | 
| 
       55 
     | 
    
         
            -
                end
         
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
18 
     | 
    
         
             
              end
         
     | 
| 
       59 
19 
     | 
    
         
             
            end
         
     | 
| 
         @@ -7,19 +7,21 @@ module ActiveRecord 
     | 
|
| 
       7 
7 
     | 
    
         
             
                  end
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                  if has_include?(column_names.first)
         
     | 
| 
       10 
     | 
    
         
            -
                     
     | 
| 
      
 10 
     | 
    
         
            +
                    relation = apply_join_dependency
         
     | 
| 
      
 11 
     | 
    
         
            +
                    relation.pluck(*column_names)
         
     | 
| 
       11 
12 
     | 
    
         
             
                  elsif klass.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
         
     | 
| 
       12 
13 
     | 
    
         
             
                    load
         
     | 
| 
       13 
14 
     | 
    
         
             
                    return records.pluck(*column_names.map{|n| n.sub(/^#{klass.table_name}\./, "")})
         
     | 
| 
       14 
15 
     | 
    
         
             
                  else
         
     | 
| 
      
 16 
     | 
    
         
            +
                    enforce_raw_sql_whitelist(column_names)
         
     | 
| 
       15 
17 
     | 
    
         
             
                    relation = spawn
         
     | 
| 
       16 
18 
     | 
    
         
             
                    relation.select_values = column_names.map { |cn|
         
     | 
| 
       17 
19 
     | 
    
         
             
                      @klass.has_attribute?(cn) || @klass.attribute_alias?(cn) ? arel_attribute(cn) : cn
         
     | 
| 
       18 
20 
     | 
    
         
             
                    }
         
     | 
| 
       19 
     | 
    
         
            -
                    result = klass.connection.select_all(relation.arel, nil 
     | 
| 
      
 21 
     | 
    
         
            +
                    result = skip_query_cache_if_necessary { klass.connection.select_all(relation.arel, nil) }
         
     | 
| 
       20 
22 
     | 
    
         
             
                    result.cast_values(klass.attribute_types)
         
     | 
| 
       21 
23 
     | 
    
         
             
                  end
         
     | 
| 
       22 
24 
     | 
    
         
             
                end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       24 
26 
     | 
    
         
             
              end
         
     | 
| 
       25 
27 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,9 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 2 
     | 
    
         
            +
              module QueryMethods
         
     | 
| 
      
 3 
     | 
    
         
            +
                private
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def assert_mutability!
         
     | 
| 
      
 5 
     | 
    
         
            +
                    raise ImmutableRelation if @loaded
         
     | 
| 
      
 6 
     | 
    
         
            +
                    raise ImmutableRelation if defined?(@arel) && !klass.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && @arel
         
     | 
| 
      
 7 
     | 
    
         
            +
                  end
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -5,9 +5,7 @@ module ActiveRecord 
     | 
|
| 
       5 
5 
     | 
    
         
             
                  def initialize(values, sunstone=false)
         
     | 
| 
       6 
6 
     | 
    
         
             
                    @values = values
         
     | 
| 
       7 
7 
     | 
    
         
             
                    @indexes = if sunstone
         
     | 
| 
       8 
     | 
    
         
            -
                       
     | 
| 
       9 
     | 
    
         
            -
                        Arel::Nodes::BindParam === thing
         
     | 
| 
       10 
     | 
    
         
            -
                      }
         
     | 
| 
      
 8 
     | 
    
         
            +
                      
         
     | 
| 
       11 
9 
     | 
    
         
             
                    else
         
     | 
| 
       12 
10 
     | 
    
         
             
                      values.each_with_index.find_all { |thing,i|
         
     | 
| 
       13 
11 
     | 
    
         
             
                        Arel::Nodes::BindParam === thing
         
     | 
| 
         @@ -16,11 +14,11 @@ module ActiveRecord 
     | 
|
| 
       16 
14 
     | 
    
         
             
                  end
         
     | 
| 
       17 
15 
     | 
    
         | 
| 
       18 
16 
     | 
    
         
             
                  def sql_for(binds, connection)
         
     | 
| 
       19 
     | 
    
         
            -
                    casted_binds = binds.map(&:value_for_database)
         
     | 
| 
       20 
     | 
    
         
            -
                    
         
     | 
| 
       21 
17 
     | 
    
         
             
                    if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
         
     | 
| 
       22 
     | 
    
         
            -
                       
     | 
| 
      
 18 
     | 
    
         
            +
                      binds.map!(&:value_for_database)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      @values
         
     | 
| 
       23 
20 
     | 
    
         
             
                    else
         
     | 
| 
      
 21 
     | 
    
         
            +
                      casted_binds = binds.map(&:value_for_database)
         
     | 
| 
       24 
22 
     | 
    
         
             
                      val = @values.dup
         
     | 
| 
       25 
23 
     | 
    
         
             
                      @indexes.each { |i| val[i] = connection.quote(casted_binds.shift) }
         
     | 
| 
       26 
24 
     | 
    
         
             
                      val.join
         
     | 
| 
         @@ -34,29 +34,19 @@ module ActiveRecord 
     | 
|
| 
       34 
34 
     | 
    
         
             
                # end
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
       36 
36 
     | 
    
         
             
                def with_transaction_returning_status
         
     | 
| 
       37 
     | 
    
         
            -
                  if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && instance_variable_defined?(:@updating) && @updating
         
     | 
| 
       38 
     | 
    
         
            -
                    begin
         
     | 
| 
       39 
     | 
    
         
            -
                      status = yield
         
     | 
| 
       40 
     | 
    
         
            -
                    rescue ActiveRecord::Rollback
         
     | 
| 
       41 
     | 
    
         
            -
                      clear_transaction_record_state
         
     | 
| 
       42 
     | 
    
         
            -
                      status = nil
         
     | 
| 
       43 
     | 
    
         
            -
                    end
         
     | 
| 
       44 
     | 
    
         
            -
                    return status
         
     | 
| 
       45 
     | 
    
         
            -
                  end
         
     | 
| 
       46 
     | 
    
         
            -
                  
         
     | 
| 
       47 
37 
     | 
    
         
             
                  status = nil
         
     | 
| 
       48 
     | 
    
         
            -
                   
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                     
     | 
| 
      
 38 
     | 
    
         
            +
                  
         
     | 
| 
      
 39 
     | 
    
         
            +
                  if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && instance_variable_defined?(:@updating) && @updating
         
     | 
| 
      
 40 
     | 
    
         
            +
                    status = yield
         
     | 
| 
      
 41 
     | 
    
         
            +
                    status
         
     | 
| 
      
 42 
     | 
    
         
            +
                  else
         
     | 
| 
      
 43 
     | 
    
         
            +
                    self.class.transaction do
         
     | 
| 
      
 44 
     | 
    
         
            +
                      add_to_transaction
         
     | 
| 
       51 
45 
     | 
    
         
             
                      status = yield
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
                      clear_transaction_record_state
         
     | 
| 
       54 
     | 
    
         
            -
                      status = nil
         
     | 
| 
      
 46 
     | 
    
         
            +
                      raise ActiveRecord::Rollback unless status
         
     | 
| 
       55 
47 
     | 
    
         
             
                    end
         
     | 
| 
       56 
     | 
    
         
            -
                    
         
     | 
| 
       57 
     | 
    
         
            -
                    raise ActiveRecord::Rollback unless status
         
     | 
| 
      
 48 
     | 
    
         
            +
                    status
         
     | 
| 
       58 
49 
     | 
    
         
             
                  end
         
     | 
| 
       59 
     | 
    
         
            -
                  status
         
     | 
| 
       60 
50 
     | 
    
         
             
                ensure
         
     | 
| 
       61 
51 
     | 
    
         
             
                  if @transaction_state && @transaction_state.committed?
         
     | 
| 
       62 
52 
     | 
    
         
             
                    clear_transaction_record_state
         
     | 
| 
         @@ -4,24 +4,38 @@ module Arel 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
                  attr_accessor :eager_load
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
                  def  
     | 
| 
       8 
     | 
    
         
            -
                     
     | 
| 
       9 
     | 
    
         
            -
                    @ 
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize cores = [SelectCore.new]
         
     | 
| 
      
 8 
     | 
    
         
            +
                    super()
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @cores          = cores
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @orders         = []
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @limit          = nil
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @lock           = nil
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @offset         = nil
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @with           = nil
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @eager_load     = nil
         
     | 
| 
       10 
16 
     | 
    
         
             
                  end
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                   
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
      
 17 
     | 
    
         
            +
                  
         
     | 
| 
      
 18 
     | 
    
         
            +
                  def initialize_copy other
         
     | 
| 
      
 19 
     | 
    
         
            +
                    super
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @cores  = @cores.map { |x| x.clone }
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @orders = @orders.map { |x| x.clone }
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @eager_load = @eager_load&.map { |x| x.clone }
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                  
         
     | 
| 
       15 
25 
     | 
    
         
             
                  def hash
         
     | 
| 
       16 
26 
     | 
    
         
             
                    [@cores, @orders, @limit, @lock, @offset, @with, @eager_load].hash
         
     | 
| 
       17 
27 
     | 
    
         
             
                  end
         
     | 
| 
       18 
28 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
                  def  
     | 
| 
       20 
     | 
    
         
            -
                     
     | 
| 
      
 29 
     | 
    
         
            +
                  def eql? other
         
     | 
| 
      
 30 
     | 
    
         
            +
                    self.class == other.class &&
         
     | 
| 
      
 31 
     | 
    
         
            +
                      self.cores == other.cores &&
         
     | 
| 
      
 32 
     | 
    
         
            +
                      self.orders == other.orders &&
         
     | 
| 
      
 33 
     | 
    
         
            +
                      self.limit == other.limit &&
         
     | 
| 
      
 34 
     | 
    
         
            +
                      self.lock == other.lock &&
         
     | 
| 
      
 35 
     | 
    
         
            +
                      self.offset == other.offset &&
         
     | 
| 
      
 36 
     | 
    
         
            +
                      self.with == other.with &&
         
     | 
| 
      
 37 
     | 
    
         
            +
                      self.eager_load == other.eager_load
         
     | 
| 
       21 
38 
     | 
    
         
             
                  end
         
     | 
| 
       22 
     | 
    
         
            -
                  alias_method :eql_without_eager_load?, :eql?
         
     | 
| 
       23 
     | 
    
         
            -
                  alias_method :eql?, :eql_with_eager_load?
         
     | 
| 
       24 
     | 
    
         
            -
                  alias_method :==, :eql?
         
     | 
| 
       25 
39 
     | 
    
         | 
| 
       26 
40 
     | 
    
         
             
                end
         
     | 
| 
       27 
41 
     | 
    
         
             
              end
         
     | 
| 
         @@ -7,49 +7,97 @@ module ActiveRecord 
     | 
|
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
                    def to_sql(arel, binds = [])
         
     | 
| 
       9 
9 
     | 
    
         
             
                      if arel.respond_to?(:ast)
         
     | 
| 
       10 
     | 
    
         
            -
                         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 10 
     | 
    
         
            +
                        unless binds.empty?
         
     | 
| 
      
 11 
     | 
    
         
            +
                          raise "Passing bind parameters with an arel AST is forbidden. " \
         
     | 
| 
      
 12 
     | 
    
         
            +
                            "The values must be stored on the AST directly"
         
     | 
| 
      
 13 
     | 
    
         
            +
                        end
         
     | 
| 
      
 14 
     | 
    
         
            +
                        Arel::Visitors::ToSql.new(self).accept(arel.ast, Arel::Collectors::SubstituteBinds.new(self, Arel::Collectors::SQLString.new)).value
         
     | 
| 
       12 
15 
     | 
    
         
             
                      else
         
     | 
| 
       13 
16 
     | 
    
         
             
                        arel.dup.freeze
         
     | 
| 
       14 
17 
     | 
    
         
             
                      end
         
     | 
| 
       15 
18 
     | 
    
         
             
                    end
         
     | 
| 
       16 
19 
     | 
    
         | 
| 
       17 
20 
     | 
    
         
             
                    # Converts an arel AST to a Sunstone API Request
         
     | 
| 
       18 
     | 
    
         
            -
                    def to_sar( 
     | 
| 
       19 
     | 
    
         
            -
                      if  
     | 
| 
       20 
     | 
    
         
            -
                         
     | 
| 
       21 
     | 
    
         
            -
                         
     | 
| 
      
 21 
     | 
    
         
            +
                    def to_sar(arel_or_sar_string, binds = nil)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      if arel_or_sar_string.respond_to?(:ast)
         
     | 
| 
      
 23 
     | 
    
         
            +
                        sar = visitor.accept(arel_or_sar_string.ast, collector)
         
     | 
| 
      
 24 
     | 
    
         
            +
                        binds = sar.binds if binds.nil?
         
     | 
| 
       22 
25 
     | 
    
         
             
                      else
         
     | 
| 
       23 
     | 
    
         
            -
                         
     | 
| 
      
 26 
     | 
    
         
            +
                        sar = arel_or_sar_string
         
     | 
| 
       24 
27 
     | 
    
         
             
                      end
         
     | 
| 
      
 28 
     | 
    
         
            +
                      sar.compile(binds)
         
     | 
| 
       25 
29 
     | 
    
         
             
                    end
         
     | 
| 
       26 
30 
     | 
    
         | 
| 
      
 31 
     | 
    
         
            +
                    def to_sar_and_binds(arel_or_sar_string, binds = []) # :nodoc:
         
     | 
| 
      
 32 
     | 
    
         
            +
                      if arel_or_sar_string.respond_to?(:ast)
         
     | 
| 
      
 33 
     | 
    
         
            +
                        unless binds.empty?
         
     | 
| 
      
 34 
     | 
    
         
            +
                          raise "Passing bind parameters with an arel AST is forbidden. " \
         
     | 
| 
      
 35 
     | 
    
         
            +
                            "The values must be stored on the AST directly"
         
     | 
| 
      
 36 
     | 
    
         
            +
                        end
         
     | 
| 
      
 37 
     | 
    
         
            +
                        sar = visitor.accept(arel_or_sar_string.ast, collector)
         
     | 
| 
      
 38 
     | 
    
         
            +
                        # puts ['a', sar.freeze, sar.binds].map(&:inspect)
         
     | 
| 
      
 39 
     | 
    
         
            +
                        [sar.freeze, sar.binds]
         
     | 
| 
      
 40 
     | 
    
         
            +
                      else
         
     | 
| 
      
 41 
     | 
    
         
            +
                        # puts ['b',arel_or_sar_string.dup.freeze, binds].map(&:inspect)
         
     | 
| 
      
 42 
     | 
    
         
            +
                        [arel_or_sar_string.dup.freeze, binds]
         
     | 
| 
      
 43 
     | 
    
         
            +
                      end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
                    
         
     | 
| 
      
 46 
     | 
    
         
            +
                    # This is used in the StatementCache object. It returns an object that
         
     | 
| 
      
 47 
     | 
    
         
            +
                    # can be used to query the database repeatedly.
         
     | 
| 
       27 
48 
     | 
    
         
             
                    def cacheable_query(klass, arel) # :nodoc:
         
     | 
| 
       28 
     | 
    
         
            -
                      collected = visitor.accept(arel.ast, collector)
         
     | 
| 
       29 
49 
     | 
    
         
             
                      if prepared_statements
         
     | 
| 
       30 
     | 
    
         
            -
                         
     | 
| 
      
 50 
     | 
    
         
            +
                        sql, binds = visitor.accept(arel.ast, collector).value
         
     | 
| 
      
 51 
     | 
    
         
            +
                        query = klass.query(sql)
         
     | 
| 
      
 52 
     | 
    
         
            +
                      elsif self.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
         
     | 
| 
      
 53 
     | 
    
         
            +
                        collector = SunstonePartialQueryCollector.new(self.collector)
         
     | 
| 
      
 54 
     | 
    
         
            +
                        parts, binds = visitor.accept(arel.ast, collector).value
         
     | 
| 
      
 55 
     | 
    
         
            +
                        query = StatementCache::PartialQuery.new(parts, true)
         
     | 
| 
       31 
56 
     | 
    
         
             
                      else
         
     | 
| 
       32 
     | 
    
         
            -
                         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
      
 57 
     | 
    
         
            +
                        collector = PartialQueryCollector.new
         
     | 
| 
      
 58 
     | 
    
         
            +
                        parts, binds = visitor.accept(arel.ast, collector).value
         
     | 
| 
      
 59 
     | 
    
         
            +
                        query = klass.partial_query(parts)
         
     | 
| 
      
 60 
     | 
    
         
            +
                      end
         
     | 
| 
      
 61 
     | 
    
         
            +
                      [query, binds]
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    class SunstonePartialQueryCollector
         
     | 
| 
      
 65 
     | 
    
         
            +
                      delegate_missing_to :@collector
         
     | 
| 
      
 66 
     | 
    
         
            +
                      
         
     | 
| 
      
 67 
     | 
    
         
            +
                      def initialize(collector)
         
     | 
| 
      
 68 
     | 
    
         
            +
                        @collector = collector
         
     | 
| 
      
 69 
     | 
    
         
            +
                        @binds = []
         
     | 
| 
      
 70 
     | 
    
         
            +
                      end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                      def add_bind(obj)
         
     | 
| 
      
 73 
     | 
    
         
            +
                        @binds << obj
         
     | 
| 
      
 74 
     | 
    
         
            +
                      end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                      def value
         
     | 
| 
      
 77 
     | 
    
         
            +
                        [@collector, @binds]
         
     | 
| 
       37 
78 
     | 
    
         
             
                      end
         
     | 
| 
       38 
79 
     | 
    
         
             
                    end
         
     | 
| 
       39 
80 
     | 
    
         | 
| 
       40 
81 
     | 
    
         
             
                    # Returns an ActiveRecord::Result instance.
         
     | 
| 
       41 
82 
     | 
    
         
             
                    def select_all(arel, name = nil, binds = [], preparable: nil)
         
     | 
| 
       42 
     | 
    
         
            -
                      arel 
     | 
| 
       43 
     | 
    
         
            -
                       
     | 
| 
      
 83 
     | 
    
         
            +
                      arel = arel_from_relation(arel)
         
     | 
| 
      
 84 
     | 
    
         
            +
                      sar, binds = to_sar_and_binds(arel, binds)
         
     | 
| 
      
 85 
     | 
    
         
            +
                      select(sar, name, binds)
         
     | 
| 
       44 
86 
     | 
    
         
             
                    end
         
     | 
| 
       45 
87 
     | 
    
         | 
| 
       46 
88 
     | 
    
         
             
                    def exec_query(arel, name = 'SAR', binds = [], prepare: false)
         
     | 
| 
       47 
89 
     | 
    
         
             
                      sars = []
         
     | 
| 
       48 
     | 
    
         
            -
                      multiple_requests = arel.is_a?(Arel:: 
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
      
 90 
     | 
    
         
            +
                      multiple_requests = arel.is_a?(Arel::Collectors::Sunstone)
         
     | 
| 
      
 91 
     | 
    
         
            +
                      type_casted_binds = binds#type_casted_binds(binds)
         
     | 
| 
      
 92 
     | 
    
         
            +
                      
         
     | 
| 
       50 
93 
     | 
    
         
             
                      if multiple_requests
         
     | 
| 
       51 
     | 
    
         
            -
                        allowed_limit = limit_definition(arel. 
     | 
| 
       52 
     | 
    
         
            -
                         
     | 
| 
      
 94 
     | 
    
         
            +
                        allowed_limit = limit_definition(arel.table)
         
     | 
| 
      
 95 
     | 
    
         
            +
                        limit_bind_index = nil#binds.find_index { |x| x.name == 'LIMIT' }
         
     | 
| 
      
 96 
     | 
    
         
            +
                        requested_limit = if limit_bind_index
         
     | 
| 
      
 97 
     | 
    
         
            +
                          type_casted_binds[limit_bind_index]
         
     | 
| 
      
 98 
     | 
    
         
            +
                        else
         
     | 
| 
      
 99 
     | 
    
         
            +
                          arel.limit&.value&.value_for_database
         
     | 
| 
      
 100 
     | 
    
         
            +
                        end
         
     | 
| 
       53 
101 
     | 
    
         | 
| 
       54 
102 
     | 
    
         
             
                        if allowed_limit.nil?
         
     | 
| 
       55 
103 
     | 
    
         
             
                          multiple_requests = false
         
     | 
| 
         @@ -61,7 +109,7 @@ module ActiveRecord 
     | 
|
| 
       61 
109 
     | 
    
         
             
                      end
         
     | 
| 
       62 
110 
     | 
    
         | 
| 
       63 
111 
     | 
    
         
             
                      send_request = lambda { |req_arel|
         
     | 
| 
       64 
     | 
    
         
            -
                        sar = to_sar(req_arel,  
     | 
| 
      
 112 
     | 
    
         
            +
                        sar = to_sar(req_arel, type_casted_binds)
         
     | 
| 
       65 
113 
     | 
    
         
             
                        sars.push(sar)
         
     | 
| 
       66 
114 
     | 
    
         
             
                        log_mess = sar.path.split('?', 2)
         
     | 
| 
       67 
115 
     | 
    
         
             
                        log("#{sar.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? MessagePack.unpack(CGI.unescape(log_mess[1])) : '' }", name) do
         
     | 
| 
         @@ -75,12 +123,11 @@ module ActiveRecord 
     | 
|
| 
       75 
123 
     | 
    
         
             
                      }
         
     | 
| 
       76 
124 
     | 
    
         | 
| 
       77 
125 
     | 
    
         
             
                      result = if multiple_requests
         
     | 
| 
       78 
     | 
    
         
            -
                         
     | 
| 
       79 
     | 
    
         
            -
                        binds.delete(bind)
         
     | 
| 
      
 126 
     | 
    
         
            +
                        binds.delete_at(limit_bind_index) if limit_bind_index
         
     | 
| 
       80 
127 
     | 
    
         | 
| 
       81 
128 
     | 
    
         
             
                        limit, offset, results = allowed_limit, 0, []
         
     | 
| 
       82 
129 
     | 
    
         
             
                        while requested_limit ? offset < requested_limit : true
         
     | 
| 
       83 
     | 
    
         
            -
                          split_arel = arel. 
     | 
| 
      
 130 
     | 
    
         
            +
                          split_arel = arel.dup
         
     | 
| 
       84 
131 
     | 
    
         
             
                          split_arel.limit = limit
         
     | 
| 
       85 
132 
     | 
    
         
             
                          split_arel.offset = offset
         
     | 
| 
       86 
133 
     | 
    
         
             
                          request_results = send_request.call(split_arel)
         
     | 
| 
         @@ -104,8 +151,12 @@ module ActiveRecord 
     | 
|
| 
       104 
151 
     | 
    
         
             
                    end
         
     | 
| 
       105 
152 
     | 
    
         | 
| 
       106 
153 
     | 
    
         
             
                    def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
         
     | 
| 
       107 
     | 
    
         
            -
                       
     | 
| 
      
 154 
     | 
    
         
            +
                      sar, binds = to_sar_and_binds(arel, binds)
         
     | 
| 
      
 155 
     | 
    
         
            +
                      value = exec_insert(sar, name, binds, pk, sequence_name)
         
     | 
| 
       108 
156 
     | 
    
         
             
                      id_value || last_inserted_id(value)
         
     | 
| 
      
 157 
     | 
    
         
            +
                      
         
     | 
| 
      
 158 
     | 
    
         
            +
                      # value = exec_insert(arel, name, binds, pk, sequence_name)
         
     | 
| 
      
 159 
     | 
    
         
            +
                      # id_value || last_inserted_id(value)
         
     | 
| 
       109 
160 
     | 
    
         
             
                    end
         
     | 
| 
       110 
161 
     | 
    
         | 
| 
       111 
162 
     | 
    
         
             
                    def update(arel, name = nil, binds = [])
         
     | 
| 
         @@ -130,7 +130,7 @@ module ActiveRecord 
     | 
|
| 
       130 
130 
     | 
    
         
             
                  def collector
         
     | 
| 
       131 
131 
     | 
    
         
             
                    Arel::Collectors::Sunstone.new
         
     | 
| 
       132 
132 
     | 
    
         
             
                  end
         
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
      
 133 
     | 
    
         
            +
                  
         
     | 
| 
       134 
134 
     | 
    
         
             
                  def server_config
         
     | 
| 
       135 
135 
     | 
    
         
             
                    JSON.parse(@connection.get("/configuration").body)
         
     | 
| 
       136 
136 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -173,8 +173,7 @@ module ActiveRecord 
     | 
|
| 
       173 
173 
     | 
    
         
             
                  # If the next id was calculated in advance (as in Oracle), it should be
         
     | 
| 
       174 
174 
     | 
    
         
             
                  # passed in as +id_value+.
         
     | 
| 
       175 
175 
     | 
    
         
             
                  def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
         
     | 
| 
       176 
     | 
    
         
            -
                     
     | 
| 
       177 
     | 
    
         
            -
                    exec_insert(sql, name, binds, pk, sequence_name)
         
     | 
| 
      
 176 
     | 
    
         
            +
                    exec_insert(arel, name, binds, pk, sequence_name)
         
     | 
| 
       178 
177 
     | 
    
         
             
                  end
         
     | 
| 
       179 
178 
     | 
    
         
             
                  alias create insert
         
     | 
| 
       180 
179 
     | 
    
         |