Serialize postgres' hstore, json and array types correctly in AR update methods.
Fixes #12261. Closes #12395. Conflicts: activerecord/CHANGELOG.md activerecord/test/cases/adapters/postgresql/array_test.rb activerecord/test/cases/adapters/postgresql/json_test.rb
This commit is contained in:
parent
56510091fb
commit
73bba4c1e1
@ -1,3 +1,10 @@
|
||||
* Fixed `update_column`, `update_columns`, and `update_all` to correctly serialize
|
||||
values for `array`, `hstore` and `json` column types in `PostgreSQL`.
|
||||
|
||||
Fixes #12261.
|
||||
|
||||
*Tadas Tamosauskas*
|
||||
|
||||
* Do not consider PostgreSQL array columns as number or text columns.
|
||||
|
||||
The code uses these checks in several places to know what to do with a
|
||||
|
@ -101,7 +101,7 @@ def sanitize_sql_hash_for_conditions(attrs, default_table_name = self.table_name
|
||||
# # => "status = NULL , group_id = 1"
|
||||
def sanitize_sql_hash_for_assignment(attrs, table)
|
||||
attrs.map do |attr, value|
|
||||
"#{connection.quote_table_name_for_assignment(table, attr)} = #{quote_bound_value(value)}"
|
||||
"#{connection.quote_table_name_for_assignment(table, attr)} = #{quote_bound_value(value, connection, columns_hash[attr.to_s])}"
|
||||
end.join(', ')
|
||||
end
|
||||
|
||||
@ -152,15 +152,16 @@ def replace_named_bind_variables(statement, bind_vars) #:nodoc:
|
||||
end
|
||||
end
|
||||
|
||||
def quote_bound_value(value, c = connection) #:nodoc:
|
||||
if value.respond_to?(:map) && !value.acts_like?(:string)
|
||||
def quote_bound_value(value, c = connection, column = nil) #:nodoc:
|
||||
db_native_type = column && (column.respond_to?(:array) && column.array || [:json, :hstore].include?(column.type) )
|
||||
if value.respond_to?(:map) && !value.acts_like?(:string) && !db_native_type
|
||||
if value.respond_to?(:empty?) && value.empty?
|
||||
c.quote(nil)
|
||||
else
|
||||
value.map { |v| c.quote(v) }.join(',')
|
||||
end
|
||||
else
|
||||
c.quote(value)
|
||||
c.quote(value, column)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -128,6 +128,12 @@ def test_attribute_for_inspect_for_array_field
|
||||
assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...]", record.attribute_for_inspect(:ratings))
|
||||
end
|
||||
|
||||
def test_update_all
|
||||
PgArray.create! tags: ["one", "two", "three"]
|
||||
PgArray.update_all tags: ["four", "five"]
|
||||
assert_equal ["four", "five"], PgArray.first.tags
|
||||
end
|
||||
|
||||
private
|
||||
def assert_cycle field, array
|
||||
# test creation
|
||||
|
@ -206,6 +206,12 @@ def test_quoting_special_characters
|
||||
def test_multiline
|
||||
assert_cycle("a\nb" => "c\nd")
|
||||
end
|
||||
|
||||
def test_update_all
|
||||
Hstore.create! tags: { "one" => "two" }
|
||||
Hstore.update_all tags: { "three" => "four" }
|
||||
assert_equal({ "three" => "four" }, Hstore.first.tags)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -121,4 +121,10 @@ def test_with_store_accessors
|
||||
x = JsonDataType.first
|
||||
assert_equal "640×1136", x.resolution
|
||||
end
|
||||
|
||||
def test_update_all
|
||||
JsonDataType.create! payload: { "one" => "two" }
|
||||
JsonDataType.update_all payload: { "three" => "four" }
|
||||
assert_equal({ "three" => "four" }, JsonDataType.first.payload)
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user