sunstone 7.2.0 → 8.0.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/finder_methods.rb +5 -0
- data/ext/active_record/relation/calculations.rb +27 -6
- data/ext/active_record/relation/query_methods.rb +1 -1
- data/lib/active_record/connection_adapters/sunstone/database_statements.rb +72 -40
- data/lib/active_record/connection_adapters/sunstone_adapter.rb +19 -24
- data/lib/sunstone/version.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd0eae0dbdee21a95ca29317302b67b50647f7d6654af15553425f55d1d11aed
|
4
|
+
data.tar.gz: b0cdc960489411360b1ee4f2cb4cdcce93b7df2464dabdafa2bc26955be002b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce768f425153db1d5a2242f845bc3de221a4d0d0d8a30a1428c128d2bb1e4353ef986020283fdd1d17e7652937c38d03eb1f42478acbc694da32135f335cab22
|
7
|
+
data.tar.gz: ece020a27e0554bad07f0e831919e8969cebdd6970adc344fb4f018b3a45032588dcd7c4eb512d9fcb8ff4acfc09ef27d9fe6124fa2b9db0d5eeff659885d800
|
@@ -8,6 +8,11 @@ module ActiveRecord
|
|
8
8
|
return ["1=0"] if attributes.empty?
|
9
9
|
|
10
10
|
attributes.flat_map do |key, value|
|
11
|
+
if key.is_a?(Array) && key.size == 1
|
12
|
+
key = key.first
|
13
|
+
value = value.flatten
|
14
|
+
end
|
15
|
+
|
11
16
|
if key.is_a?(Array)
|
12
17
|
queries = Array(value).map do |ids_set|
|
13
18
|
raise ArgumentError, "Expected corresponding value for #{key} to be an Array" unless ids_set.is_a?(Array)
|
@@ -4,6 +4,27 @@
|
|
4
4
|
module ActiveRecord
|
5
5
|
module Calculations
|
6
6
|
|
7
|
+
# Prior to Rails 8 we didn't need this method becuase it would
|
8
|
+
# return the first value if there was just one - so we'll just
|
9
|
+
# do the same as prevously because it doesn't have to be joined
|
10
|
+
def select_for_count
|
11
|
+
if select_values.empty?
|
12
|
+
:all
|
13
|
+
else
|
14
|
+
with_connection do |conn|
|
15
|
+
# Rails compiles this to a string, but we don't have string we
|
16
|
+
# have a hash
|
17
|
+
if model.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
|
18
|
+
sv = arel_columns(select_values)
|
19
|
+
sv.one? ? sv.first : sv
|
20
|
+
else
|
21
|
+
sv = arel_columns(select_values).map { |column| conn.visitor.compile(column) }
|
22
|
+
sv.one? ? sv.first : sv.join(", ")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
7
28
|
def pluck(*column_names)
|
8
29
|
if @none
|
9
30
|
if @async
|
@@ -25,20 +46,20 @@ module ActiveRecord
|
|
25
46
|
if has_include?(column_names.first)
|
26
47
|
relation = apply_join_dependency
|
27
48
|
relation.pluck(*column_names)
|
28
|
-
elsif
|
49
|
+
elsif model.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
|
29
50
|
load
|
30
|
-
return records.pluck(*column_names.map{|n| n.to_s.sub(/^#{
|
51
|
+
return records.pluck(*column_names.map{|n| n.to_s.sub(/^#{model.table_name}\./, "")})
|
31
52
|
else
|
32
|
-
|
33
|
-
columns = arel_columns(column_names)
|
53
|
+
model.disallow_raw_sql!(flattened_args(column_names))
|
34
54
|
relation = spawn
|
55
|
+
columns = relation.arel_columns(column_names)
|
35
56
|
relation.select_values = columns
|
36
57
|
result = skip_query_cache_if_necessary do
|
37
58
|
if where_clause.contradiction?
|
38
59
|
ActiveRecord::Result.empty(async: @async)
|
39
60
|
else
|
40
|
-
|
41
|
-
c.select_all(relation.arel, "#{
|
61
|
+
model.with_connection do |c|
|
62
|
+
c.select_all(relation.arel, "#{model.name} Pluck", async: @async)
|
42
63
|
end
|
43
64
|
end
|
44
65
|
end
|
@@ -4,7 +4,7 @@ module ActiveRecord
|
|
4
4
|
|
5
5
|
def assert_modifiable!
|
6
6
|
raise UnmodifiableRelation if @loaded
|
7
|
-
raise UnmodifiableRelation if @arel && !
|
7
|
+
raise UnmodifiableRelation if @arel && !model.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
|
8
8
|
end
|
9
9
|
|
10
10
|
end
|
@@ -30,6 +30,7 @@ module ActiveRecord
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def to_sar_and_binds(arel_or_sar_string, binds = [], preparable = nil, allow_retry = false)
|
33
|
+
# Arel::TreeManager -> Arel::Node
|
33
34
|
if arel_or_sar_string.respond_to?(:ast)
|
34
35
|
arel_or_sar_string = arel_or_sar_string.ast
|
35
36
|
end
|
@@ -40,10 +41,13 @@ module ActiveRecord
|
|
40
41
|
"The values must be stored on the AST directly"
|
41
42
|
end
|
42
43
|
|
43
|
-
|
44
|
+
col = collector()
|
45
|
+
col.retryable = true
|
46
|
+
sar = visitor.compile(arel_or_sar_string, col)
|
44
47
|
[sar.freeze, sar.binds, false, allow_retry]
|
45
48
|
else
|
46
|
-
|
49
|
+
arel_or_sar_string = arel_or_sar_string.dup.freeze unless arel_or_sar_string.frozen?
|
50
|
+
[arel_or_sar_string, binds, false, allow_retry]
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
@@ -115,8 +119,8 @@ module ActiveRecord
|
|
115
119
|
internal_exec_query(sar, name, binds)
|
116
120
|
end
|
117
121
|
|
118
|
-
|
119
|
-
|
122
|
+
# Lowest level way to execute a query. Doesn't check for illegal writes, doesn't annotate queries, yields a native result object.
|
123
|
+
def raw_execute(arel, name = nil, binds = [], prepare: false, async: false, allow_retry: false, materialize_transactions: true, batch: false)
|
120
124
|
multiple_requests = arel.is_a?(Arel::Collectors::Sunstone)
|
121
125
|
type_casted_binds = binds#type_casted_binds(binds)
|
122
126
|
|
@@ -137,50 +141,73 @@ module ActiveRecord
|
|
137
141
|
multiple_requests = true
|
138
142
|
end
|
139
143
|
end
|
140
|
-
|
141
|
-
send_request = lambda { |req_arel|
|
144
|
+
|
145
|
+
send_request = lambda { |conn, req_arel, batch|
|
142
146
|
sar = to_sar(req_arel, type_casted_binds)
|
143
|
-
sars.push(sar)
|
144
147
|
log_mess = sar.path.split('?', 2)
|
145
|
-
log("#{sar.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? MessagePack.unpack(CGI.unescape(log_mess[1])) : '' }", name) do
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
148
|
+
log("#{sar.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? MessagePack.unpack(CGI.unescape(log_mess[1])) : '' }", name) do |notification_payload|
|
149
|
+
result = perform_query(conn, sar, prepare:, notification_payload:, batch: batch)
|
150
|
+
result.instance_variable_set(:@sunstone_calculation, true) if result && sar.instance_variable_get(:@sunstone_calculation)
|
151
|
+
result
|
152
|
+
end
|
153
|
+
}
|
154
|
+
|
155
|
+
result = with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
|
156
|
+
if multiple_requests
|
157
|
+
binds.delete_at(limit_bind_index) if limit_bind_index
|
158
|
+
|
159
|
+
limit, offset, results = allowed_limit, 0, nil
|
160
|
+
last_affected_rows = 0
|
161
|
+
while requested_limit ? offset < requested_limit : true
|
162
|
+
split_arel = arel.dup
|
163
|
+
split_arel.limit = limit
|
164
|
+
split_arel.offset = offset
|
165
|
+
request_results = send_request.call(conn, split_arel, true)
|
166
|
+
last_affected_rows += @last_affected_rows
|
167
|
+
if results
|
168
|
+
results.push(*request_results)
|
150
169
|
else
|
151
|
-
|
170
|
+
results = request_results
|
152
171
|
end
|
172
|
+
break if request_results.size < limit
|
173
|
+
offset = offset + limit
|
153
174
|
end
|
175
|
+
@last_affected_rows = last_affected_rows
|
176
|
+
results
|
177
|
+
else
|
178
|
+
send_request.call(conn, arel, true)
|
154
179
|
end
|
155
|
-
}
|
156
|
-
|
157
|
-
result = if multiple_requests
|
158
|
-
binds.delete_at(limit_bind_index) if limit_bind_index
|
159
|
-
|
160
|
-
limit, offset, results = allowed_limit, 0, []
|
161
|
-
while requested_limit ? offset < requested_limit : true
|
162
|
-
split_arel = arel.dup
|
163
|
-
split_arel.limit = limit
|
164
|
-
split_arel.offset = offset
|
165
|
-
request_results = send_request.call(split_arel)
|
166
|
-
results = results + request_results
|
167
|
-
break if request_results.size < limit
|
168
|
-
offset = offset + limit
|
169
|
-
end
|
170
|
-
results
|
171
|
-
else
|
172
|
-
send_request.call(arel)
|
173
180
|
end
|
174
|
-
|
175
|
-
|
181
|
+
|
182
|
+
result
|
183
|
+
end
|
184
|
+
|
185
|
+
def perform_query(raw_connection, sar, prepare:, notification_payload:, batch: false)
|
186
|
+
response = raw_connection.send_request(sar)
|
187
|
+
result = response.is_a?(Net::HTTPNoContent) ? nil : JSON.parse(response.body)
|
188
|
+
|
189
|
+
verified!
|
190
|
+
# handle_warnings(result)
|
191
|
+
@last_affected_rows = response['Affected-Rows'] || result&.count || 0
|
192
|
+
notification_payload[:row_count] = @last_affected_rows
|
193
|
+
result
|
194
|
+
end
|
195
|
+
|
196
|
+
# Receive a native adapter result object and returns an ActiveRecord::Result object.
|
197
|
+
def cast_result(raw_result)
|
198
|
+
if raw_result.instance_variable_defined?(:@sunstone_calculation) && raw_result.instance_variable_get(:@sunstone_calculation)
|
176
199
|
# this is a count, min, max.... yea i know..
|
177
|
-
ActiveRecord::Result.new(['all'], [
|
178
|
-
elsif
|
179
|
-
ActiveRecord::Result.new(
|
200
|
+
ActiveRecord::Result.new(['all'], [raw_result], {:all => @type_map.lookup('integer', {})})
|
201
|
+
elsif raw_result.is_a?(Array)
|
202
|
+
ActiveRecord::Result.new(raw_result[0] ? raw_result[0].keys : [], raw_result.map{|r| r.values})
|
180
203
|
else
|
181
|
-
ActiveRecord::Result.new(
|
204
|
+
ActiveRecord::Result.new(raw_result.keys, [raw_result.values])
|
182
205
|
end
|
183
206
|
end
|
207
|
+
|
208
|
+
def affected_rows(raw_result)
|
209
|
+
@last_affected_rows
|
210
|
+
end
|
184
211
|
|
185
212
|
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [], returning: nil)
|
186
213
|
sar, binds = to_sar_and_binds(arel, binds)
|
@@ -190,13 +217,18 @@ module ActiveRecord
|
|
190
217
|
|
191
218
|
id_value || last_inserted_id(value)
|
192
219
|
end
|
193
|
-
|
220
|
+
alias create insert
|
221
|
+
|
222
|
+
# Executes the update statement and returns the number of rows affected.
|
194
223
|
def update(arel, name = nil, binds = [])
|
195
|
-
|
224
|
+
sar, binds = to_sar_and_binds(arel, binds)
|
225
|
+
internal_exec_query(sar, name, binds)
|
196
226
|
end
|
197
227
|
|
228
|
+
# Executes the delete statement and returns the number of rows affected.
|
198
229
|
def delete(arel, name = nil, binds = [])
|
199
|
-
|
230
|
+
sql, binds = to_sar_and_binds(arel, binds)
|
231
|
+
exec_delete(sql, name, binds)
|
200
232
|
end
|
201
233
|
|
202
234
|
def last_inserted_id(result)
|
@@ -92,18 +92,30 @@ module ActiveRecord
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def active?
|
95
|
-
@
|
95
|
+
@lock.synchronize do
|
96
|
+
@raw_connection&.active?
|
97
|
+
end
|
96
98
|
end
|
97
99
|
|
98
|
-
|
99
|
-
|
100
|
-
|
100
|
+
# Connects to a StandardAPI server and sets up the adapter depending
|
101
|
+
# on the connected server's characteristics.
|
102
|
+
def connect
|
103
|
+
@raw_connection = self.class.new_client(@connection_parameters)
|
101
104
|
end
|
102
105
|
|
106
|
+
def reconnect
|
107
|
+
@lock.synchronize do
|
108
|
+
@raw_connection&.reconnect!
|
109
|
+
connect unless @raw_connection
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
103
113
|
def disconnect!
|
104
|
-
|
105
|
-
|
106
|
-
|
114
|
+
@lock.synchronize do
|
115
|
+
super
|
116
|
+
@raw_connection&.disconnect!
|
117
|
+
@raw_connection = nil
|
118
|
+
end
|
107
119
|
end
|
108
120
|
|
109
121
|
def discard! # :nodoc:
|
@@ -111,12 +123,6 @@ module ActiveRecord
|
|
111
123
|
@raw_connection = nil
|
112
124
|
end
|
113
125
|
|
114
|
-
# Executes the delete statement and returns the number of rows affected.
|
115
|
-
def delete(arel, name = nil, binds = [])
|
116
|
-
r = exec_delete(arel, name, binds)
|
117
|
-
r.rows.first.to_i
|
118
|
-
end
|
119
|
-
|
120
126
|
def native_database_types #:nodoc:
|
121
127
|
NATIVE_DATABASE_TYPES
|
122
128
|
end
|
@@ -189,17 +195,6 @@ module ActiveRecord
|
|
189
195
|
end
|
190
196
|
alias create insert
|
191
197
|
|
192
|
-
# Connects to a StandardAPI server and sets up the adapter depending
|
193
|
-
# on the connected server's characteristics.
|
194
|
-
def connect
|
195
|
-
@raw_connection = self.class.new_client(@connection_parameters)
|
196
|
-
end
|
197
|
-
|
198
|
-
def reconnect
|
199
|
-
@raw_connection&.reconnect!
|
200
|
-
connect unless @raw_connection
|
201
|
-
end
|
202
|
-
|
203
198
|
# Configures the encoding, verbosity, schema search path, and time zone of the connection.
|
204
199
|
# This is called by #connect and should not be called manually.
|
205
200
|
def configure_connection
|
data/lib/sunstone/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sunstone
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 8.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Bracy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -226,14 +226,14 @@ dependencies:
|
|
226
226
|
requirements:
|
227
227
|
- - ">="
|
228
228
|
- !ruby/object:Gem::Version
|
229
|
-
version:
|
229
|
+
version: 8.0.1
|
230
230
|
type: :runtime
|
231
231
|
prerelease: false
|
232
232
|
version_requirements: !ruby/object:Gem::Requirement
|
233
233
|
requirements:
|
234
234
|
- - ">="
|
235
235
|
- !ruby/object:Gem::Version
|
236
|
-
version:
|
236
|
+
version: 8.0.1
|
237
237
|
- !ruby/object:Gem::Dependency
|
238
238
|
name: arel-extensions
|
239
239
|
requirement: !ruby/object:Gem::Requirement
|
@@ -324,7 +324,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
324
324
|
- !ruby/object:Gem::Version
|
325
325
|
version: '0'
|
326
326
|
requirements: []
|
327
|
-
rubygems_version: 3.5.
|
327
|
+
rubygems_version: 3.5.21
|
328
328
|
signing_key:
|
329
329
|
specification_version: 4
|
330
330
|
summary: A library for interacting with REST APIs
|