sunstone 7.0.0 → 7.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02df1d75e40c2ef207e6e1f329068c95098f5b99758d1bcea603e157ed2c1f40
4
- data.tar.gz: 4807c8a530f9c7f09448a08bea1dbe015724f2afb53d81b86cf5cef6d6b49dcf
3
+ metadata.gz: d280487f58777eebd36b07eb69f9492b77370ea3def7b05321bb2d4fd8e55626
4
+ data.tar.gz: a34f616483aca20b1207f12538e08fafb19b16ac01db6c19977b902cd1cd1537
5
5
  SHA512:
6
- metadata.gz: e884525eda7c249da0f4decbadff3d27ff97859eac4874e1c20b4b0e10c80d6d96ee49419d27bd2f6d429c55c93485bfe1961451ff8396d101e37752ec39ac6d
7
- data.tar.gz: 4323252706192a940b6f730a6c46324d4c40729df5864a5d1aafc4283764ef159284ddefe9b1335a7d9174b6716d11a2d0da4aa59dbdfbc3ac7cdccc537b06f8
6
+ metadata.gz: 0211de6c05fded268d04e00af2e0f16e9f4ee0650307288ea890c343e1b20f0a2fcf924631e2c0c3e72b602af7e964c8663a6df51f22cce9bd85798b26d12604
7
+ data.tar.gz: 62e9b986925a43ca27c172499bca956ea20e6b8ca237d94dbcb1b07f52772ad1ffc9d5a0fe68d9ef6560e9a3df5ccc7bc27a8a78b56aad4fcccc44604f2a9060
@@ -1,14 +1,16 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
1
3
  module ActiveRecord
2
4
  module Associations
3
5
  class CollectionAssociation
4
6
 
5
7
  def replace(other_array)
6
8
  other_array.each { |val| raise_on_type_mismatch!(val) }
7
- original_target = load_target.dup
9
+ original_target = skip_strict_loading { load_target }.dup
8
10
 
9
11
  if owner.new_record?
10
12
  replace_records(other_array, original_target)
11
- elsif owner.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && owner.instance_variable_defined?(:@updating) && owner.instance_variable_get(:@updating)
13
+ elsif owner.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && owner.instance_variable_defined?(:@sunstone_updating) && owner.instance_variable_get(:@sunstone_updating)
12
14
  replace_common_records_in_memory(other_array, original_target)
13
15
 
14
16
  # Remove from target
@@ -41,7 +43,7 @@ module ActiveRecord
41
43
  end
42
44
 
43
45
  def insert_record(record, validate = true, raise = false, &block)
44
- if record.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && owner.instance_variable_defined?(:@updating) && owner.instance_variable_get(:@updating)
46
+ if record.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && owner.instance_variable_defined?(:@sunstone_updating) && owner.instance_variable_get(:@sunstone_updating)
45
47
  true
46
48
  elsif raise
47
49
  record.save!(validate: validate, &block)
@@ -50,7 +52,6 @@ module ActiveRecord
50
52
  end
51
53
  end
52
54
 
53
-
54
55
  end
55
56
 
56
57
  class HasManyThroughAssociation
@@ -70,27 +71,3 @@ module ActiveRecord
70
71
 
71
72
  end
72
73
  end
73
-
74
- module ActiveRecord
75
- module Persistence
76
-
77
- # Updates the attributes of the model from the passed-in hash and saves the
78
- # record, all wrapped in a transaction. If the object is invalid, the saving
79
- # will fail and false will be returned.
80
- def update(attributes)
81
- @updating = :updating
82
- Thread.current[:sunstone_updating_model] = self
83
-
84
- # The following transaction covers any possible database side-effects of the
85
- # attributes assignment. For example, setting the IDs of a child collection.
86
- with_transaction_returning_status do
87
- assign_attributes(attributes)
88
- save
89
- end
90
- ensure
91
- @updating = false
92
- Thread.current[:sunstone_updating_model] = nil
93
- end
94
-
95
- end
96
- end
@@ -1,5 +1,9 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
3
+
1
4
  require 'active_record'
2
5
  require 'active_record/associations'
6
+
3
7
  module ActiveRecord
4
8
  module Associations
5
9
  module ClassMethods
@@ -21,13 +25,13 @@ module ActiveRecord
21
25
 
22
26
  include Module.new {
23
27
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
24
- def destroy_associations
25
- if !self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
26
- association(:#{middle_reflection.name}).delete_all(:delete_all)
27
- association(:#{name}).reset
28
+ def destroy_associations
29
+ if !self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
30
+ association(:#{middle_reflection.name}).delete_all(:delete_all)
31
+ association(:#{name}).reset
32
+ end
33
+ super
28
34
  end
29
- super
30
- end
31
35
  RUBY
32
36
  }
33
37
 
@@ -40,8 +44,8 @@ module ActiveRecord
40
44
  end
41
45
 
42
46
  has_many name, scope, **hm_options, &extension
43
- _reflections[name.to_s].parent_reflection = habtm_reflection
47
+ _reflections[name].parent_reflection = habtm_reflection
44
48
  end
45
49
  end
46
50
  end
47
- end
51
+ end
@@ -1,14 +1,15 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
3
+
1
4
  module ActiveRecord
2
5
  module AttributeMethods
3
-
6
+
4
7
  protected
5
-
8
+
6
9
  # Returns a Hash of the Arel::Attributes and attribute values that have been
7
10
  # typecasted for use in an Arel insert/update method.
8
11
  def attributes_with_values(attribute_names)
9
- attrs = attribute_names.index_with do |name|
10
- _read_attribute(name)
11
- end
12
+ attrs = attribute_names.index_with { |name| @attributes[name] }
12
13
 
13
14
  if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
14
15
  self.class.reflect_on_all_associations.each do |reflection|
@@ -25,17 +26,17 @@ module ActiveRecord
25
26
  end
26
27
  end
27
28
  end
28
-
29
+
29
30
  attrs
30
31
  end
31
-
32
+
32
33
  def add_attributes_for_belongs_to_association(reflection, attrs)
33
34
  key = :"add_attributes_for_belongs_to_association_#{reflection.name}"
34
35
  @_already_called ||= {}
35
36
  return if @_already_called[key]
36
37
  @_already_called[key]=true
37
38
  @_already_called[:"autosave_associated_records_for_#{reflection.name}"] = true
38
-
39
+
39
40
  association = association_instance_get(reflection.name)
40
41
  record = association && association.load_target
41
42
  if record && !record.destroyed?
@@ -51,14 +52,14 @@ module ActiveRecord
51
52
  end
52
53
  end
53
54
  end
54
-
55
+
55
56
  def add_attributes_for_has_one_association(reflection, attrs)
56
57
  key = :"add_attributes_for_has_one_association#{reflection.name}"
57
58
  @_already_called ||= {}
58
59
  return if @_already_called[key]
59
60
  @_already_called[key]=true
60
61
  @_already_called[:"autosave_associated_records_for_#{reflection.name}"] = true
61
-
62
+
62
63
  association = association_instance_get(reflection.name)
63
64
  record = association && association.load_target
64
65
 
@@ -80,7 +81,7 @@ module ActiveRecord
80
81
  end
81
82
  end
82
83
  end
83
-
84
+
84
85
  def add_attributes_for_collection_association(reflection, attrs, arel_table=nil)
85
86
  key = :"add_attributes_for_collection_association#{reflection.name}"
86
87
  @_already_called ||= {}
@@ -106,7 +107,7 @@ module ActiveRecord
106
107
  )
107
108
  end
108
109
  end
109
-
110
+
110
111
  association.instance_variable_set(:@sunstone_changed, false)
111
112
  end
112
113
 
@@ -114,6 +115,6 @@ module ActiveRecord
114
115
  association.reset_scope if association.respond_to?(:reset_scope)
115
116
  end
116
117
  end
117
-
118
+
118
119
  end
119
120
  end
@@ -1,3 +1,6 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
3
+
1
4
  module ActiveRecord
2
5
  module Callbacks
3
6
  private
@@ -14,4 +17,4 @@ module ActiveRecord
14
17
  end
15
18
 
16
19
  end
17
- end
20
+ end
@@ -1,14 +1,24 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
3
+
1
4
  module ActiveRecord
2
5
  class PredicateBuilder # :nodoc:
3
6
 
4
7
  def expand_from_hash(attributes, &block)
5
8
  return ["1=0"] if attributes.empty?
6
-
9
+
7
10
  attributes.flat_map do |key, value|
8
- if value.is_a?(Hash) && !table.has_column?(key)
11
+ if key.is_a?(Array)
12
+ queries = Array(value).map do |ids_set|
13
+ raise ArgumentError, "Expected corresponding value for #{key} to be an Array" unless ids_set.is_a?(Array)
14
+ expand_from_hash(key.zip(ids_set).to_h)
15
+ end
16
+ grouping_queries(queries)
17
+ elsif value.is_a?(Hash) && !table.has_column?(key)
9
18
  ka = table.associated_table(key, &block)
10
- .predicate_builder.expand_from_hash(value.stringify_keys)
11
- if self.send(:table).instance_variable_get(:@klass).connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
19
+ .predicate_builder.expand_from_hash(value.stringify_keys)
20
+
21
+ if self.table.instance_variable_get(:@klass).connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
12
22
  ka.each { |k|
13
23
  if k.left.is_a?(Arel::Attributes::Attribute) || k.left.is_a?(Arel::Attributes::Relation)
14
24
  k.left = Arel::Attributes::Relation.new(k.left, key)
@@ -6,10 +6,12 @@ module ActiveRecord
6
6
  def rpc(name)
7
7
  define_method("#{name}!") do
8
8
  req = Net::HTTP::Post.new("/#{self.class.table_name}/#{CGI.escape(id.to_s)}/#{CGI.escape(name.to_s)}")
9
- self.class.connection.instance_variable_get(:@connection).send_request(req) do |response|
10
- JSON.parse(response.body).each do |k,v|
11
- if self.class.column_names.include?(k)
12
- @attributes.write_from_database(k, v)
9
+ self.class.connection.send(:with_raw_connection) do |conn|
10
+ conn.send_request(req) do |response|
11
+ JSON.parse(response.body).each do |k,v|
12
+ if self.class.column_names.include?(k)
13
+ @attributes.write_from_database(k, v)
14
+ end
13
15
  end
14
16
  end
15
17
  end
@@ -17,7 +19,25 @@ module ActiveRecord
17
19
  end
18
20
  end
19
21
  end
20
-
22
+
23
+ # Updates the attributes of the model from the passed-in hash and saves the
24
+ # record, all wrapped in a transaction. If the object is invalid, the saving
25
+ # will fail and false will be returned.
26
+ def update(attributes)
27
+ @sunstone_updating = :updating
28
+ Thread.current[:sunstone_updating_model] = self
29
+
30
+ # The following transaction covers any possible database side-effects of the
31
+ # attributes assignment. For example, setting the IDs of a child collection.
32
+ with_transaction_returning_status do
33
+ assign_attributes(attributes)
34
+ save
35
+ end
36
+ ensure
37
+ @sunstone_updating = false
38
+ Thread.current[:sunstone_updating_model] = nil
39
+ end
40
+
21
41
  def update!(attributes)
22
42
  @no_save_transaction = true
23
43
  with_transaction_returning_status do
@@ -33,14 +53,14 @@ module ActiveRecord
33
53
  def create_or_update(**, &block)
34
54
  _raise_readonly_record_error if readonly?
35
55
  return false if destroyed?
36
-
37
- @updating = new_record? ? :creating : :updating
56
+
57
+ @sunstone_updating = new_record? ? :creating : :updating
38
58
  Thread.current[:sunstone_updating_model] = self
39
59
 
40
60
  result = new_record? ? _create_record(&block) : _update_record(&block)
41
61
 
42
62
  if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && result != 0
43
- row_hash = result.rows.first
63
+ row_hash = result[0]
44
64
 
45
65
  seen = Hash.new { |h, parent_klass|
46
66
  h[parent_klass] = Hash.new { |i, parent_id|
@@ -51,10 +71,13 @@ module ActiveRecord
51
71
  model_cache = Hash.new { |h,klass| h[klass] = {} }
52
72
  parents = model_cache[self.class.base_class]
53
73
 
54
- self.assign_attributes(row_hash.select{|k,v| self.class.column_names.include?(k.to_s) })
55
- row_hash.select{|k,v| !self.class.column_names.include?(k.to_s) }.each do |relation_name, value|
56
- assc = association(relation_name.to_sym)
57
- assc.reset if assc.reflection.collection?
74
+ row_hash.each do |key, value|
75
+ if self.class.column_names.include?(key.to_s)
76
+ _write_attribute(key, value)
77
+ else
78
+ assc = association(key.to_sym)
79
+ assc.reset if assc.reflection.collection? # TODO: can load here if included
80
+ end
58
81
  end
59
82
 
60
83
  construct(self, row_hash.select{|k,v| !self.class.column_names.include?(k.to_s) }, seen, model_cache)
@@ -72,39 +95,54 @@ module ActiveRecord
72
95
  end
73
96
  raise ActiveRecord::RecordInvalid
74
97
  ensure
75
- @updating = false
98
+ @sunstone_updating = false
76
99
  Thread.current[:sunstone_updating_model] = nil
77
100
  end
78
-
101
+
79
102
  # Creates a record with values matching those of the instance attributes
80
103
  # and returns its id.
81
104
  def _create_record(attribute_names = self.attribute_names)
82
105
  attribute_names = attributes_for_create(attribute_names)
83
- attributes_values = attributes_with_values(attribute_names)
106
+ attribute_values = attributes_with_values(attribute_names)
107
+ returning_values = nil
84
108
 
85
- new_id = self.class._insert_record(attributes_values)
109
+ self.class.with_connection do |connection|
110
+ returning_columns = self.class._returning_columns_for_insert(connection)
111
+
112
+ returning_values = self.class._insert_record(
113
+ connection,
114
+ attribute_values,
115
+ returning_columns
116
+ )
117
+
118
+ if !self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
119
+ returning_columns.zip(returning_values).each do |column, value|
120
+ _write_attribute(column, value) if !_read_attribute(column)
121
+ end if returning_values
122
+ end
123
+ end
86
124
 
87
- self.id ||= new_id if @primary_key
88
125
  @new_record = false
89
126
  @previously_new_record = true
90
127
 
91
128
  yield(self) if block_given?
92
129
 
93
130
  if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
94
- new_id
131
+ returning_values
95
132
  else
96
133
  id
97
134
  end
98
135
  end
99
-
136
+
100
137
  def _update_record(attribute_names = self.attribute_names)
138
+ attribute_names = attributes_for_update(attribute_names)
101
139
  attribute_values = attributes_with_values(attribute_names)
102
140
 
103
141
  if attribute_values.empty?
104
142
  affected_rows = 0
105
143
  @_trigger_update_callback = true
106
144
  else
107
- affected_rows = self.class._update_record( attribute_values, self.class.primary_key => id_in_database )
145
+ affected_rows = self.class._update_record(attribute_values, _query_constraints_hash)
108
146
  @_trigger_update_callback = affected_rows == 1
109
147
  end
110
148
 
@@ -1,11 +1,27 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
3
+
1
4
  module ActiveRecord
2
5
  module Calculations
3
-
6
+
4
7
  def pluck(*column_names)
8
+ if @none
9
+ if @async
10
+ return Promise::Complete.new([])
11
+ else
12
+ return []
13
+ end
14
+ end
15
+
5
16
  if loaded? && all_attributes?(column_names)
6
- return records.pluck(*column_names)
17
+ result = records.pluck(*column_names)
18
+ if @async
19
+ return Promise::Complete.new(result)
20
+ else
21
+ return result
22
+ end
7
23
  end
8
-
24
+
9
25
  if has_include?(column_names.first)
10
26
  relation = apply_join_dependency
11
27
  relation.pluck(*column_names)
@@ -13,18 +29,22 @@ module ActiveRecord
13
29
  load
14
30
  return records.pluck(*column_names.map{|n| n.to_s.sub(/^#{klass.table_name}\./, "")})
15
31
  else
16
- klass.disallow_raw_sql!(column_names)
32
+ klass.disallow_raw_sql!(flattened_args(column_names))
17
33
  columns = arel_columns(column_names)
18
34
  relation = spawn
19
35
  relation.select_values = columns
20
36
  result = skip_query_cache_if_necessary do
21
37
  if where_clause.contradiction?
22
- ActiveRecord::Result.empty
38
+ ActiveRecord::Result.empty(async: @async)
23
39
  else
24
- klass.connection.select_all(relation.arel, "#{klass.name} Pluck")
40
+ klass.with_connection do |c|
41
+ c.select_all(relation.arel, "#{klass.name} Pluck", async: @async)
42
+ end
25
43
  end
26
44
  end
27
- type_cast_pluck_values(result, columns)
45
+ result.then do |result|
46
+ type_cast_pluck_values(result, columns)
47
+ end
28
48
  end
29
49
  end
30
50
 
@@ -1,9 +1,11 @@
1
1
  module ActiveRecord
2
2
  module QueryMethods
3
3
  private
4
- def assert_mutability!
5
- raise ImmutableRelation if @loaded
6
- raise ImmutableRelation if defined?(@arel) && @arel && !klass.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
7
- end
4
+
5
+ def assert_modifiable!
6
+ raise UnmodifiableRelation if @loaded
7
+ raise UnmodifiableRelation if @arel && !klass.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
8
+ end
9
+
8
10
  end
9
11
  end
@@ -34,23 +34,25 @@ module ActiveRecord
34
34
  # end
35
35
 
36
36
  def with_transaction_returning_status
37
- status = nil
38
- connection = self.class.connection
39
-
40
- if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && instance_variable_defined?(:@updating) && @updating
41
- status = yield
42
- else
43
- ensure_finalize = !connection.transaction_open?
44
- connection.transaction do
45
- add_to_transaction(ensure_finalize || has_transactional_callbacks?)
46
- remember_transaction_record_state
37
+ self.class.with_connection do |connection|
38
+ status = nil
39
+ # connection = self.class.connection
47
40
 
41
+ if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && instance_variable_defined?(:@sunstone_updating) && @sunstone_updating
48
42
  status = yield
49
- raise ActiveRecord::Rollback unless status
43
+ else
44
+ ensure_finalize = !connection.transaction_open?
45
+ connection.transaction do
46
+ add_to_transaction(ensure_finalize || has_transactional_callbacks?)
47
+ remember_transaction_record_state
48
+
49
+ status = yield
50
+ raise ActiveRecord::Rollback unless status
51
+ end
50
52
  end
51
- end
52
53
 
53
- status
54
+ status
55
+ end
54
56
  end
55
57
 
56
58
 
@@ -2,6 +2,8 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  # Sunstone-specific extensions to column definitions in a table.
4
4
  class SunstoneColumn < Column #:nodoc:
5
+ NONE = Object.new
6
+
5
7
  attr_reader :array
6
8
 
7
9
  def initialize(name, sql_type_metadata, options={})
@@ -14,12 +16,20 @@ module ActiveRecord
14
16
  @table_name = nil
15
17
  @primary_key = (options['primary_key'] == true)
16
18
  @array = options['array']
19
+ @auto_populated = options.has_key?('auto_populated') ? options['auto_populated'] : NONE
17
20
  end
18
21
 
19
22
  def primary_key?
20
23
  @primary_key
21
24
  end
22
25
 
26
+ def auto_populated?
27
+ # TODO: when retuning is working we can do the following to only
28
+ # return autopulated fields from StandardAPI
29
+ # @auto_populated == NONE ? @primary_key : @auto_populated
30
+ true
31
+ end
32
+
23
33
  end
24
34
  end
25
35
  end
@@ -25,22 +25,34 @@ module ActiveRecord
25
25
  else
26
26
  sar = arel_or_sar_string
27
27
  end
28
+
28
29
  sar.compile(binds)
29
30
  end
30
31
 
31
- def to_sar_and_binds(arel_or_sar_string, binds = [], preparable = nil) # :nodoc:
32
+ def to_sar_and_binds(arel_or_sar_string, binds = [], preparable = nil, allow_retry = false)
32
33
  if arel_or_sar_string.respond_to?(:ast)
34
+ arel_or_sar_string = arel_or_sar_string.ast
35
+ end
36
+
37
+ if Arel.arel_node?(arel_or_sar_string) && !(String === arel_or_sar_string)
33
38
  unless binds.empty?
34
39
  raise "Passing bind parameters with an arel AST is forbidden. " \
35
40
  "The values must be stored on the AST directly"
36
41
  end
37
- sar = visitor.accept(arel_or_sar_string.ast, collector)
38
- [sar.freeze, sar.binds, false]
42
+
43
+ sar = visitor.accept(arel_or_sar_string, collector)
44
+ [sar.freeze, sar.binds, false, allow_retry]
39
45
  else
40
- [arel_or_sar_string.dup.freeze, binds, false]
46
+ [arel_or_sar_string.dup.freeze, binds, false, allow_retry]
41
47
  end
42
48
  end
43
49
 
50
+ def sar_for_insert(sql, pk, binds, returning)
51
+ # TODO: when StandardAPI supports returning we can do this; it might
52
+ # already need to investigate
53
+ to_sar_and_binds(sql, binds)
54
+ end
55
+
44
56
  # This is used in the StatementCache object. It returns an object that
45
57
  # can be used to query the database repeatedly.
46
58
  def cacheable_query(klass, arel) # :nodoc:
@@ -77,14 +89,33 @@ module ActiveRecord
77
89
  end
78
90
 
79
91
  # Returns an ActiveRecord::Result instance.
80
- def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
92
+ def select_all(arel, name = nil, binds = [], preparable: nil, async: false, allow_retry: false)
81
93
  arel = arel_from_relation(arel)
82
- sar, binds, preparable = to_sar_and_binds(arel, binds, preparable)
83
-
84
- select(sar, name, binds, prepare: prepared_statements && preparable, async: async && FutureResult::SelectAll)
94
+ sar, binds, preparable, allow_retry = to_sar_and_binds(arel, binds, preparable, allow_retry)
95
+
96
+ select(sar, name, binds,
97
+ prepare: prepared_statements && preparable,
98
+ async: async && FutureResult::SelectAll,
99
+ allow_retry: allow_retry
100
+ )
101
+ rescue ::RangeError
102
+ ActiveRecord::Result.empty(async: async)
103
+ end
104
+
105
+ # Executes insert +sql+ statement in the context of this connection using
106
+ # +binds+ as the bind substitutes. +name+ is logged along with
107
+ # the executed +sql+ statement.
108
+ # Some adapters support the `returning` keyword argument which allows to control the result of the query:
109
+ # `nil` is the default value and maintains default behavior. If an array of column names is passed -
110
+ # the result will contain values of the specified columns from the inserted row.
111
+ #
112
+ # TODO: Add support for returning
113
+ def exec_insert(arel, name = nil, binds = [], pk = nil, sequence_name = nil, returning: nil)
114
+ sar, binds = sar_for_insert(arel, pk, binds, returning)
115
+ internal_exec_query(sar, name, binds)
85
116
  end
86
117
 
87
- def exec_query(arel, name = 'SAR', binds = [], prepare: false)
118
+ def internal_exec_query(arel, name = 'SAR', binds = [], prepare: false, async: false, allow_retry: false)
88
119
  sars = []
89
120
  multiple_requests = arel.is_a?(Arel::Collectors::Sunstone)
90
121
  type_casted_binds = binds#type_casted_binds(binds)
@@ -112,11 +143,13 @@ module ActiveRecord
112
143
  sars.push(sar)
113
144
  log_mess = sar.path.split('?', 2)
114
145
  log("#{sar.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? MessagePack.unpack(CGI.unescape(log_mess[1])) : '' }", name) do
115
- response = @connection.send_request(sar)
116
- if response.is_a?(Net::HTTPNoContent)
117
- nil
118
- else
119
- JSON.parse(response.body)
146
+ with_raw_connection do |conn|
147
+ response = conn.send_request(sar)
148
+ if response.is_a?(Net::HTTPNoContent)
149
+ nil
150
+ else
151
+ JSON.parse(response.body)
152
+ end
120
153
  end
121
154
  end
122
155
  }
@@ -141,21 +174,21 @@ module ActiveRecord
141
174
 
142
175
  if sars[0].instance_variable_defined?(:@sunstone_calculation) && sars[0].instance_variable_get(:@sunstone_calculation)
143
176
  # this is a count, min, max.... yea i know..
144
- ActiveRecord::Result.new(['all'], [result], {:all => type_map.lookup('integer', {})})
177
+ ActiveRecord::Result.new(['all'], [result], {:all => @type_map.lookup('integer', {})})
145
178
  elsif result.is_a?(Array)
146
179
  ActiveRecord::Result.new(result[0] ? result[0].keys : [], result.map{|r| r.values})
147
180
  else
148
- ActiveRecord::Result.new(result.keys, [result])
181
+ ActiveRecord::Result.new(result.keys, [result.values])
149
182
  end
150
183
  end
151
184
 
152
- def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
185
+ def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [], returning: nil)
153
186
  sar, binds = to_sar_and_binds(arel, binds)
154
- value = exec_insert(sar, name, binds, pk, sequence_name)
187
+ value = exec_insert(sar, name, binds, pk, sequence_name, returning: returning)
188
+
189
+ return returning_column_values(value) unless returning.nil?
190
+
155
191
  id_value || last_inserted_id(value)
156
-
157
- # value = exec_insert(arel, name, binds, pk, sequence_name)
158
- # id_value || last_inserted_id(value)
159
192
  end
160
193
 
161
194
  def update(arel, name = nil, binds = [])
@@ -171,6 +204,10 @@ module ActiveRecord
171
204
  row && row['id']
172
205
  end
173
206
 
207
+ def returning_column_values(result)
208
+ result.rows.first
209
+ end
210
+
174
211
  end
175
212
  end
176
213
  end