Skip to content

Commit

Permalink
Don't require an active connection for table and column quoting (#1159)
Browse files Browse the repository at this point in the history
  • Loading branch information
aidanharan authored Apr 18, 2024
1 parent c85e862 commit 6101432
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,10 @@ def build_insert_sql(insert) # :nodoc:

if returning = insert.send(:insert_all).returning
returning_sql = if returning.is_a?(String)
returning
else
returning.map { |column| "INSERTED.#{quote_column_name(column)}" }.join(", ")
end
returning
else
returning.map { |column| "INSERTED.#{quote_column_name(column)}" }.join(", ")
end
sql << " OUTPUT #{returning_sql}"
end

Expand Down
90 changes: 44 additions & 46 deletions lib/active_record/connection_adapters/sqlserver/quoting.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,53 @@ module ActiveRecord
module ConnectionAdapters
module SQLServer
module Quoting
extend ActiveSupport::Concern

QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:

module ClassMethods
def column_name_matcher
/
\A
(
(?:
# [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\]) | \w+\((?:|\g<2>)\))
)
(?:\s+AS\s+(?:\w+|\[\w+\]))?
)
(?:\s*,\s*\g<1>)*
\z
/ix
end

def column_name_with_order_matcher
/
\A
(
(?:
# [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\]) | \w+\((?:|\g<2>)\))
)
(?:\s+COLLATE\s+\w+)?
(?:\s+ASC|\s+DESC)?
(?:\s+NULLS\s+(?:FIRST|LAST))?
)
(?:\s*,\s*\g<1>)*
\z
/ix
end

def quote_column_name(name)
QUOTED_COLUMN_NAMES[name] ||= SQLServer::Utils.extract_identifiers(name).quoted
end

def quote_table_name(name)
QUOTED_TABLE_NAMES[name] ||= SQLServer::Utils.extract_identifiers(name).quoted
end
end

def fetch_type_metadata(sql_type, sqlserver_options = {})
cast_type = lookup_cast_type(sql_type)

Expand All @@ -33,14 +77,6 @@ def quote_string_single_national(s)
SQLServer::Utils.quote_string_single_national(s)
end

def quote_column_name(name)
QUOTED_COLUMN_NAMES[name] ||= SQLServer::Utils.extract_identifiers(name).quoted
end

def quote_table_name(name)
QUOTED_TABLE_NAMES[name] ||= SQLServer::Utils.extract_identifiers(name).quoted
end

def quote_default_expression(value, column)
cast_type = lookup_cast_type(column.sql_type)
if cast_type.type == :uuid && value.is_a?(String) && value.include?('()')
Expand Down Expand Up @@ -76,44 +112,6 @@ def quoted_date(value)
end
end

def column_name_matcher
COLUMN_NAME
end

def column_name_with_order_matcher
COLUMN_NAME_WITH_ORDER
end

COLUMN_NAME = /
\A
(
(?:
# [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\]) | \w+\((?:|\g<2>)\))
)
(?:\s+AS\s+(?:\w+|\[\w+\]))?
)
(?:\s*,\s*\g<1>)*
\z
/ix

COLUMN_NAME_WITH_ORDER = /
\A
(
(?:
# [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\]) | \w+\((?:|\g<2>)\))
)
(?:\s+COLLATE\s+\w+)?
(?:\s+ASC|\s+DESC)?
(?:\s+NULLS\s+(?:FIRST|LAST))?
)
(?:\s*,\s*\g<1>)*
\z
/ix

private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER

def quote(value)
case value
when Type::Binary::Data
Expand Down

0 comments on commit 6101432

Please sign in to comment.