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 +4 -4
- data/ext/active_record/associations/collection_association.rb +5 -28
- data/ext/active_record/associations.rb +12 -8
- data/ext/active_record/attribute_methods.rb +14 -13
- data/ext/active_record/callbacks.rb +4 -1
- data/ext/active_record/finder_methods.rb +14 -4
- data/ext/active_record/persistence.rb +58 -20
- data/ext/active_record/relation/calculations.rb +27 -7
- data/ext/active_record/relation/query_methods.rb +6 -4
- data/ext/active_record/transactions.rb +15 -13
- data/lib/active_record/connection_adapters/sunstone/column.rb +10 -0
- data/lib/active_record/connection_adapters/sunstone/database_statements.rb +58 -21
- data/lib/active_record/connection_adapters/sunstone/quoting.rb +19 -0
- data/lib/active_record/connection_adapters/sunstone/schema_statements.rb +6 -5
- data/lib/active_record/connection_adapters/sunstone/type/binary.rb +3 -3
- data/lib/active_record/connection_adapters/sunstone_adapter.rb +102 -75
- data/lib/arel/visitors/sunstone.rb +69 -58
- data/lib/sunstone/connection.rb +4 -4
- data/lib/sunstone/version.rb +1 -1
- data/lib/sunstone.rb +2 -14
- metadata +14 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d280487f58777eebd36b07eb69f9492b77370ea3def7b05321bb2d4fd8e55626
|
4
|
+
data.tar.gz: a34f616483aca20b1207f12538e08fafb19b16ac01db6c19977b902cd1cd1537
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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?(:@
|
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?(:@
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
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
|
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,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
|
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
|
-
|
11
|
-
|
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.
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
@
|
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
|
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
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
-
@
|
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
|
-
|
106
|
+
attribute_values = attributes_with_values(attribute_names)
|
107
|
+
returning_values = nil
|
84
108
|
|
85
|
-
|
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
|
-
|
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(
|
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
|
-
|
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.
|
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
|
-
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
38
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
38
|
-
|
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,
|
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
|
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
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|