sunstone 6.1.3 → 7.1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|