sunstone 7.0.0 → 7.2.0

Sign up to get free protection for your applications and to get access to all the features.
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