sunstone 6.1.0.2 → 7.0.0

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/ext/active_record/associations/collection_association.rb +1 -1
  3. data/ext/active_record/attribute_methods.rb +7 -1
  4. data/ext/active_record/finder_methods.rb +14 -13
  5. data/ext/active_record/persistence.rb +6 -3
  6. data/ext/active_record/relation/calculations.rb +11 -4
  7. data/ext/active_record/relation/query_methods.rb +1 -1
  8. data/ext/active_record/statement_cache.rb +0 -1
  9. data/ext/arel/nodes/select_statement.rb +3 -3
  10. data/lib/active_record/connection_adapters/sunstone/column.rb +1 -1
  11. data/lib/active_record/connection_adapters/sunstone/database_statements.rb +8 -9
  12. data/lib/active_record/connection_adapters/sunstone/schema_statements.rb +31 -14
  13. data/lib/active_record/connection_adapters/sunstone_adapter.rb +17 -7
  14. data/lib/arel/collectors/sunstone.rb +25 -4
  15. data/lib/arel/visitors/sunstone.rb +21 -26
  16. data/lib/sunstone/connection.rb +40 -13
  17. data/lib/sunstone/version.rb +1 -1
  18. metadata +21 -61
  19. data/.github/workflows/main.yml +0 -141
  20. data/.gitignore +0 -31
  21. data/.tm_properties +0 -1
  22. data/Gemfile +0 -4
  23. data/README.md +0 -46
  24. data/Rakefile +0 -37
  25. data/TODO.md +0 -89
  26. data/sunstone.gemspec +0 -40
  27. data/test/active_record/associations/belongs_to_test.rb +0 -162
  28. data/test/active_record/associations/has_and_belongs_to_many_test.rb +0 -125
  29. data/test/active_record/associations/has_many_test.rb +0 -244
  30. data/test/active_record/eager_loading_test.rb +0 -62
  31. data/test/active_record/persistance_test.rb +0 -184
  32. data/test/active_record/preload_test.rb +0 -51
  33. data/test/active_record/query/all_test.rb +0 -33
  34. data/test/active_record/query/count_test.rb +0 -51
  35. data/test/active_record/query/distinct_test.rb +0 -30
  36. data/test/active_record/query/find_test.rb +0 -37
  37. data/test/active_record/query/limit_test.rb +0 -19
  38. data/test/active_record/query/order_test.rb +0 -27
  39. data/test/active_record/query/where_test.rb +0 -79
  40. data/test/active_record/query_test.rb +0 -131
  41. data/test/active_record/rpc_test.rb +0 -30
  42. data/test/schema_mock.rb +0 -121
  43. data/test/sunstone/connection/column_definition_test.rb +0 -30
  44. data/test/sunstone/connection/configuration_test.rb +0 -44
  45. data/test/sunstone/connection/cookie_store_test.rb +0 -37
  46. data/test/sunstone/connection/request_helper_test.rb +0 -105
  47. data/test/sunstone/connection/send_request_test.rb +0 -164
  48. data/test/sunstone/connection_test.rb +0 -23
  49. data/test/test_helper.rb +0 -153
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52f0e0a557ddc1ec6d7dcc9728d3cfbf602d8c467d1647571cb887b56755e3cc
4
- data.tar.gz: 8db1bd8849700b80328ac2cf1248ff5260659d0afc49648e694fae33790c79cc
3
+ metadata.gz: 02df1d75e40c2ef207e6e1f329068c95098f5b99758d1bcea603e157ed2c1f40
4
+ data.tar.gz: 4807c8a530f9c7f09448a08bea1dbe015724f2afb53d81b86cf5cef6d6b49dcf
5
5
  SHA512:
6
- metadata.gz: a656ce5545ac0ad4a3f660f61857e8068a9c1f59060d4e9f9f06b1d80d2f6daca73e3317e02b35669a100ea1f8c578695f8ca0cc3a9eb2f00fc908708c1d18ff
7
- data.tar.gz: 3395da82c6d52adc2029570a459f98cb7311c428a3f92c9f598d61ae8f0b7c5c7a354bb4d88933a6096e2cd5271997f929535f9ad2a35cda2c066d59472dae72
6
+ metadata.gz: e884525eda7c249da0f4decbadff3d27ff97859eac4874e1c20b4b0e10c80d6d96ee49419d27bd2f6d429c55c93485bfe1961451ff8396d101e37752ec39ac6d
7
+ data.tar.gz: 4323252706192a940b6f730a6c46324d4c40729df5864a5d1aafc4283764ef159284ddefe9b1335a7d9174b6716d11a2d0da4aa59dbdfbc3ac7cdccc537b06f8
@@ -41,7 +41,7 @@ module ActiveRecord
41
41
  end
42
42
 
43
43
  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))
44
+ if record.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && owner.instance_variable_defined?(:@updating) && owner.instance_variable_get(:@updating)
45
45
  true
46
46
  elsif raise
47
47
  record.save!(validate: validate, &block)
@@ -97,7 +97,13 @@ module ActiveRecord
97
97
  []
98
98
  else
99
99
  association.target.select { |r| !r.destroyed? }.map do |record|
100
- record.send(:attributes_with_values, record.send(:attribute_names_for_partial_writes) + (record.new_record? ? [] : [record.class.primary_key]))
100
+ record.send(
101
+ :attributes_with_values,
102
+ record.new_record? ?
103
+ record.send(:attribute_names_for_partial_inserts)
104
+ :
105
+ record.send(:attribute_names_for_partial_updates) + [record.class.primary_key]
106
+ )
101
107
  end
102
108
  end
103
109
 
@@ -6,7 +6,8 @@ module ActiveRecord
6
6
 
7
7
  attributes.flat_map do |key, value|
8
8
  if value.is_a?(Hash) && !table.has_column?(key)
9
- ka = table.associated_table(key, &block).predicate_builder.expand_from_hash(value.stringify_keys)
9
+ ka = table.associated_table(key, &block)
10
+ .predicate_builder.expand_from_hash(value.stringify_keys)
10
11
  if self.send(:table).instance_variable_get(:@klass).connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
11
12
  ka.each { |k|
12
13
  if k.left.is_a?(Arel::Attributes::Attribute) || k.left.is_a?(Arel::Attributes::Relation)
@@ -23,11 +24,8 @@ module ActiveRecord
23
24
  # PriceEstimate.where(estimate_of: treasure)
24
25
  associated_table = table.associated_table(key)
25
26
  if associated_table.polymorphic_association?
26
- case value.is_a?(Array) ? value.first : value
27
- when Base, Relation
28
- value = [value] unless value.is_a?(Array)
29
- klass = PolymorphicArrayValue
30
- end
27
+ value = [value] unless value.is_a?(Array)
28
+ klass = PolymorphicArrayValue
31
29
  elsif associated_table.through_association?
32
30
  next associated_table.predicate_builder.expand_from_hash(
33
31
  associated_table.primary_key => value
@@ -36,7 +34,9 @@ module ActiveRecord
36
34
 
37
35
  klass ||= AssociationQueryValue
38
36
  queries = klass.new(associated_table, value).queries.map! do |query|
39
- expand_from_hash(query)
37
+ # If the query produced is identical to attributes don't go any deeper.
38
+ # Prevents stack level too deep errors when association and foreign_key are identical.
39
+ query == attributes ? self[key, value] : expand_from_hash(query)
40
40
  end
41
41
 
42
42
  grouping_queries(queries)
@@ -202,7 +202,7 @@ module ActiveRecord
202
202
  relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
203
203
  end
204
204
 
205
- if eager_loading && !(
205
+ if eager_loading && has_limit_or_offset? && !(
206
206
  using_limitable_reflections?(join_dependency.reflections) &&
207
207
  using_limitable_reflections?(
208
208
  construct_join_dependency(
@@ -211,12 +211,12 @@ module ActiveRecord
211
211
  ), nil
212
212
  ).reflections
213
213
  )
214
- )
215
- if has_limit_or_offset?
216
- limited_ids = limited_ids_for(relation)
217
- limited_ids.empty? ? relation.none! : relation.where!(primary_key => limited_ids)
214
+ )
215
+ if !connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
216
+ relation = skip_query_cache_if_necessary do
217
+ klass.connection.distinct_relation_for_primary_key(relation)
218
+ end
218
219
  end
219
- relation.limit_value = relation.offset_value = nil
220
220
  end
221
221
 
222
222
  if block_given?
@@ -225,6 +225,7 @@ module ActiveRecord
225
225
  relation
226
226
  end
227
227
  end
228
+
228
229
  end
229
230
 
230
231
  end
@@ -79,17 +79,20 @@ module ActiveRecord
79
79
  # Creates a record with values matching those of the instance attributes
80
80
  # and returns its id.
81
81
  def _create_record(attribute_names = self.attribute_names)
82
- attribute_names &= self.class.column_names
82
+ attribute_names = attributes_for_create(attribute_names)
83
83
  attributes_values = attributes_with_values(attribute_names)
84
-
84
+
85
85
  new_id = self.class._insert_record(attributes_values)
86
86
 
87
+ self.id ||= new_id if @primary_key
87
88
  @new_record = false
89
+ @previously_new_record = true
90
+
91
+ yield(self) if block_given?
88
92
 
89
93
  if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
90
94
  new_id
91
95
  else
92
- self.id ||= new_id if self.class.primary_key
93
96
  id
94
97
  end
95
98
  end
@@ -2,7 +2,7 @@ module ActiveRecord
2
2
  module Calculations
3
3
 
4
4
  def pluck(*column_names)
5
- if loaded? && (column_names.map(&:to_s) - @klass.attribute_names - @klass.attribute_aliases.keys).empty?
5
+ if loaded? && all_attributes?(column_names)
6
6
  return records.pluck(*column_names)
7
7
  end
8
8
 
@@ -14,10 +14,17 @@ module ActiveRecord
14
14
  return records.pluck(*column_names.map{|n| n.to_s.sub(/^#{klass.table_name}\./, "")})
15
15
  else
16
16
  klass.disallow_raw_sql!(column_names)
17
+ columns = arel_columns(column_names)
17
18
  relation = spawn
18
- relation.select_values = column_names
19
- result = skip_query_cache_if_necessary { klass.connection.select_all(relation.arel, nil) }
20
- result.cast_values(klass.attribute_types)
19
+ relation.select_values = columns
20
+ result = skip_query_cache_if_necessary do
21
+ if where_clause.contradiction?
22
+ ActiveRecord::Result.empty
23
+ else
24
+ klass.connection.select_all(relation.arel, "#{klass.name} Pluck")
25
+ end
26
+ end
27
+ type_cast_pluck_values(result, columns)
21
28
  end
22
29
  end
23
30
 
@@ -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) && @arel
6
+ raise ImmutableRelation if defined?(@arel) && @arel && !klass.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
7
7
  end
8
8
  end
9
9
  end
@@ -14,7 +14,6 @@ module ActiveRecord
14
14
 
15
15
  def sql_for(binds, connection)
16
16
  if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
17
- binds.map!(&:value_for_database)
18
17
  @values
19
18
  else
20
19
  val = @values.dup
@@ -4,9 +4,9 @@ module Arel
4
4
 
5
5
  attr_accessor :eager_load
6
6
 
7
- def initialize(cores = [SelectCore.new])
7
+ def initialize(relation = nil)
8
8
  super()
9
- @cores = 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
@@ -8,7 +8,7 @@ module ActiveRecord
8
8
  @name = name.freeze
9
9
  @sql_type_metadata = sql_type_metadata
10
10
  @null = options['null']
11
- @default = options['default']
11
+ @default = options['default'] ? JSON.generate(options['default']) : options['default']
12
12
  @default_function = nil
13
13
  @collation = nil
14
14
  @table_name = nil
@@ -28,18 +28,16 @@ module ActiveRecord
28
28
  sar.compile(binds)
29
29
  end
30
30
 
31
- def to_sar_and_binds(arel_or_sar_string, binds = []) # :nodoc:
31
+ def to_sar_and_binds(arel_or_sar_string, binds = [], preparable = nil) # :nodoc:
32
32
  if arel_or_sar_string.respond_to?(:ast)
33
33
  unless binds.empty?
34
34
  raise "Passing bind parameters with an arel AST is forbidden. " \
35
35
  "The values must be stored on the AST directly"
36
36
  end
37
37
  sar = visitor.accept(arel_or_sar_string.ast, collector)
38
- # puts ['a', sar.freeze, sar.binds].map(&:inspect)
39
- [sar.freeze, sar.binds]
38
+ [sar.freeze, sar.binds, false]
40
39
  else
41
- # puts ['b',arel_or_sar_string.dup.freeze, binds].map(&:inspect)
42
- [arel_or_sar_string.dup.freeze, binds]
40
+ [arel_or_sar_string.dup.freeze, binds, false]
43
41
  end
44
42
  end
45
43
 
@@ -79,10 +77,11 @@ module ActiveRecord
79
77
  end
80
78
 
81
79
  # Returns an ActiveRecord::Result instance.
82
- def select_all(arel, name = nil, binds = [], preparable: nil)
80
+ def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
83
81
  arel = arel_from_relation(arel)
84
- sar, binds = to_sar_and_binds(arel, binds)
85
- select(sar, name, binds)
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)
86
85
  end
87
86
 
88
87
  def exec_query(arel, name = 'SAR', binds = [], prepare: false)
@@ -96,7 +95,7 @@ module ActiveRecord
96
95
  requested_limit = if limit_bind_index
97
96
  type_casted_binds[limit_bind_index]
98
97
  else
99
- arel.limit&.value&.value_for_database
98
+ arel.limit
100
99
  end
101
100
 
102
101
  if allowed_limit.nil?
@@ -29,17 +29,7 @@ module ActiveRecord
29
29
 
30
30
  response = @connection.get("/#{table_name}/schema")
31
31
 
32
- version = Gem::Version.create(response['StandardAPI-Version'] || '5.0.0.4')
33
-
34
- @definitions[table_name] = if (version >= Gem::Version.create('6.0.0.29'))
35
- schema = JSON.parse(response.body)
36
- schema['columns'] = schema.delete('attributes')
37
- schema
38
- elsif (version >= Gem::Version.create('5.0.0.5'))
39
- JSON.parse(response.body)
40
- else
41
- { 'columns' => JSON.parse(response.body), 'limit' => nil }
42
- end
32
+ @definitions[table_name] = JSON.parse(response.body)
43
33
  rescue ::Sunstone::Exception::NotFound
44
34
  raise ActiveRecord::StatementInvalid, "Table \"#{table_name}\" does not exist"
45
35
  end
@@ -50,9 +40,7 @@ module ActiveRecord
50
40
  # - format_type includes the column size constraint, e.g. varchar(50)
51
41
  # - ::regclass is a function that gives the id for a table name
52
42
  def column_definitions(table_name) # :nodoc:
53
- # First check for attributes and then for the deprecated columns field
54
- # TODO: Remove after 0.3
55
- definition(table_name)['attributes'] || definition(table_name)['columns']
43
+ definition(table_name)['columns']
56
44
  end
57
45
 
58
46
  # Returns the limit definition of the table (the maximum limit that can
@@ -93,6 +81,35 @@ module ActiveRecord
93
81
  def column_name_for_operation(operation, node) # :nodoc:
94
82
  visitor.accept(node, collector).first[operation.to_sym]
95
83
  end
84
+
85
+ # Given a set of columns and an ORDER BY clause, returns the columns for a SELECT DISTINCT.
86
+ # PostgreSQL, MySQL, and Oracle override this for custom DISTINCT syntax - they
87
+ # require the order columns appear in the SELECT.
88
+ #
89
+ # columns_for_distinct("posts.id", ["posts.created_at desc"])
90
+ #
91
+ def columns_for_distinct(columns, orders) # :nodoc:
92
+ columns
93
+ end
94
+
95
+ def distinct_relation_for_primary_key(relation) # :nodoc:
96
+ values = columns_for_distinct(
97
+ relation.table[relation.primary_key],
98
+ relation.order_values
99
+ )
100
+
101
+ limited = relation.reselect(values).distinct!
102
+ limited_ids = select_rows(limited.arel, "SQL").map(&:last)
103
+
104
+ if limited_ids.empty?
105
+ relation.none!
106
+ else
107
+ relation.where!(relation.primary_key => limited_ids)
108
+ end
109
+
110
+ relation.limit_value = relation.offset_value = nil
111
+ relation
112
+ end
96
113
 
97
114
  # TODO: def encoding
98
115
 
@@ -85,8 +85,8 @@ module ActiveRecord
85
85
  @prepared_statement_status = Concurrent::ThreadLocalVar.new(false)
86
86
  @connection_parameters = connection_parameters
87
87
 
88
- # @type_map = Type::HashLookupTypeMap.new
89
- # initialize_type_map(type_map)
88
+ @type_map = Type::HashLookupTypeMap.new
89
+ initialize_type_map(@type_map)
90
90
  end
91
91
 
92
92
  def active?
@@ -180,14 +180,24 @@ module ActiveRecord
180
180
  end
181
181
  alias create insert
182
182
 
183
- # Should be the defuat insert, but rails escapes if for SQL so we'll just
184
- # catch the string "DEFATUL VALUES" in the visitor
185
- # def empty_insert_statement_value
186
- # {}
187
- # end
183
+ def reload_type_map
184
+ type_map.clear
185
+ initialize_type_map
186
+ end
188
187
 
189
188
  private
190
189
 
190
+ def type_map
191
+ @type_map ||= Type::HashLookupTypeMap.new.tap do |mapping|
192
+ initialize_type_map(mapping)
193
+ end
194
+ end
195
+
196
+ def initialize_type_map(m = type_map)
197
+ self.class.initialize_type_map(m)
198
+ load_additional_types
199
+ end
200
+
191
201
  def initialize_type_map(m) # :nodoc:
192
202
  m.register_type 'boolean', Type::Boolean.new
193
203
  m.register_type 'string' do |_, options|
@@ -24,7 +24,14 @@ module Arel
24
24
  def substitute_binds hash, bvs
25
25
  if hash.is_a?(Array)
26
26
  hash.map do |v|
27
- if v.is_a?(Arel::Nodes::BindParam)
27
+ if v.is_a?(ActiveRecord::Relation::QueryAttribute)
28
+ new_v = bvs.shift
29
+ if new_v.is_a?(ActiveRecord::Relation::QueryAttribute)
30
+ new_v.value_for_database
31
+ else
32
+ v.type.serialize(new_v)
33
+ end
34
+ elsif v.is_a?(Arel::Nodes::BindParam)
28
35
  bvs.shift#.value_for_database
29
36
  elsif v.is_a?(Hash) || v.is_a?(Array)
30
37
  substitute_binds(v, bvs)
@@ -35,7 +42,14 @@ module Arel
35
42
  elsif hash.is_a?(Hash)
36
43
  newhash = {}
37
44
  hash.each do |k, v|
38
- if v.is_a?(Arel::Nodes::BindParam)
45
+ if v.is_a?(ActiveRecord::Relation::QueryAttribute)
46
+ new_v = bvs.shift
47
+ newhash[k] = if new_v.is_a?(ActiveRecord::Relation::QueryAttribute)
48
+ new_v.value_for_database
49
+ else
50
+ v.type.serialize(new_v)
51
+ end
52
+ elsif v.is_a?(Arel::Nodes::BindParam)
39
53
  newhash[k] = bvs.shift || v.value.value_for_database
40
54
  elsif v.is_a?(Hash)
41
55
  newhash[k] = substitute_binds(v, bvs)
@@ -47,9 +61,16 @@ module Arel
47
61
  end
48
62
  newhash
49
63
  elsif hash.is_a?(Arel::Nodes::BindParam)
50
- bvs.shift || hash.value.value_for_database
64
+ bvs.shift
65
+ elsif hash.is_a?(ActiveRecord::Relation::QueryAttribute)
66
+ new_v = bvs.shift
67
+ if new_v.is_a?(ActiveRecord::Relation::QueryAttribute)
68
+ new_v.value_for_database
69
+ else
70
+ v.type.serialize(new_v)
71
+ end
51
72
  else
52
- bvs.shift || hash.value.value_for_database
73
+ bvs.shift
53
74
  end
54
75
  end
55
76
 
@@ -8,10 +8,6 @@ module Arel
8
8
  accept(node, collector).value
9
9
  end
10
10
 
11
- def preparable
12
- false
13
- end
14
-
15
11
  private
16
12
 
17
13
  def visit_Arel_Nodes_SelectStatement o, collector
@@ -72,26 +68,12 @@ module Arel
72
68
  else
73
69
  collector.updates = {}
74
70
 
75
- o.values.expr[0].each_with_index do |value, i|
76
- k = value.value.name
77
- if k.is_a?(Hash)
78
- add_to_bottom_of_hash_or_array(k, value)
79
- collector.updates.deep_merge!(k) { |key, v1, v2|
80
- if (v1.is_a?(Array) && v2.is_a?(Array))
81
- v2.each_with_index do |v, j|
82
- if v1[j].nil?
83
- v1[j] = v2[j]
84
- else
85
- v1[j].deep_merge!(v2[j]) unless v2[j].nil?
86
- end
87
- end
88
- v1
89
- else
90
- v2
91
- end
92
- }
71
+ o.columns.map(&:name).zip(o.values.expr.first).to_h.each do |k, v|
72
+ collector.updates[k] = case v
73
+ when Nodes::SqlLiteral, Nodes::BindParam, ActiveModel::Attribute
74
+ visit(v, collector)
93
75
  else
94
- collector.updates[k] = visit(value, collector)
76
+ v
95
77
  end
96
78
  end
97
79
  end
@@ -765,8 +747,13 @@ module Arel
765
747
  def visit_Arel_Nodes_Assignment o, collector
766
748
  case o.left
767
749
  when Arel::Nodes::UnqualifiedColumn
768
- { visit(o.left.expr, collector) => visit(o.right, collector) }
769
- when Arel::Attributes::Attribute, Arel::Nodes::BindParam
750
+ case o.right
751
+ when Arel::Attributes::Attribute, Arel::Nodes::BindParam, ActiveModel::Attribute
752
+ { visit(o.left.expr, collector) => visit(o.right, collector) }
753
+ else
754
+ { visit(o.left.expr, collector) => o.right }
755
+ end
756
+ when Arel::Attributes::Attribute, Arel::Nodes::BindParam, ActiveModel::Attribute
770
757
  { visit(o.left, collector) => visit(o.right, collector) }
771
758
  else
772
759
  collector = visit o.left, collector
@@ -968,6 +955,15 @@ module Arel
968
955
  alias :visit_Arel_Attributes_Time :visit_Arel_Attributes_Attribute
969
956
  alias :visit_Arel_Attributes_Boolean :visit_Arel_Attributes_Attribute
970
957
 
958
+ def visit_ActiveModel_Attribute(o, collector)
959
+ if o.value.is_a?(ActiveRecord::StatementCache::Substitute)
960
+ a = collector.add_bind(o)
961
+ o
962
+ else
963
+ o.value_for_database
964
+ end
965
+ end
966
+
971
967
  def visit_Arel_Nodes_BindParam o, collector
972
968
  a = collector.add_bind(o.value)
973
969
  o.is_a?(Arel::Nodes::BindParam) ? o : a
@@ -1067,7 +1063,6 @@ module Arel
1067
1063
 
1068
1064
  def maybe_visit thing, collector
1069
1065
  return collector unless thing
1070
- collector << " "
1071
1066
  visit thing, collector
1072
1067
  end
1073
1068
  end
@@ -132,25 +132,52 @@ module Sunstone
132
132
  if Thread.current[:sunstone_transaction_count] == 1 && !Thread.current[:sunstone_request_sent]
133
133
  Thread.current[:sunstone_request_sent] = request
134
134
  elsif Thread.current[:sunstone_request_sent]
135
- log_mess = request.path.split('?', 2)
136
- log_mess += Thread.current[:sunstone_request_sent].path.split('?', 2)
137
- raise ActiveRecord::StatementInvalid, <<~MSG
135
+ message = <<~MSG
138
136
  Cannot send multiple request in a transaction.
139
-
137
+
140
138
  Trying to send:
141
- #{request.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? MessagePack.unpack(CGI.unescape(log_mess[1])) : '' }
142
-
143
- Already sent:
144
- #{Thread.current[:sunstone_request_sent].method} #{log_mess[2]} #{(log_mess[3] && !log_mess[3].empty?) ? MessagePack.unpack(CGI.unescape(log_mess[3])) : '' }
145
139
  MSG
140
+
141
+ path_and_query = request.path.split('?', 2)
142
+ message << " #{request.method} #{path_and_query[0]}"
143
+ if path_and_query[1]
144
+ if request['Query-Encoding'] == 'application/msgpack'
145
+ message << " " << MessagePack.unpack(CGI.unescape(path_and_query[1]))
146
+ else
147
+ message << " " << CGI.unescape(path_and_query[1])
148
+ end
149
+ end
150
+
151
+ message << "\n\nAlready sent:\n"
152
+ path_and_query = Thread.current[:sunstone_request_sent].path.split('?', 2)
153
+ message << " #{Thread.current[:sunstone_request_sent].method} #{path_and_query[0]}"
154
+ if path_and_query[1]
155
+ if request['Query-Encoding'] == 'application/msgpack'
156
+ message << " " << MessagePack.unpack(CGI.unescape(path_and_query[1]))
157
+ else
158
+ message << " " << CGI.unescape(path_and_query[1])
159
+ end
160
+ end
161
+
162
+ raise ActiveRecord::StatementInvalid, message
146
163
  else
147
164
  log_mess = request.path.split('?', 2)
148
- raise ActiveRecord::StatementInvalid, <<~MSG
149
- Cannot send multiple request in a transaction.
165
+ message = if request['Query-Encoding'] == 'application/msgpack'
166
+ <<~MSG
167
+ Cannot send multiple request in a transaction.
150
168
 
151
- Trying to send:
152
- #{request.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? MessagePack.unpack(CGI.unescape(log_mess[1])) : '' }
153
- MSG
169
+ Trying to send:
170
+ #{request.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? MessagePack.unpack(CGI.unescape(log_mess[1])) : '' }
171
+ MSG
172
+ else
173
+ <<~MSG
174
+ Cannot send multiple request in a transaction.
175
+
176
+ Trying to send:
177
+ #{request.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? CGI.unescape(log_mess[1]) : '' }
178
+ MSG
179
+ end
180
+ raise ActiveRecord::StatementInvalid, message
154
181
  end
155
182
  end
156
183
 
@@ -1,3 +1,3 @@
1
1
  module Sunstone
2
- VERSION = '6.1.0.2'
2
+ VERSION = '7.0.0'
3
3
  end