From 1340498d2102423665cc5cfe7be7cdba32c72928 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Sun, 9 Jun 2019 14:03:31 +0900 Subject: Refactor `disallow_raw_sql!` to avoid `split(/\s*,\s*/)` to order args `split(/\s*,\s*/)` to order args and then `permit.match?` one by one is much slower than `permit.match?` once. --- .../connection_adapters/abstract/quoting.rb | 19 ++++++++++++++----- .../connection_adapters/mysql/quoting.rb | 17 +++++++++++++---- .../connection_adapters/postgresql/quoting.rb | 20 ++++++++++++++------ .../connection_adapters/sqlite3/quoting.rb | 17 +++++++++++++---- .../lib/active_record/relation/query_methods.rb | 1 + activerecord/lib/active_record/sanitization.rb | 3 +-- 6 files changed, 56 insertions(+), 21 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb index 99e1a11f30..a1b91c22de 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb @@ -155,7 +155,14 @@ module ActiveRecord # # "#{table_name}.#{column_name}" # "#{column_name}" - COLUMN_NAME = /\A(?:\w+\.)?\w+\z/i + COLUMN_NAME = / + \A + ( + (?:\w+\.)?\w+ + ) + (?:\s*,\s*\g<1>)* + \z + /ix # Regexp for column names with order (with or without a table name prefix, # with or without various order modifiers). Matches the following: @@ -170,10 +177,12 @@ module ActiveRecord # "#{column_name} NULLS LAST" COLUMN_NAME_WITH_ORDER = / \A - (?:\w+\.)? - \w+ - (?:\s+ASC|\s+DESC)? - (?:\s+NULLS\s+(?:FIRST|LAST))? + ( + (?:\w+\.)?\w+ + (?:\s+ASC|\s+DESC)? + (?:\s+NULLS\s+(?:FIRST|LAST))? + ) + (?:\s*,\s*\g<1>)* \z /ix diff --git a/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb b/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb index 84354c0187..740832d6b8 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb @@ -40,13 +40,22 @@ module ActiveRecord COLUMN_NAME_WITH_ORDER end - COLUMN_NAME = /\A(?:(`?)\w+\k<1>\.)?(`?)\w+\k<2>\z/i + COLUMN_NAME = / + \A + ( + (?:\w+\.|`\w+`\.)?(?:\w+|`\w+`) + ) + (?:\s*,\s*\g<1>)* + \z + /ix COLUMN_NAME_WITH_ORDER = / \A - (?:(`?)\w+\k<1>\.)? - (`?)\w+\k<2> - (?:\s+ASC|\s+DESC)? + ( + (?:\w+\.|`\w+`\.)?(?:\w+|`\w+`) + (?:\s+ASC|\s+DESC)? + ) + (?:\s*,\s*\g<1>)* \z /ix diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb index 0ebed21717..095429dd89 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb @@ -86,15 +86,23 @@ module ActiveRecord COLUMN_NAME_WITH_ORDER end - COLUMN_NAME = /\A(?:("?)\w+\k<1>\.)?("?)\w+\k<2>(?:::\w+)?\z/i + COLUMN_NAME = / + \A + ( + (?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)? + ) + (?:\s*,\s*\g<1>)* + \z + /ix COLUMN_NAME_WITH_ORDER = / \A - (?:("?)\w+\k<1>\.)? - ("?)\w+\k<2> - (?:::\w+)? - (?:\s+ASC|\s+DESC)? - (?:\s+NULLS\s+(?:FIRST|LAST))? + ( + (?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)? + (?:\s+ASC|\s+DESC)? + (?:\s+NULLS\s+(?:FIRST|LAST))? + ) + (?:\s*,\s*\g<1>)* \z /ix diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb index 79d477cdb2..88a16599f7 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb @@ -53,13 +53,22 @@ module ActiveRecord COLUMN_NAME_WITH_ORDER end - COLUMN_NAME = /\A(?:("?)\w+\k<1>\.)?("?)\w+\k<2>\z/i + COLUMN_NAME = / + \A + ( + (?:\w+\.|"\w+"\.)?(?:\w+|"\w+") + ) + (?:\s*,\s*\g<1>)* + \z + /ix COLUMN_NAME_WITH_ORDER = / \A - (?:("?)\w+\k<1>\.)? - ("?)\w+\k<2> - (?:\s+ASC|\s+DESC)? + ( + (?:\w+\.|"\w+"\.)?(?:\w+|"\w+") + (?:\s+ASC|\s+DESC)? + ) + (?:\s*,\s*\g<1>)* \z /ix diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 588cb130f2..d1bcec9704 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -1247,6 +1247,7 @@ module ActiveRecord end def preprocess_order_args(order_args) + order_args.reject!(&:blank?) order_args.map! do |arg| klass.sanitize_sql_for_order(arg) end diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb index 5296499bad..b16cbb0f84 100644 --- a/activerecord/lib/active_record/sanitization.rb +++ b/activerecord/lib/active_record/sanitization.rb @@ -137,8 +137,7 @@ module ActiveRecord def disallow_raw_sql!(args, permit: connection.column_name_matcher) # :nodoc: unexpected = nil args.each do |arg| - next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || - arg.to_s.split(/\s*,\s*/).all? { |part| permit.match?(part) } + next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s) (unexpected ||= []) << arg end -- cgit v1.2.3