activerecord-sqlserver-adapter icon indicating copy to clipboard operation
activerecord-sqlserver-adapter copied to clipboard

undefined method `sql_type' for nil:NilClass

Open abhaynikam opened this issue 7 years ago • 0 comments

NOTE:

Please update the reproduction script database adapter to sqlserver

Reproduction steps:

# frozen_string_literal: true

begin
  require "bundler/inline"
rescue LoadError => e
  $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler"
  raise e
end

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  # Activate the gem you are reporting the issue against.
  gem "activerecord", "5.0.7"
  gem "sqlite3"

  # sqlserver in all environments
  group :sqlserver do
    gem 'tiny_tds', '~> 2.1'
    gem 'activerecord-sqlserver-adapter', '5.0.7'
  end
end

require "active_record"
require "minitest/autorun"
require "logger"

# Ensure backward compatibility with Minitest 4
Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)

# Please update the adapter to `adapter: sqlserver` here
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)


ActiveRecord::Schema.define do
  create_table :payments, force: true do |t|
    t.decimal :amount, precision: 10, scale: 0, default: 0, null: false
  end
end

class Payment < ActiveRecord::Base
end

class ChangeAmountToAddScale < ActiveRecord::Migration[5.0]
  def change
    reversible do |dir|
      dir.up do
        rename_column :payments, :amount, :total
        change_column :payments, :total, :decimal, precision: 10, scale: 2, default: 0, null: false
      end
    end
  end
end

class BugTest < Minitest::Test
  def test_migration_up
    ChangeAmountToAddScale.migrate(:up)
    Payment.reset_column_information

    assert_equal "decimal(10,2)", Payment.columns.last.sql_type
  end
end

The error comes from this line(https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/master/lib/active_record/connection_adapters/sqlserver/quoting.rb#L39) where column_object is nil.

After more debugging found that the migration throws error because it first renames the column and then changes the column here

rename_column :payments, :amount, :total
change_column :payments, :total, :decimal, precision: 10, scale: 2, default: 0, null: false

The column object comes null because https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/ed8b1700e4404a529b59f55d6bd76397ee9df737/lib/active_record/connection_adapters/sqlserver/schema_statements.rb#L132-L138

here we do not update the schema_cache after renaming the column. So schema_cache could not find column total while quote_default_expression.

Temporary Solution:

Change the column first and then rename.

change_column :payments, :total, :decimal, precision: 10, scale: 2, default: 0, null: false
rename_column :payments, :amount, :total

Expected:

schema_cache should be updated after rename_column. This might solve the issue here.

I checked here(https://github.com/rails/rails/blob/5-0-stable/activerecord/lib/active_record/connection_adapters/schema_cache.rb) how to update schema_cache but could find any lead.

Environment:

Rails version: 5.0.7 activerecord-sqlserver-adapter version: 5.0.7

abhaynikam avatar Jun 08 '18 13:06 abhaynikam