From 2cbc5b927f516f2e6b52e1259417ced206729c46 Mon Sep 17 00:00:00 2001 From: Wanderson Policarpo Date: Fri, 15 May 2020 23:27:59 +0100 Subject: [PATCH] Rubocop: Enable Layout/* cops --- activerecord-sqlserver-adapter.gemspec | 6 +-- .../sqlserver/database_statements.rb | 5 ++ .../sqlserver/database_tasks.rb | 3 -- .../connection_adapters/sqlserver/quoting.rb | 2 +- .../sqlserver/schema_dumper.rb | 2 + .../sqlserver/schema_statements.rb | 35 ++++++++------ .../sqlserver/transaction.rb | 1 + .../sqlserver/type/char.rb | 2 + .../sqlserver/type/date.rb | 1 + .../sqlserver/type/time.rb | 1 + .../sqlserver/type/time_value_fractional.rb | 3 ++ .../sqlserver/type/uuid.rb | 1 + .../connection_adapters/sqlserver/utils.rb | 1 + .../connection_adapters/sqlserver_adapter.rb | 5 +- .../tasks/sqlserver_database_tasks.rb | 3 ++ lib/arel/visitors/sqlserver.rb | 10 ++-- test/cases/adapter_test_sqlserver.rb | 17 ++++--- test/cases/coerced_tests.rb | 37 +++++++++------ test/cases/column_test_sqlserver.rb | 2 + test/cases/fetch_test_sqlserver.rb | 1 - .../pessimistic_locking_test_sqlserver.rb | 10 ++-- test/cases/schema_dumper_test_sqlserver.rb | 11 +++-- test/cases/schema_test_sqlserver.rb | 1 - test/cases/utils_test_sqlserver.rb | 46 ++++++++++--------- test/schema/sqlserver_specific_schema.rb | 2 +- test/support/coerceable_test_sqlserver.rb | 1 + test/support/connection_reflection.rb | 1 + test/support/rake_helpers.rb | 2 + 28 files changed, 128 insertions(+), 84 deletions(-) diff --git a/activerecord-sqlserver-adapter.gemspec b/activerecord-sqlserver-adapter.gemspec index 1b66fbf32..a9c72c9e7 100644 --- a/activerecord-sqlserver-adapter.gemspec +++ b/activerecord-sqlserver-adapter.gemspec @@ -17,9 +17,9 @@ Gem::Specification.new do |spec| spec.description = "ActiveRecord SQL Server Adapter. SQL Server 2012 and upward." spec.metadata = { - "bug_tracker_uri" => "https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues", - "changelog_uri" => "https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v#{version}/CHANGELOG.md", - "source_code_uri" => "https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v#{version}", + "bug_tracker_uri" => "https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues", + "changelog_uri" => "https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v#{version}/CHANGELOG.md", + "source_code_uri" => "https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v#{version}", } spec.files = `git ls-files -z`.split("\x0") diff --git a/lib/active_record/connection_adapters/sqlserver/database_statements.rb b/lib/active_record/connection_adapters/sqlserver/database_statements.rb index bba3752a9..20f940413 100644 --- a/lib/active_record/connection_adapters/sqlserver/database_statements.rb +++ b/lib/active_record/connection_adapters/sqlserver/database_statements.rb @@ -186,12 +186,14 @@ def with_identity_insert_enabled(table_name) def use_database(database = nil) return if sqlserver_azure? + name = SQLServer::Utils.extract_identifiers(database || @connection_options[:database]).quoted do_execute "USE #{name}" unless name.blank? end def user_options return {} if sqlserver_azure? + rows = select_rows("DBCC USEROPTIONS WITH NO_INFOMSGS", "SCHEMA") rows = rows.first if rows.size == 2 && rows.last.empty? rows.reduce(HashWithIndifferentAccess.new) do |values, row| @@ -315,6 +317,7 @@ def sp_executesql_types_and_parameters(binds) def sp_executesql_sql_type(attr) return attr.type.sqlserver_type if attr.type.respond_to?(:sqlserver_type) + case value = attr.value_for_database when Numeric value > 2_147_483_647 ? "bigint".freeze : "int".freeze @@ -376,8 +379,10 @@ def exclude_output_inserted_table_names? def exclude_output_inserted_table_name?(table_name, sql) return false unless exclude_output_inserted_table_names? + table_name ||= get_table_name(sql) return false unless table_name + self.class.exclude_output_inserted_table_names[table_name] end diff --git a/lib/active_record/connection_adapters/sqlserver/database_tasks.rb b/lib/active_record/connection_adapters/sqlserver/database_tasks.rb index 954d3d0fe..63f33356f 100644 --- a/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +++ b/lib/active_record/connection_adapters/sqlserver/database_tasks.rb @@ -63,6 +63,3 @@ def create_database_edition_options(options = {}) end end end - - - diff --git a/lib/active_record/connection_adapters/sqlserver/quoting.rb b/lib/active_record/connection_adapters/sqlserver/quoting.rb index 430a1bc4c..6c955057f 100644 --- a/lib/active_record/connection_adapters/sqlserver/quoting.rb +++ b/lib/active_record/connection_adapters/sqlserver/quoting.rb @@ -65,7 +65,7 @@ def quoted_date(value) if value.acts_like?(:date) Type::Date.new.serialize(value) else value.acts_like?(:time) - Type::DateTime.new.serialize(value) + Type::DateTime.new.serialize(value) end end diff --git a/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb b/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb index 99b4dab8d..ef69fee42 100644 --- a/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +++ b/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb @@ -20,11 +20,13 @@ def explicit_primary_key_default?(column) def schema_limit(column) return if SQLSEVER_NO_LIMIT_TYPES.include?(column.sql_type) + super end def schema_collation(column) return unless column.collation + column.collation if column.collation != @connection.collation end diff --git a/lib/active_record/connection_adapters/sqlserver/schema_statements.rb b/lib/active_record/connection_adapters/sqlserver/schema_statements.rb index 3f8eea12f..17b3976f4 100644 --- a/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +++ b/lib/active_record/connection_adapters/sqlserver/schema_statements.rb @@ -66,6 +66,7 @@ def indexes(table_name) def columns(table_name) return [] if table_name.blank? + column_definitions(table_name).map do |ci| sqlserver_options = ci.slice :ordinal_position, :is_primary, :is_identity, :table_name sql_type_metadata = fetch_type_metadata ci[:type], sqlserver_options @@ -131,6 +132,7 @@ def rename_table(table_name, new_name) def remove_column(table_name, column_name, type = nil, options = {}) raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_name.is_a? Array + remove_check_constraints(table_name, column_name) remove_default_constraint(table_name, column_name) remove_indexes(table_name, column_name) @@ -144,9 +146,9 @@ def change_column(table_name, column_name, type, options = {}) without_constraints = options.key?(:default) || options.key?(:limit) default = if !options.key?(:default) && column_object column_object.default - else - options[:default] - end + else + options[:default] + end if without_constraints || (column_object && column_object.type != type.to_sym) remove_default_constraint(table_name, column_name) indexes = indexes(table_name).select { |index| index.columns.include?(column_name.to_s) } @@ -172,6 +174,7 @@ def change_column_default(table_name, column_name, default_or_changes) clear_cache! column = column_for(table_name, column_name) return unless column + remove_default_constraint(table_name, column_name) default = extract_new_default_value(default_or_changes) do_execute "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{default_constraint_name(table_name, column_name)} DEFAULT #{quote_default_expression(default, column)} FOR #{quote_column_name(column_name)}" @@ -188,6 +191,7 @@ def rename_column(table_name, column_name, new_column_name) def rename_index(table_name, old_name, new_name) raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters" if new_name.length > allowed_index_name_length + identifier = SQLServer::Utils.extract_identifiers("#{table_name}.#{old_name}") execute_procedure :sp_rename, identifier.quoted, new_name, "INDEX" end @@ -249,10 +253,10 @@ def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) def columns_for_distinct(columns, orders) order_columns = orders.reject(&:blank?).map { |s| - s = s.to_sql unless s.is_a?(String) - s.gsub(/\s+(?:ASC|DESC)\b/i, "") - .gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "") - }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" } + s = s.to_sql unless s.is_a?(String) + s.gsub(/\s+(?:ASC|DESC)\b/i, "") + .gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "") + }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" } (order_columns << super).join(", ") end @@ -507,11 +511,11 @@ def remove_indexes(table_name, column_name) def get_table_name(sql) tn = if sql =~ /^\s*(INSERT|EXEC sp_executesql N'INSERT)(\s+INTO)?\s+([^\(\s]+)\s*|^\s*update\s+([^\(\s]+)\s*/i Regexp.last_match[3] || Regexp.last_match[4] - elsif sql =~ /FROM\s+([^\(\s]+)\s*/i - Regexp.last_match[1] - else - nil - end + elsif sql =~ /FROM\s+([^\(\s]+)\s*/i + Regexp.last_match[1] + else + nil + end SQLServer::Utils.extract_identifiers(tn).object end @@ -540,9 +544,9 @@ def view_information(table_name) if view_info[:VIEW_DEFINITION].blank? || view_info[:VIEW_DEFINITION].length == 4000 view_info[:VIEW_DEFINITION] = begin select_values("EXEC sp_helptext #{identifier.object_quoted}", "SCHEMA").join - rescue - warn "No view definition found, possible permissions problem.\nPlease run GRANT VIEW DEFINITION TO your_user;" - nil + rescue + warn "No view definition found, possible permissions problem.\nPlease run GRANT VIEW DEFINITION TO your_user;" + nil end end end @@ -553,6 +557,7 @@ def view_information(table_name) def views_real_column_name(table_name, column_name) view_definition = view_information(table_name)[:VIEW_DEFINITION] return column_name unless view_definition + match_data = view_definition.match(/([\w-]*)\s+as\s+#{column_name}/im) match_data ? match_data[1] : column_name end diff --git a/lib/active_record/connection_adapters/sqlserver/transaction.rb b/lib/active_record/connection_adapters/sqlserver/transaction.rb index 08deeed44..d25617e9e 100644 --- a/lib/active_record/connection_adapters/sqlserver/transaction.rb +++ b/lib/active_record/connection_adapters/sqlserver/transaction.rb @@ -13,6 +13,7 @@ def sqlserver? def current_isolation_level return unless sqlserver? + level = connection.user_options_isolation_level # When READ_COMMITTED_SNAPSHOT is set to ON, # user_options_isolation_level will be equal to 'read committed diff --git a/lib/active_record/connection_adapters/sqlserver/type/char.rb b/lib/active_record/connection_adapters/sqlserver/type/char.rb index 55b1eae4b..2084f5132 100644 --- a/lib/active_record/connection_adapters/sqlserver/type/char.rb +++ b/lib/active_record/connection_adapters/sqlserver/type/char.rb @@ -12,6 +12,7 @@ def type def serialize(value) return if value.nil? return value if value.is_a?(Data) + Data.new super, self end @@ -24,6 +25,7 @@ def sqlserver_type def quoted(value) return value.quoted_id if value.respond_to?(:quoted_id) + Utils.quote_string_single(value) end end diff --git a/lib/active_record/connection_adapters/sqlserver/type/date.rb b/lib/active_record/connection_adapters/sqlserver/type/date.rb index f8993e3be..281fd2b0b 100644 --- a/lib/active_record/connection_adapters/sqlserver/type/date.rb +++ b/lib/active_record/connection_adapters/sqlserver/type/date.rb @@ -11,6 +11,7 @@ def sqlserver_type def serialize(value) return unless value.present? + date = super(value).to_s(:_sqlserver_dateformat) Data.new date, self end diff --git a/lib/active_record/connection_adapters/sqlserver/type/time.rb b/lib/active_record/connection_adapters/sqlserver/type/time.rb index 4261ae7b7..ef209641a 100644 --- a/lib/active_record/connection_adapters/sqlserver/type/time.rb +++ b/lib/active_record/connection_adapters/sqlserver/type/time.rb @@ -37,6 +37,7 @@ def quoted(value) def cast_value(value) value = super return if value.blank? + value = value.change year: 2000, month: 01, day: 01 apply_seconds_precision(value) end diff --git a/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb b/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb index fe67d3d9e..f5c8744ea 100644 --- a/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +++ b/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb @@ -9,11 +9,13 @@ module TimeValueFractional def apply_seconds_precision(value) return value if !value.respond_to?(fractional_property) || value.send(fractional_property).zero? + value.change fractional_property => seconds_precision(value) end def seconds_precision(value) return 0 if fractional_scale == 0 + seconds = value.send(fractional_property).to_f / fractional_operator.to_f seconds = ((seconds * (1 / fractional_precision)).round / (1 / fractional_precision)).round(fractional_scale) (seconds * fractional_operator).round(0).to_i @@ -21,6 +23,7 @@ def seconds_precision(value) def quote_fractional(value) return 0 if fractional_scale == 0 + frac_seconds = seconds_precision(value) seconds = (frac_seconds.to_f / fractional_operator.to_f).round(fractional_scale) seconds.to_d.to_s.split(".").last.to(fractional_scale - 1) diff --git a/lib/active_record/connection_adapters/sqlserver/type/uuid.rb b/lib/active_record/connection_adapters/sqlserver/type/uuid.rb index 387796c12..d469f0bfd 100644 --- a/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +++ b/lib/active_record/connection_adapters/sqlserver/type/uuid.rb @@ -19,6 +19,7 @@ def sqlserver_type def serialize(value) return unless value + Data.new super, self end diff --git a/lib/active_record/connection_adapters/sqlserver/utils.rb b/lib/active_record/connection_adapters/sqlserver/utils.rb index c8836ae5f..c574dc693 100644 --- a/lib/active_record/connection_adapters/sqlserver/utils.rb +++ b/lib/active_record/connection_adapters/sqlserver/utils.rb @@ -75,6 +75,7 @@ def hash def parse_raw_name @parts = [] return if raw_name.blank? + scanner = StringScanner.new(raw_name) matched = scanner.exist?(QUOTED_CHECKER) ? scanner.scan_until(QUOTED_SCANNER) : scanner.scan_until(UNQUOTED_SCANNER) while matched diff --git a/lib/active_record/connection_adapters/sqlserver_adapter.rb b/lib/active_record/connection_adapters/sqlserver_adapter.rb index 8d77c8b6c..dc641eff1 100644 --- a/lib/active_record/connection_adapters/sqlserver_adapter.rb +++ b/lib/active_record/connection_adapters/sqlserver_adapter.rb @@ -188,6 +188,7 @@ def disable_referential_integrity def active? return false unless @connection + raw_connection_do "SELECT 1" true rescue *connection_errors @@ -253,6 +254,7 @@ def sqlserver_azure? def database_prefix_remote_server? return false if database_prefix.blank? + name = SQLServer::Utils.extract_identifiers(database_prefix) name.fully_qualified? && name.object.blank? end @@ -420,7 +422,7 @@ def dblib_connect(config) appname: config_appname(config), login_timeout: config_login_timeout(config), timeout: config_timeout(config), - encoding: config_encoding(config), + encoding: config_encoding(config), azure: config[:azure], contained: config[:contained] ).tap do |client| @@ -476,6 +478,7 @@ def initialize_dateformatter def version_year return 2016 if sqlserver_version =~ /vNext/ + /SQL Server (\d+)/.match(sqlserver_version).to_a.last.to_s.to_i rescue StandardError => e 2016 diff --git a/lib/active_record/tasks/sqlserver_database_tasks.rb b/lib/active_record/tasks/sqlserver_database_tasks.rb index df1415e0d..6b2df7e7c 100644 --- a/lib/active_record/tasks/sqlserver_database_tasks.rb +++ b/lib/active_record/tasks/sqlserver_database_tasks.rb @@ -64,6 +64,7 @@ def structure_dump(filename, extra_flags) view_args = connection.views.map { |v| Shellwords.escape(v) } command.concat(view_args) raise "Error dumping database" unless Kernel.system(command.join(" ")) + dump = File.read(filename) dump.gsub!(/^USE .*$\nGO\n/, "") # Strip db USE statements dump.gsub!(/^GO\n/, "") # Strip db GO statements @@ -110,11 +111,13 @@ def local_database?(configuration) def configuration_host_ip(configuration) return nil unless configuration["host"] + Socket::getaddrinfo(configuration["host"], "echo", Socket::AF_INET)[0][3] end def local_ipaddr?(host_ip) return false unless host_ip + LOCAL_IPADDR.any? { |ip| ip.include?(host_ip) } end end diff --git a/lib/arel/visitors/sqlserver.rb b/lib/arel/visitors/sqlserver.rb index f70cac55c..c28b190f0 100644 --- a/lib/arel/visitors/sqlserver.rb +++ b/lib/arel/visitors/sqlserver.rb @@ -90,8 +90,8 @@ def visit_Arel_Table o, collector else quote_table_name(o.name) end - rescue Exception => e - quote_table_name(o.name) + rescue Exception => e + quote_table_name(o.name) end if o.table_alias collector << "#{table_name} #{quote_table_name o.table_alias}" @@ -176,6 +176,7 @@ def visit_Make_Fetch_Happen o, collector def node_value(node) return nil unless node + case node.expr when NilClass then nil when Numeric then node.expr @@ -189,9 +190,11 @@ def select_statement_lock? def make_Fetch_Possible_And_Deterministic o return if o.limit.nil? && o.offset.nil? + t = table_From_Statement o pk = primary_Key_From_Table t return unless pk + if o.orders.empty? # Prefer deterministic vs a simple `(SELECT NULL)` expr. o.orders = [pk.asc] @@ -222,8 +225,9 @@ def table_From_Statement o def primary_Key_From_Table t return unless t + column_name = @connection.schema_cache.primary_keys(t.name) || - @connection.schema_cache.columns_hash(t.name).first.try(:second).try(:name) + @connection.schema_cache.columns_hash(t.name).first.try(:second).try(:name) column_name ? t[column_name] : nil end diff --git a/test/cases/adapter_test_sqlserver.rb b/test/cases/adapter_test_sqlserver.rb index d20ced9e6..f11ce7f77 100644 --- a/test/cases/adapter_test_sqlserver.rb +++ b/test/cases/adapter_test_sqlserver.rb @@ -76,13 +76,13 @@ class AdapterTestSQLServer < ActiveRecord::TestCase it "test database exists returns false if database does not exist" do config = ActiveRecord::Base.configurations["arunit"].merge(database: "inexistent_activerecord_unittest") assert_not ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(config), - "expected database to not exist" + "expected database to not exist" end it "test database exists returns true when the database exists" do config = ActiveRecord::Base.configurations["arunit"] assert ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(config), - "expected database #{config[:database]} to exist" + "expected database #{config[:database]} to exist" end describe "with different language" do @@ -343,8 +343,8 @@ class AdapterTestSQLServer < ActiveRecord::TestCase assert_equal columns.size, SSTestCustomersView.columns.size columns.each do |colname| assert_instance_of ActiveRecord::ConnectionAdapters::SQLServerColumn, - SSTestCustomersView.columns_hash[colname], - "Column name #{colname.inspect} was not found in these columns #{SSTestCustomersView.columns.map(&:name).inspect}" + SSTestCustomersView.columns_hash[colname], + "Column name #{colname.inspect} was not found in these columns #{SSTestCustomersView.columns.map(&:name).inspect}" end end @@ -370,8 +370,8 @@ class AdapterTestSQLServer < ActiveRecord::TestCase assert_equal columns.size, SSTestStringDefaultsView.columns.size columns.each do |colname| assert_instance_of ActiveRecord::ConnectionAdapters::SQLServerColumn, - SSTestStringDefaultsView.columns_hash[colname], - "Column name #{colname.inspect} was not found in these columns #{SSTestStringDefaultsView.columns.map(&:name).inspect}" + SSTestStringDefaultsView.columns_hash[colname], + "Column name #{colname.inspect} was not found in these columns #{SSTestStringDefaultsView.columns.map(&:name).inspect}" end end @@ -383,7 +383,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase it "find default values" do assert_equal "null", SSTestStringDefaultsView.new.pretend_null, - SSTestStringDefaultsView.columns_hash["pretend_null"].inspect + SSTestStringDefaultsView.columns_hash["pretend_null"].inspect end it "respond true to data_source_exists?" do @@ -398,7 +398,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase it "using alternate view defintion still be able to find real default" do assert_equal "null", SSTestStringDefaultsBigView.new.pretend_null, - SSTestStringDefaultsBigView.columns_hash["pretend_null"].inspect + SSTestStringDefaultsBigView.columns_hash["pretend_null"].inspect end end @@ -474,4 +474,3 @@ def test_doesnt_error_when_a_select_query_is_called_while_preventing_writes end end end - diff --git a/test/cases/coerced_tests.rb b/test/cases/coerced_tests.rb index 782c7d15a..e33fa0bc5 100644 --- a/test/cases/coerced_tests.rb +++ b/test/cases/coerced_tests.rb @@ -459,15 +459,21 @@ module ActiveRecord module DatabaseTasksSetupper def setup @sqlserver_tasks = - Class.new do - def create; end - def drop; end - def purge; end - def charset; end - def collation; end - def structure_dump(*); end - def structure_load(*); end - end.new + Class.new do + def create; end + + def drop; end + + def purge; end + + def charset; end + + def collation; end + + def structure_dump(*); end + + def structure_load(*); end + end.new $stdout, @original_stdout = StringIO.new, $stdout $stderr, @original_stderr = StringIO.new, $stderr @@ -552,8 +558,8 @@ class DatabaseTasksStructureDumpTest < ActiveRecord::TestCase def test_sqlserver_structure_dump with_stubbed_new do assert_called_with( - eval("@sqlserver_tasks"), :structure_dump, - ["awesome-file.sql", nil] + eval("@sqlserver_tasks"), :structure_dump, + ["awesome-file.sql", nil] ) do ActiveRecord::Tasks::DatabaseTasks.structure_dump({ "adapter" => :sqlserver }, "awesome-file.sql") end @@ -568,9 +574,9 @@ class DatabaseTasksStructureLoadTest < ActiveRecord::TestCase def test_sqlserver_structure_load with_stubbed_new do assert_called_with( - eval("@sqlserver_tasks"), - :structure_load, - ["awesome-file.sql", nil] + eval("@sqlserver_tasks"), + :structure_load, + ["awesome-file.sql", nil] ) do ActiveRecord::Tasks::DatabaseTasks.structure_load({ "adapter" => :sqlserver }, "awesome-file.sql") end @@ -1228,6 +1234,7 @@ module ActiveRecord module ConnectionAdapters class SchemaCacheTest < ActiveRecord::TestCase private + # We need to give the full path for this to work. def schema_dump_path File.join ARTest::SQLServer.root_activerecord, "test/assets/schema_dump_5_1.yml" @@ -1237,7 +1244,7 @@ def schema_dump_path end class UnsafeRawSqlTest < ActiveRecord::TestCase - # Use LEN() vs length() function. + # Use LEN() vs length() function. coerce_tests! %r{order: always allows Arel} test "order: always allows Arel" do ids_depr = with_unsafe_raw_sql_deprecated { Post.order(Arel.sql("len(title)")).pluck(:title) } diff --git a/test/cases/column_test_sqlserver.rb b/test/cases/column_test_sqlserver.rb index 09f57a8dc..c1d58a66c 100644 --- a/test/cases/column_test_sqlserver.rb +++ b/test/cases/column_test_sqlserver.rb @@ -14,7 +14,9 @@ class ColumnTestSQLServer < ActiveRecord::TestCase Type = ActiveRecord::ConnectionAdapters::SQLServer::Type def new_obj; SSTestDatatype.new; end + def column(name); SSTestDatatype.columns_hash[name]; end + def assert_obj_set_and_save(attribute, value) obj.send :"#{attribute}=", value _(obj.send(attribute)).must_equal value diff --git a/test/cases/fetch_test_sqlserver.rb b/test/cases/fetch_test_sqlserver.rb index 922bf9e37..266052ce7 100755 --- a/test/cases/fetch_test_sqlserver.rb +++ b/test/cases/fetch_test_sqlserver.rb @@ -49,4 +49,3 @@ def create_10_books @books = (1..10).map { |i| Book.create! name: "Name-#{i}" } end end - diff --git a/test/cases/pessimistic_locking_test_sqlserver.rb b/test/cases/pessimistic_locking_test_sqlserver.rb index f63365356..a8dbbcdb5 100644 --- a/test/cases/pessimistic_locking_test_sqlserver.rb +++ b/test/cases/pessimistic_locking_test_sqlserver.rb @@ -39,11 +39,11 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase it "lock with eager find" do assert_nothing_raised do - Person.transaction do - person = Person.lock(true).includes(:readers).find(1) - _(person).must_equal Person.find(1) - end - end + Person.transaction do + person = Person.lock(true).includes(:readers).find(1) + _(person).must_equal Person.find(1) + end + end end it "can add a custom lock directive" do diff --git a/test/cases/schema_dumper_test_sqlserver.rb b/test/cases/schema_dumper_test_sqlserver.rb index 9a348efa5..3a9a3ad8c 100644 --- a/test/cases/schema_dumper_test_sqlserver.rb +++ b/test/cases/schema_dumper_test_sqlserver.rb @@ -28,14 +28,14 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase assert_line :datetime, type: "datetime", limit: nil, precision: nil, scale: nil, default: "01-01-1753 00:00:00.123" if connection_dblib_73? assert_line :datetime2_7, type: "datetime", limit: nil, precision: 7, scale: nil, default: "12-31-9999 23:59:59.9999999" - assert_line :datetime2_3, type: "datetime", limit: nil, precision: 3, scale: nil, default: nil - assert_line :datetime2_1, type: "datetime", limit: nil, precision: 1, scale: nil, default: nil + assert_line :datetime2_3, type: "datetime", limit: nil, precision: 3, scale: nil, default: nil + assert_line :datetime2_1, type: "datetime", limit: nil, precision: 1, scale: nil, default: nil end assert_line :smalldatetime, type: "smalldatetime", limit: nil, precision: nil, scale: nil, default: "01-01-1901 15:45:00.0" if connection_dblib_73? assert_line :time_7, type: "time", limit: nil, precision: 7, scale: nil, default: "04:20:00.2883215" - assert_line :time_2, type: "time", limit: nil, precision: 2, scale: nil, default: nil - assert_line :time_default, type: "time", limit: nil, precision: 7, scale: nil, default: "15:03:42.0621978" + assert_line :time_2, type: "time", limit: nil, precision: 2, scale: nil, default: nil + assert_line :time_default, type: "time", limit: nil, precision: 7, scale: nil, default: "15:03:42.0621978" end # Character Strings assert_line :char_10, type: "char", limit: 10, precision: nil, scale: nil, default: "1234567890", collation: nil @@ -148,6 +148,7 @@ def generate_schema_for_table(*table_names) type_matcher = /\A\s+t\.\w+\s+"(.*?)"[,\n]/ @generated_schema.each_line do |line| next unless line =~ type_matcher + @schema_lines[Regexp.last_match[1]] = SchemaLine.new(line) end @generated_schema @@ -162,6 +163,7 @@ def assert_line(column_name, options = {}) assert line, "Count not find line with column name: #{column_name.inspect} in schema:\n#{schema}" [:type, :limit, :precision, :scale, :collation, :default].each do |key| next unless options.key?(key) + actual = key == :type ? line.send(:type_method) : line.send(key) expected = options[key] message = "#{key.to_s.titleize} of #{expected.inspect} not found in:\n#{line}" @@ -229,4 +231,3 @@ def parse_options(opts) end end end - diff --git a/test/cases/schema_test_sqlserver.rb b/test/cases/schema_test_sqlserver.rb index b51e7a974..40379cd51 100644 --- a/test/cases/schema_test_sqlserver.rb +++ b/test/cases/schema_test_sqlserver.rb @@ -46,4 +46,3 @@ class SchemaTestSQLServer < ActiveRecord::TestCase end end end - diff --git a/test/cases/utils_test_sqlserver.rb b/test/cases/utils_test_sqlserver.rb index 173b91a72..9ede9ab2b 100644 --- a/test/cases/utils_test_sqlserver.rb +++ b/test/cases/utils_test_sqlserver.rb @@ -18,27 +18,31 @@ class UtilsTestSQLServer < ActiveRecord::TestCase describe ".extract_identifiers constructor and thus SQLServer::Utils::Name value object" do let(:valid_names) { valid_names_unquoted + valid_names_quoted } - let(:valid_names_unquoted) { [ - "server.database.schema.object", - "server.database..object", - "server..schema.object", - "server...object", - "database.schema.object", - "database..object", - "schema.object", - "object" - ]} - - let(:valid_names_quoted) { [ - "[server].[database].[schema].[object]", - "[server].[database]..[object]", - "[server]..[schema].[object]", - "[server]...[object]", - "[database].[schema].[object]", - "[database]..[object]", - "[schema].[object]", - "[object]" - ]} + let(:valid_names_unquoted) { + [ + "server.database.schema.object", + "server.database..object", + "server..schema.object", + "server...object", + "database.schema.object", + "database..object", + "schema.object", + "object" + ] + } + + let(:valid_names_quoted) { + [ + "[server].[database].[schema].[object]", + "[server].[database]..[object]", + "[server]..[schema].[object]", + "[server]...[object]", + "[database].[schema].[object]", + "[database]..[object]", + "[schema].[object]", + "[object]" + ] + } let(:server_names) { valid_names.partition { |name| name =~ /server/ } } let(:database_names) { valid_names.partition { |name| name =~ /database/ } } diff --git a/test/schema/sqlserver_specific_schema.rb b/test/schema/sqlserver_specific_schema.rb index 939d5d077..bae4e4b78 100644 --- a/test/schema/sqlserver_specific_schema.rb +++ b/test/schema/sqlserver_specific_schema.rb @@ -46,7 +46,7 @@ if ENV["IN_MEMORY_OLTP"] && supports_in_memory_oltp? create_table "sst_memory", force: true, id: false, - options: "WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)" do |t| + options: "WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)" do |t| t.primary_key_nonclustered :id t.string :name t.timestamps diff --git a/test/support/coerceable_test_sqlserver.rb b/test/support/coerceable_test_sqlserver.rb index a0fba3fc0..bd8cd0e6d 100644 --- a/test/support/coerceable_test_sqlserver.rb +++ b/test/support/coerceable_test_sqlserver.rb @@ -21,6 +21,7 @@ def coerce_tests!(*methods) def coerce_all_tests! instance_methods(false).each do |method| next unless method.to_s =~ /\Atest/ + undef_method(method) end STDOUT.puts "🙉 🙈 🙊 Undefined all tests: #{self.name}" diff --git a/test/support/connection_reflection.rb b/test/support/connection_reflection.rb index 9fe1ac1fb..154346470 100644 --- a/test/support/connection_reflection.rb +++ b/test/support/connection_reflection.rb @@ -21,6 +21,7 @@ def connection_dblib? def connection_dblib_73? return false unless connection_dblib? + rc = connection.raw_connection rc.respond_to?(:tds_73?) && rc.tds_73? end diff --git a/test/support/rake_helpers.rb b/test/support/rake_helpers.rb index bc0192d00..fb22215d2 100644 --- a/test/support/rake_helpers.rb +++ b/test/support/rake_helpers.rb @@ -5,6 +5,7 @@ def env_ar_test_files return unless ENV["TEST_FILES_AR"] && !ENV["TEST_FILES_AR"].empty? + @env_ar_test_files ||= begin ENV["TEST_FILES_AR"].split(",").map { |file| File.join ARTest::SQLServer.root_activerecord, file.strip @@ -14,6 +15,7 @@ def env_ar_test_files def env_test_files return unless ENV["TEST_FILES"] && !ENV["TEST_FILES"].empty? + @env_test_files ||= ENV["TEST_FILES"].split(",").map(&:strip) end