diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 93ae6e9c360cb7b3fd6d06dc2da329dd8246d169..faa521f5eebab4c7690fe2900e6634935a0e95f2 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,9 @@ *SVN* +* SQLServer: correctly schema-dump tables with no indexes or descending indexes. #7333, #7703 [Jakob S, Tom Ward] + +* SQLServer: recognize real column type as Ruby float. #7057 [sethladd, Tom Ward] + * Added fixtures :all as a way of loading all fixtures in the fixture directory at once #7214 [manfred] * Added database connection as a yield parameter to ActiveRecord::Base.transaction so you can manually rollback [DHH]. Example: diff --git a/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb index e85a826942e22b86a7af2e2a256ea0a2b080b556..5463bb645f22e5a79b71a27abc436f0544527788 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlserver_adapter.rb @@ -41,7 +41,7 @@ def self.sqlserver_connection(config) #:nodoc: raise ArgumentError, "Missing Database. Argument ':database' must be set in order for this adapter to work." unless config.has_key?(:database) database = config[:database] host = config[:host] ? config[:host].to_s : 'localhost' - driver_url = "DBI:ADO:Provider=SQLOLEDB;Data Source=#{host};Initial Catalog=#{database};User Id=#{username};Password=#{password};" + driver_url = "DBI:ADO:Provider=SQLOLEDB;Data Source=#{host};Initial Catalog=#{database};User ID=#{username};Password=#{password};" end conn = DBI.connect(driver_url, username, password) conn["AutoCommit"] = autocommit @@ -64,6 +64,7 @@ def initialize(name, default, sql_type = nil, identity = false, null = true) # T def simplified_type(field_type) case field_type + when /real/i then :float when /money/i then :decimal when /image/i then :binary when /bit/i then :boolean @@ -168,11 +169,13 @@ def self.binary_to_string(value) # * :mode -- ADO or ODBC. Defaults to ADO. # * :username -- Defaults to sa. # * :password -- Defaults to empty string. + # * :windows_auth -- Defaults to "User ID=#{username};Password=#{password}" # # ADO specific options: # # * :host -- Defaults to localhost. # * :database -- The name of the database. No default, must be provided. + # * :windows_auth -- Use windows authentication instead of username/password. # # ODBC specific options: # @@ -419,9 +422,9 @@ def current_database def tables(name = nil) execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'", name) do |sth| - sth.inject([]) do |tables, field| + result = sth.inject([]) do |tables, field| table_name = field[0] - tables << table_name unless table_name == 'dtproperties' + tables << table_name unless table_name == 'dtproperties' tables end end @@ -430,18 +433,20 @@ def tables(name = nil) def indexes(table_name, name = nil) ActiveRecord::Base.connection.instance_variable_get("@connection")["AutoCommit"] = false indexes = [] - execute("EXEC sp_helpindex '#{table_name}'", name) do |sth| - sth.each do |index| - unique = index[1] =~ /unique/ - primary = index[1] =~ /primary key/ - if !primary - indexes << IndexDefinition.new(table_name, index[0], unique, index[2].split(", ")) + execute("EXEC sp_helpindex '#{table_name}'", name) do |handle| + if handle.column_info.any? + handle.each do |index| + unique = index[1] =~ /unique/ + primary = index[1] =~ /primary key/ + if !primary + indexes << IndexDefinition.new(table_name, index[0], unique, index[2].split(", ").map {|e| e.gsub('(-)','')}) + end end end end indexes - ensure - ActiveRecord::Base.connection.instance_variable_get("@connection")["AutoCommit"] = true + ensure + ActiveRecord::Base.connection.instance_variable_get("@connection")["AutoCommit"] = true end def rename_table(name, new_name) @@ -473,6 +478,11 @@ def change_column(table_name, column_name, type, options = {}) #:nodoc: } end + def change_column_default(table_name, column_name, default) + remove_default_constraint(table_name, column_name) + execute "ALTER TABLE #{table_name} ADD CONSTRAINT DF_#{table_name}_#{column_name} DEFAULT #{quote(default, column_name)} FOR #{column_name}" + end + def remove_column(table_name, column_name) remove_check_constraints(table_name, column_name) remove_default_constraint(table_name, column_name) diff --git a/activerecord/test/adapter_test_sqlserver.rb b/activerecord/test/adapter_test_sqlserver.rb index bf74671209d2befd5e531704e2edd477dc8931fb..548668d5e71e66984528202b8986185cbe2e9c78 100644 --- a/activerecord/test/adapter_test_sqlserver.rb +++ b/activerecord/test/adapter_test_sqlserver.rb @@ -4,6 +4,8 @@ require 'fixtures/task' class SqlServerAdapterTest < Test::Unit::TestCase + class TableWithRealColumn < ActiveRecord::Base; end + fixtures :posts, :tasks def setup @@ -11,7 +13,11 @@ def setup end def teardown - @connection.execute("SET LANGUAGE us_english") + @connection.execute("SET LANGUAGE us_english") rescue nil + end + + def test_real_column_has_float_type + assert_equal :float, TableWithRealColumn.columns_hash["real_number"].type end # SQL Server 2000 has a bug where some unambiguous date formats are not @@ -24,6 +30,14 @@ def test_date_insertion_when_language_is_german end end + def test_indexes_with_descending_order + # Make sure we have an index with descending order + @connection.execute "CREATE INDEX idx_credit_limit ON accounts (credit_limit DESC)" rescue nil + assert_equal ["credit_limit"], @connection.indexes('accounts').first.columns + ensure + @connection.execute "DROP INDEX accounts.idx_credit_limit" + end + def test_execute_without_block_closes_statement assert_all_statements_used_are_closed do @connection.execute("SELECT 1") diff --git a/activerecord/test/fixtures/db_definitions/schema.rb b/activerecord/test/fixtures/db_definitions/schema.rb index b5d7704d2e958f0660b84821c1c4bf1e65eb176b..3dc9a9b8a3a50327f94ff4c3a292d1f5f378f45f 100644 --- a/activerecord/test/fixtures/db_definitions/schema.rb +++ b/activerecord/test/fixtures/db_definitions/schema.rb @@ -64,4 +64,11 @@ def create_table(*args, &block) t.column :name, :string end end + + # For sqlserver 2000+, ensure real columns can be used + if adapter_name.starts_with?("SQLServer") + create_table :table_with_real_columns, :force => true do |t| + t.column :real_number, :real + end + end end