Allow column name with COLLATE (e.g., title COLLATE "C") as safe SQL string

This commit is contained in:
Shugo Maeda 2022-02-10 12:53:46 +09:00
parent 41c9d15b74
commit d12e4daca9
No known key found for this signature in database
GPG Key ID: 2DFE34085E97CE47
5 changed files with 21 additions and 0 deletions

View File

@ -1,3 +1,7 @@
* Allow column name with COLLATE (e.g., title COLLATE "C") as safe SQL string
*Shugo Maeda*
* Permit underscores in the VERSION argument to database rake tasks.
*Eddie Lebow*

View File

@ -97,6 +97,7 @@ module ActiveRecord
# `table_name`.`column_name` | function(one or no argument)
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\)
)
(?:\s+COLLATE\s+(?:\w+|"\w+"))?
(?:\s+ASC|\s+DESC)?
)
(?:\s*,\s*\g<1>)*

View File

@ -149,6 +149,7 @@ module ActiveRecord
# "schema_name"."table_name"."column_name"::type_name | function(one or no argument)::type_name
((?:\w+\.|"\w+"\.){,2}(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)?
)
(?:\s+COLLATE\s+"\w+")?
(?:\s+ASC|\s+DESC)?
(?:\s+NULLS\s+(?:FIRST|LAST))?
)

View File

@ -101,6 +101,7 @@ module ActiveRecord
# "table_name"."column_name" | function(one or no argument)
((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\)
)
(?:\s+COLLATE\s+(?:\w+|"\w+"))?
(?:\s+ASC|\s+DESC)?
)
(?:\s*,\s*\g<1>)*

View File

@ -166,6 +166,20 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase
assert_equal ids_expected, ids
end
test "order: allows valid arguments with COLLATE" do
collation_name = {
"PostgreSQL" => "C",
"Mysql2" => "utf8mb4_bin",
"SQLite" => "binary"
}[ActiveRecord::Base.connection.adapter_name]
ids_expected = Post.order(Arel.sql(%Q'author_id, title COLLATE "#{collation_name}" DESC')).pluck(:id)
ids = Post.order(["author_id", %Q'title COLLATE "#{collation_name}" DESC']).pluck(:id)
assert_equal ids_expected, ids
end
test "order: logs deprecation warning for unrecognized column" do
e = assert_raises(ActiveRecord::UnknownAttributeReference) do
Post.order("REPLACE(title, 'misc', 'zzzz')")