sunstone 6.1.3 → 7.1.0.1
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 +4 -26
- data/ext/active_record/associations.rb +5 -1
- data/ext/active_record/attribute_methods.rb +21 -14
- data/ext/active_record/callbacks.rb +4 -1
- data/ext/active_record/finder_methods.rb +26 -16
- data/ext/active_record/persistence.rb +58 -21
- data/ext/active_record/relation/calculations.rb +15 -5
- data/ext/active_record/relation/query_methods.rb +1 -1
- data/ext/active_record/statement_cache.rb +0 -1
- data/ext/active_record/transactions.rb +2 -2
- data/ext/arel/nodes/select_statement.rb +3 -3
- data/lib/active_record/connection_adapters/sunstone/column.rb +11 -1
- data/lib/active_record/connection_adapters/sunstone/database_statements.rb +54 -21
- data/lib/active_record/connection_adapters/sunstone/schema_statements.rb +35 -17
- data/lib/active_record/connection_adapters/sunstone/type/binary.rb +3 -3
- data/lib/active_record/connection_adapters/sunstone_adapter.rb +109 -60
- data/lib/arel/collectors/sunstone.rb +25 -4
- data/lib/arel/visitors/sunstone.rb +81 -75
- data/lib/sunstone/connection.rb +42 -15
- data/lib/sunstone/version.rb +1 -1
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3956ea045dce2994b10bcac8535462bdf08597b85d7e15fc325110149a576aa6
|
4
|
+
data.tar.gz: 02be730df372f32557112e9fb618befb5aafd7a8ef15ce1e12a866f8c18c2ed7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c978ff5919d301007ccd326a632ed915cce129584e0ff9c25c199bddb9a65e517361f95a7d3a8af4ea70546acd1bb16fbc1118ff050a0c209f4168f9ec71feb9
|
7
|
+
data.tar.gz: 3a24f347b5ca8ccf2816e8d50a28ca3effedea79a897ab3692801b5cd8095d9fc324f37f792ffba621a9669eb7ea92f58be762b62d2a1e9096a9306fc1d46be9
|
@@ -1,3 +1,5 @@
|
|
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
|
@@ -8,7 +10,7 @@ module ActiveRecord
|
|
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) &&
|
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)
|
@@ -70,27 +72,3 @@ module ActiveRecord
|
|
70
72
|
|
71
73
|
end
|
72
74
|
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
|
@@ -44,4 +48,4 @@ module ActiveRecord
|
|
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 ||= {}
|
@@ -97,10 +98,16 @@ module ActiveRecord
|
|
97
98
|
[]
|
98
99
|
else
|
99
100
|
association.target.select { |r| !r.destroyed? }.map do |record|
|
100
|
-
record.send(
|
101
|
+
record.send(
|
102
|
+
:attributes_with_values,
|
103
|
+
record.new_record? ?
|
104
|
+
record.send(:attribute_names_for_partial_inserts)
|
105
|
+
:
|
106
|
+
record.send(:attribute_names_for_partial_updates) + [record.class.primary_key]
|
107
|
+
)
|
101
108
|
end
|
102
109
|
end
|
103
|
-
|
110
|
+
|
104
111
|
association.instance_variable_set(:@sunstone_changed, false)
|
105
112
|
end
|
106
113
|
|
@@ -108,6 +115,6 @@ module ActiveRecord
|
|
108
115
|
association.reset_scope if association.respond_to?(:reset_scope)
|
109
116
|
end
|
110
117
|
end
|
111
|
-
|
118
|
+
|
112
119
|
end
|
113
120
|
end
|
@@ -1,13 +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
|
9
|
-
|
10
|
-
|
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)
|
18
|
+
ka = table.associated_table(key, &block)
|
19
|
+
.predicate_builder.expand_from_hash(value.stringify_keys)
|
20
|
+
|
21
|
+
if self.table.instance_variable_get(:@klass).connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
|
11
22
|
ka.each { |k|
|
12
23
|
if k.left.is_a?(Arel::Attributes::Attribute) || k.left.is_a?(Arel::Attributes::Relation)
|
13
24
|
k.left = Arel::Attributes::Relation.new(k.left, key)
|
@@ -23,11 +34,8 @@ module ActiveRecord
|
|
23
34
|
# PriceEstimate.where(estimate_of: treasure)
|
24
35
|
associated_table = table.associated_table(key)
|
25
36
|
if associated_table.polymorphic_association?
|
26
|
-
|
27
|
-
|
28
|
-
value = [value] unless value.is_a?(Array)
|
29
|
-
klass = PolymorphicArrayValue
|
30
|
-
end
|
37
|
+
value = [value] unless value.is_a?(Array)
|
38
|
+
klass = PolymorphicArrayValue
|
31
39
|
elsif associated_table.through_association?
|
32
40
|
next associated_table.predicate_builder.expand_from_hash(
|
33
41
|
associated_table.primary_key => value
|
@@ -36,7 +44,9 @@ module ActiveRecord
|
|
36
44
|
|
37
45
|
klass ||= AssociationQueryValue
|
38
46
|
queries = klass.new(associated_table, value).queries.map! do |query|
|
39
|
-
|
47
|
+
# If the query produced is identical to attributes don't go any deeper.
|
48
|
+
# Prevents stack level too deep errors when association and foreign_key are identical.
|
49
|
+
query == attributes ? self[key, value] : expand_from_hash(query)
|
40
50
|
end
|
41
51
|
|
42
52
|
grouping_queries(queries)
|
@@ -202,7 +212,7 @@ module ActiveRecord
|
|
202
212
|
relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
|
203
213
|
end
|
204
214
|
|
205
|
-
if eager_loading && !(
|
215
|
+
if eager_loading && has_limit_or_offset? && !(
|
206
216
|
using_limitable_reflections?(join_dependency.reflections) &&
|
207
217
|
using_limitable_reflections?(
|
208
218
|
construct_join_dependency(
|
@@ -211,12 +221,12 @@ module ActiveRecord
|
|
211
221
|
), nil
|
212
222
|
).reflections
|
213
223
|
)
|
214
|
-
|
215
|
-
if
|
216
|
-
|
217
|
-
|
224
|
+
)
|
225
|
+
if !connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
|
226
|
+
relation = skip_query_cache_if_necessary do
|
227
|
+
klass.connection.distinct_relation_for_primary_key(relation)
|
228
|
+
end
|
218
229
|
end
|
219
|
-
relation.limit_value = relation.offset_value = nil
|
220
230
|
end
|
221
231
|
|
222
232
|
if block_given?
|
@@ -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,36 +95,50 @@ 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
|
-
attribute_names
|
83
|
-
|
105
|
+
attribute_names = attributes_for_create(attribute_names)
|
106
|
+
attribute_values = attributes_with_values(attribute_names)
|
107
|
+
|
108
|
+
returning_columns = self.class._returning_columns_for_insert
|
84
109
|
|
85
|
-
|
110
|
+
returning_values = self.class._insert_record(
|
111
|
+
attribute_values,
|
112
|
+
returning_columns
|
113
|
+
)
|
114
|
+
|
115
|
+
if !self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
|
116
|
+
returning_columns.zip(returning_values).each do |column, value|
|
117
|
+
_write_attribute(column, value) if !_read_attribute(column)
|
118
|
+
end if returning_values
|
119
|
+
end
|
86
120
|
|
87
121
|
@new_record = false
|
122
|
+
@previously_new_record = true
|
123
|
+
|
124
|
+
yield(self) if block_given?
|
88
125
|
|
89
126
|
if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
|
90
|
-
|
127
|
+
returning_values
|
91
128
|
else
|
92
|
-
self.id ||= new_id if self.class.primary_key
|
93
129
|
id
|
94
130
|
end
|
95
131
|
end
|
96
|
-
|
132
|
+
|
97
133
|
def _update_record(attribute_names = self.attribute_names)
|
134
|
+
attribute_names = attributes_for_update(attribute_names)
|
98
135
|
attribute_values = attributes_with_values(attribute_names)
|
99
136
|
|
100
137
|
if attribute_values.empty?
|
101
138
|
affected_rows = 0
|
102
139
|
@_trigger_update_callback = true
|
103
140
|
else
|
104
|
-
affected_rows = self.class._update_record(
|
141
|
+
affected_rows = self.class._update_record(attribute_values, _query_constraints_hash)
|
105
142
|
@_trigger_update_callback = affected_rows == 1
|
106
143
|
end
|
107
144
|
|
@@ -1,8 +1,11 @@
|
|
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)
|
5
|
-
if loaded? && (column_names
|
8
|
+
if loaded? && all_attributes?(column_names)
|
6
9
|
return records.pluck(*column_names)
|
7
10
|
end
|
8
11
|
|
@@ -14,10 +17,17 @@ module ActiveRecord
|
|
14
17
|
return records.pluck(*column_names.map{|n| n.to_s.sub(/^#{klass.table_name}\./, "")})
|
15
18
|
else
|
16
19
|
klass.disallow_raw_sql!(column_names)
|
20
|
+
columns = arel_columns(column_names)
|
17
21
|
relation = spawn
|
18
|
-
relation.select_values =
|
19
|
-
result = skip_query_cache_if_necessary
|
20
|
-
|
22
|
+
relation.select_values = columns
|
23
|
+
result = skip_query_cache_if_necessary do
|
24
|
+
if where_clause.contradiction?
|
25
|
+
ActiveRecord::Result.empty
|
26
|
+
else
|
27
|
+
klass.connection.select_all(relation.arel, "#{klass.name} Pluck")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
type_cast_pluck_values(result, columns)
|
21
31
|
end
|
22
32
|
end
|
23
33
|
|
@@ -3,7 +3,7 @@ module ActiveRecord
|
|
3
3
|
private
|
4
4
|
def assert_mutability!
|
5
5
|
raise ImmutableRelation if @loaded
|
6
|
-
raise ImmutableRelation if defined?(@arel) && !klass.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
|
6
|
+
raise ImmutableRelation if defined?(@arel) && @arel && !klass.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -36,8 +36,8 @@ module ActiveRecord
|
|
36
36
|
def with_transaction_returning_status
|
37
37
|
status = nil
|
38
38
|
connection = self.class.connection
|
39
|
-
|
40
|
-
if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && instance_variable_defined?(:@
|
39
|
+
|
40
|
+
if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && instance_variable_defined?(:@sunstone_updating) && @sunstone_updating
|
41
41
|
status = yield
|
42
42
|
else
|
43
43
|
ensure_finalize = !connection.transaction_open?
|
@@ -4,9 +4,9 @@ module Arel
|
|
4
4
|
|
5
5
|
attr_accessor :eager_load
|
6
6
|
|
7
|
-
def initialize(
|
7
|
+
def initialize(relation = nil)
|
8
8
|
super()
|
9
|
-
@cores =
|
9
|
+
@cores = [SelectCore.new(relation)]
|
10
10
|
@orders = []
|
11
11
|
@limit = nil
|
12
12
|
@lock = nil
|
@@ -36,7 +36,7 @@ module Arel
|
|
36
36
|
self.with == other.with &&
|
37
37
|
self.eager_load == other.eager_load
|
38
38
|
end
|
39
|
-
|
39
|
+
alias :== :eql?
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -2,24 +2,34 @@ 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={})
|
8
10
|
@name = name.freeze
|
9
11
|
@sql_type_metadata = sql_type_metadata
|
10
12
|
@null = options['null']
|
11
|
-
@default =
|
13
|
+
@default = options['default'] ? JSON.generate(options['default']) : options['default']
|
12
14
|
@default_function = nil
|
13
15
|
@collation = nil
|
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,24 +25,35 @@ 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 = []) # :nodoc:
|
32
|
+
def to_sar_and_binds(arel_or_sar_string, binds = [], preparable = nil) # :nodoc:
|
33
|
+
# Arel::TreeManager -> Arel::Node
|
32
34
|
if arel_or_sar_string.respond_to?(:ast)
|
35
|
+
arel_or_sar_string = arel_or_sar_string.ast
|
36
|
+
end
|
37
|
+
|
38
|
+
if Arel.arel_node?(arel_or_sar_string) && !(String === arel_or_sar_string)
|
33
39
|
unless binds.empty?
|
34
40
|
raise "Passing bind parameters with an arel AST is forbidden. " \
|
35
41
|
"The values must be stored on the AST directly"
|
36
42
|
end
|
37
|
-
|
38
|
-
|
39
|
-
[sar.freeze, sar.binds]
|
43
|
+
|
44
|
+
sar = visitor.accept(arel_or_sar_string, collector)
|
45
|
+
[sar.freeze, sar.binds, false]
|
40
46
|
else
|
41
|
-
|
42
|
-
[arel_or_sar_string.dup.freeze, binds]
|
47
|
+
[arel_or_sar_string.dup.freeze, binds, false]
|
43
48
|
end
|
44
49
|
end
|
45
50
|
|
51
|
+
def sar_for_insert(sql, pk, binds, returning)
|
52
|
+
# TODO: when StandardAPI supports returning we can do this; it might
|
53
|
+
# already need to investigate
|
54
|
+
to_sar_and_binds(sql, binds)
|
55
|
+
end
|
56
|
+
|
46
57
|
# This is used in the StatementCache object. It returns an object that
|
47
58
|
# can be used to query the database repeatedly.
|
48
59
|
def cacheable_query(klass, arel) # :nodoc:
|
@@ -79,13 +90,29 @@ module ActiveRecord
|
|
79
90
|
end
|
80
91
|
|
81
92
|
# Returns an ActiveRecord::Result instance.
|
82
|
-
def select_all(arel, name = nil, binds = [], preparable: nil)
|
93
|
+
def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
|
83
94
|
arel = arel_from_relation(arel)
|
84
|
-
sar, binds = to_sar_and_binds(arel, binds)
|
85
|
-
|
95
|
+
sar, binds, preparable = to_sar_and_binds(arel, binds, preparable)
|
96
|
+
|
97
|
+
select(sar, name, binds, prepare: prepared_statements && preparable, async: async && FutureResult::SelectAll)
|
98
|
+
rescue ::RangeError
|
99
|
+
ActiveRecord::Result.empty(async: async)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Executes insert +sql+ statement in the context of this connection using
|
103
|
+
# +binds+ as the bind substitutes. +name+ is logged along with
|
104
|
+
# the executed +sql+ statement.
|
105
|
+
# Some adapters support the `returning` keyword argument which allows to control the result of the query:
|
106
|
+
# `nil` is the default value and maintains default behavior. If an array of column names is passed -
|
107
|
+
# the result will contain values of the specified columns from the inserted row.
|
108
|
+
#
|
109
|
+
# TODO: Add support for returning
|
110
|
+
def exec_insert(arel, name = nil, binds = [], pk = nil, sequence_name = nil, returning: nil)
|
111
|
+
sar, binds = sar_for_insert(arel, pk, binds, returning)
|
112
|
+
internal_exec_query(sar, name, binds)
|
86
113
|
end
|
87
114
|
|
88
|
-
def
|
115
|
+
def internal_exec_query(arel, name = 'SAR', binds = [], prepare: false, async: false, allow_retry: false, materialize_transactions: true)
|
89
116
|
sars = []
|
90
117
|
multiple_requests = arel.is_a?(Arel::Collectors::Sunstone)
|
91
118
|
type_casted_binds = binds#type_casted_binds(binds)
|
@@ -96,7 +123,7 @@ module ActiveRecord
|
|
96
123
|
requested_limit = if limit_bind_index
|
97
124
|
type_casted_binds[limit_bind_index]
|
98
125
|
else
|
99
|
-
arel.limit
|
126
|
+
arel.limit
|
100
127
|
end
|
101
128
|
|
102
129
|
if allowed_limit.nil?
|
@@ -113,11 +140,13 @@ module ActiveRecord
|
|
113
140
|
sars.push(sar)
|
114
141
|
log_mess = sar.path.split('?', 2)
|
115
142
|
log("#{sar.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? MessagePack.unpack(CGI.unescape(log_mess[1])) : '' }", name) do
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
143
|
+
with_raw_connection do |conn|
|
144
|
+
response = conn.send_request(sar)
|
145
|
+
if response.is_a?(Net::HTTPNoContent)
|
146
|
+
nil
|
147
|
+
else
|
148
|
+
JSON.parse(response.body)
|
149
|
+
end
|
121
150
|
end
|
122
151
|
end
|
123
152
|
}
|
@@ -142,21 +171,21 @@ module ActiveRecord
|
|
142
171
|
|
143
172
|
if sars[0].instance_variable_defined?(:@sunstone_calculation) && sars[0].instance_variable_get(:@sunstone_calculation)
|
144
173
|
# this is a count, min, max.... yea i know..
|
145
|
-
ActiveRecord::Result.new(['all'], [result], {:all => type_map.lookup('integer', {})})
|
174
|
+
ActiveRecord::Result.new(['all'], [result], {:all => @type_map.lookup('integer', {})})
|
146
175
|
elsif result.is_a?(Array)
|
147
176
|
ActiveRecord::Result.new(result[0] ? result[0].keys : [], result.map{|r| r.values})
|
148
177
|
else
|
149
|
-
ActiveRecord::Result.new(result.keys, [result])
|
178
|
+
ActiveRecord::Result.new(result.keys, [result.values])
|
150
179
|
end
|
151
180
|
end
|
152
181
|
|
153
182
|
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
|
154
183
|
sar, binds = to_sar_and_binds(arel, binds)
|
155
184
|
value = exec_insert(sar, name, binds, pk, sequence_name)
|
185
|
+
|
186
|
+
return returning_column_values(value) unless returning.nil?
|
187
|
+
|
156
188
|
id_value || last_inserted_id(value)
|
157
|
-
|
158
|
-
# value = exec_insert(arel, name, binds, pk, sequence_name)
|
159
|
-
# id_value || last_inserted_id(value)
|
160
189
|
end
|
161
190
|
|
162
191
|
def update(arel, name = nil, binds = [])
|
@@ -172,6 +201,10 @@ module ActiveRecord
|
|
172
201
|
row && row['id']
|
173
202
|
end
|
174
203
|
|
204
|
+
def returning_column_values(result)
|
205
|
+
result.rows.first
|
206
|
+
end
|
207
|
+
|
175
208
|
end
|
176
209
|
end
|
177
210
|
end
|