rails-sqlserver / activerecord-sqlserver-adapter

SQL Server Adapter For Rails
MIT License
968 stars 558 forks source link

Tries to connect to Mysql instead of SQL Server #173

Closed ivanoats closed 12 years ago

ivanoats commented 12 years ago

I don't know if this is an issue with the adapter or my code but I could definitely use some help if available.

Here's my db config:

development:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: c4c_development
  pool: 5
  username: username
  password:
  host: localhost

ipp_v5:
  adapter: sqlserver
  host: host_name.washington.edu
  database: database_name
  username: somewhat_secret
  password: super_secret

Here's my class:

class BDP < ActiveRecord::Base

  establish_connection Rails.configuration.database_configuration["ipp_v5"]

  self.table_name = "Campaign"
  self.primary_key = "CAMPAIGNKEYGUID"
  alias_attribute "id", "CAMPAIGNKEYGUID"

  before_create :set_guid_column

  def set_guid_column
    self[:CAMPAIGNKEYGUID] ||= connection.newid_function
  end

  has_many :projects

end

BDP.find(:first) works.

1.9.3p125 :002 > BDP.offset(2)
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'c4c_development.campaign' doesn't exist: SHOW CREATE TABLE `Campaign`
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `query'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `block in execute'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activesupport-3.2.2/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `execute'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/mysql2_adapter.rb:211:in `execute'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:257:in `execute_and_free'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:515:in `pk_and_sequence_for'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:528:in `primary_key'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/arel-3.0.2/lib/arel/table.rb:40:in `primary_key'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-sqlserver-adapter-3.2.1/lib/arel/visitors/sqlserver.rb:367:in `rowtable_orders'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-sqlserver-adapter-3.2.1/lib/arel/visitors/sqlserver.rb:170:in `visit_Arel_Nodes_SelectStatementWithOffset'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-sqlserver-adapter-3.2.1/lib/arel/visitors/sqlserver.rb:97:in `visit_Arel_Nodes_SelectStatement'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/arel-3.0.2/lib/arel/visitors/visitor.rb:19:in `visit'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/arel-3.0.2/lib/arel/visitors/visitor.rb:5:in `accept'
... 1 levels...
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `to_sql'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/querying.rb:38:in `block in find_by_sql'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/explain.rb:40:in `logging_query_plan'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/querying.rb:37:in `find_by_sql'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/relation.rb:171:in `exec_queries'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/relation.rb:160:in `block in to_a'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/explain.rb:40:in `logging_query_plan'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/relation.rb:159:in `to_a'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/relation.rb:496:in `inspect'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.2/lib/rails/commands/console.rb:47:in `start'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.2/lib/rails/commands/console.rb:8:in `start'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.2/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'1.9.3p125 :003 
metaskills commented 12 years ago

I think the key to your problem may be what you have in Projects and the way you have things setup. Have you read the rails guide on multiple database connections? The way your using Rails.configuration is not right. Just pass a symbol to the yaml key for the connection name, in this case :ipp_v5.

Next, this is a bit of advice, never use establish connection like that in basic AR sub classes. This is a lesson that Rails tries to promote when dealing with multiple DB connections. This google thread and search for "it is always a good idea to have an abstract class that champions a connection/pool to another DB"

So basically you will have something like this.

module DTMF
  class Connection < ActiveRecord::Base
    establish_connection :dtmf_dev
    self.abstract_class = true
  end
end

module DTMF
  class SomeModel < DTML::Connection
    self.table_name = 'db_table_name'
    self.primary_key = 'view_unique_identifier'
  end
end
ivanoats commented 12 years ago

OK - we've reorganized the connections like you suggested, thanks.

BDP.offset(2) works now, we get a Arel object

BDP.offset(2).exists? errs with:

[2] pry(main)> ap BDP.offset(2).exists?
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'c4c_development.campaign' doesn't exist: SHOW CREATE TABLE `Campaign`
from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `query'

this issue seems related: https://github.com/gregbell/active_admin/pull/1062

metaskills commented 12 years ago

It is and that issue spawned this issue https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/161 which was fixed in 3.2.1.

At this point I can not tell you why you are having that issue. I still believe it is something in your Projects model and/or the way you have things setup. You will have to provide some real context and more info if I am able to help.

ivanoats commented 12 years ago

Hi, thanks so much for looking at this and following up, again. It's really wonderful to have another eye on the problem.

I've already removed the belongs_to for Project, so I'm not sure how that could have an affect?

Regarding context, would you like to see the new structure of the models, as you suggested? or something else?

metaskills commented 12 years ago

No problem! And yes, if you are still having a problem. I would love to see the models.

ivanoats commented 12 years ago

OK - I created a brand new rails app, just to test this connection out. In this pastie is all the context: http://pastie.org/3580103

Sorry, gist was acting weird just now. I'm pasting in the raw code below, but it's probably easier to read on pastie with syntax highlighting.

## app/legacy/legacy_connection.rb

class LegacyConnection < ActiveRecord::Base
  establish_connection :ipp
  self.abstract_class = true
end

## app/legacy/bdp.rb

class BDP < LegacyConnection
  self.table_name = 'Campaign'
  self.primary_key = 'CAMPAIGNKEYGUID'

  alias_attribute "id", "CAMPAIGNKEYGUID"
end

## config/database.yml

# MySQL.  Versions 4.1 and 5.0 are recommended.
# 
# Install the MYSQL driver
#   gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
#   gem 'mysql2'
#
# And be sure to use new-style password hashing:
#   http://dev.mysql.com/doc/refman/5.0/en/old-client.html
development:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: ipptest3_development
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock

ipp:
  adapter: sqlserver
  host: secret.host.washington.edu
  database: secret_db
  username: secret_user
  password: secret_password

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: ipptest3_test
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock

production:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: ipptest3_production
  pool: 5
  username: root
  password:

## tree test_app

.
├── Gemfile
├── Gemfile.lock
├── README.rdoc
├── Rakefile
├── app
│   ├── assets
│   │   ├── images
│   │   │   └── rails.png
│   │   ├── javascripts
│   │   │   └── application.js
│   │   └── stylesheets
│   │       └── application.css
│   ├── controllers
│   │   └── application_controller.rb
│   ├── helpers
│   │   └── application_helper.rb
│   ├── legacy
│   │   ├── bdp.rb
│   │   └── legacy_connection.rb
│   ├── mailers
│   ├── models
│   └── views
│       └── layouts
│           └── application.html.erb
├── config
│   ├── application.rb
│   ├── boot.rb
│   ├── database.yml
│   ├── environment.rb
│   ├── environments
│   │   ├── development.rb
│   │   ├── production.rb
│   │   └── test.rb
│   ├── initializers
│   │   ├── backtrace_silencers.rb
│   │   ├── inflections.rb
│   │   ├── mime_types.rb
│   │   ├── secret_token.rb
│   │   ├── session_store.rb
│   │   └── wrap_parameters.rb
│   ├── locales
│   │   └── en.yml
│   └── routes.rb
├── config.ru
├── db
│   └── seeds.rb
├── doc
│   └── README_FOR_APP
├── lib
│   ├── assets
│   └── tasks
├── log
│   └── development.log
├── public
│   ├── 404.html
│   ├── 422.html
│   ├── 500.html
│   ├── favicon.ico
│   └── robots.txt
├── script
│   └── rails
├── test
│   ├── fixtures
│   ├── functional
│   ├── integration
│   ├── performance
│   │   └── browsing_test.rb
│   ├── test_helper.rb
│   └── unit
└── vendor
    ├── assets
    │   ├── javascripts
    │   └── stylesheets
    └── plugins

35 directories, 39 files

## Gemfile

source 'https://rubygems.org'

gem 'rails', '3.2.2'

# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'

gem 'mysql2'
gem 'tiny_tds'
gem 'activerecord-sqlserver-adapter'

# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'

  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
  # gem 'therubyracer'

  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'

# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'

# To use Jbuilder templates for JSON
# gem 'jbuilder'

# Use unicorn as the app server
# gem 'unicorn'

# Deploy with Capistrano
# gem 'capistrano'

# To use debugger
# gem 'ruby-debug19', :require => 'ruby-debug'
metaskills commented 12 years ago

OK, now show me the code and stack trace that exercises the error. The one from above in previous comments does not seem to apply in this last paste.

metalbot commented 12 years ago

Was my issue with model.offset(2).exists? different from his? I pulled the latest source, added a test, and it was clearly failing, though mine was failing with a TinyTDS error, not with an ActiveRecord error. I think he's still going to run into this problem once he moves to the latest version. Apologies for jumping in on someone else's issue...

ivanoats commented 12 years ago

Yes, I still think it's a problem with offset.

13:38:ivan@thuja:config [git:master]  → rails c
Loading development environment (Rails 3.2.2)
1.9.3-p125 :001 > BDP
  SQL (0.7ms)  USE [IPP5UW_dev]
 => BDP(CAMPAIGNKEYGUID: string, ID: integer, Archive_ID: string, Title: string, PlanManager: string, PlanStatus: string, StartDate: datetime, ClosedDate: datetime, PublicTitle: string, Introduction: string, CommercializationPath: string, MarketSize: string, MarketLocation: string, TimeToMarket: string, TechnologyDescription: text, MarketOpportunity: string, LicensingOpportunityOrStatus: string, CREATIONDATE: datetime, MODIFICATIONDATE: datetime, MODIFIER: string, CREATOR: string, isActive: boolean, ActivityLevel: string, Managerkeyguid: string, Notes: text, TechnologyArea: string, Stage: integer, Description: string) 
1.9.3-p125 :002 > BDP.find(:first)
  BDP Load (6.6ms)  EXEC sp_executesql N'SELECT TOP (1) [Campaign].* FROM [Campaign]'
 => #<BDP CAMPAIGNKEYGUID: "0843A94B-3E8E-4558-B4BF-000D408B7014", ID: 6132, Archive_ID: "1234", Title: "Using optical scattering to measure properties of u...", PlanManager: "Person, Lisa", PlanStatus: "Active", StartDate: "2012-01-07 00:00:00", ClosedDate: nil, PublicTitle: "Using optical scattering to measure properties of u...", Introduction: "Flow thingamajic is an increasingly useful analytical...", CommercializationPath: "License", MarketSize: "", MarketLocation: "", TimeToMarket: "", TechnologyDescription: "Professor Dracula at the University of Washington ha...", MarketOpportunity: "The ability to determine dynamic properties of micr...", LicensingOpportunityOrStatus: "here is the text for the licensing opportunity", CREATIONDATE: "2011-03-22 00:00:00", MODIFICATIONDATE: "2012-01-23 10:03:18", MODIFIER: "Tina Ha", CREATOR: "Tina Person", isActive: true, ActivityLevel: "3-Low", Managerkeyguid: "614E396B-522D-43AD-992D-A69576E6DD52", Notes: "adsfadgasdgasdggasdgasdg", TechnologyArea: "Life Sciences", Stage: nil, Description: "dfafasdfafaf"> 
1.9.3-p125 :004 > BDP.find(:all).size
  BDP Load (155.3ms)  EXEC sp_executesql N'SELECT [Campaign].* FROM [Campaign]'
 => 653 
1.9.3-p125 :005 > BDP.offset(2)
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'ipptest3_development.campaign' doesn't exist: SHOW CREATE TABLE `Campaign`
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `query'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `block in execute'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activesupport-3.2.2/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:243:in `execute'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/mysql2_adapter.rb:211:in `execute'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:257:in `execute_and_free'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:515:in `pk_and_sequence_for'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:528:in `primary_key'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/arel-3.0.2/lib/arel/table.rb:39:in `primary_key'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-sqlserver-adapter-3.2.1/lib/arel/visitors/sqlserver.rb:367:in `rowtable_orders'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-sqlserver-adapter-3.2.1/lib/arel/visitors/sqlserver.rb:170:in `visit_Arel_Nodes_SelectStatementWithOffset'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-sqlserver-adapter-3.2.1/lib/arel/visitors/sqlserver.rb:97:in `visit_Arel_Nodes_SelectStatement'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/arel-3.0.2/lib/arel/visitors/visitor.rb:19:in `visit'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/arel-3.0.2/lib/arel/visitors/visitor.rb:5:in `accept'
... 1 levels...
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `to_sql'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/querying.rb:38:in `block in find_by_sql'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/explain.rb:40:in `logging_query_plan'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/querying.rb:37:in `find_by_sql'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/relation.rb:171:in `exec_queries'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/relation.rb:160:in `block in to_a'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/explain.rb:33:in `logging_query_plan'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/relation.rb:159:in `to_a'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.2/lib/active_record/relation.rb:496:in `inspect'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.2/lib/rails/commands/console.rb:47:in `start'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.2/lib/rails/commands/console.rb:8:in `start'
    from /Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.2/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'1.9.3-p125 :006 > 
metaskills commented 12 years ago

Interesting, things are in our stack up to here.

https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/master/lib/arel/visitors/sqlserver.rb#L367

Which is calling #primary key on a found Arel table. The table returned comes from this table_from_select_statement method in our visitor.

https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/master/lib/arel/visitors/sqlserver.rb#L218

Perhaps it is getting this line Arel::Table.new(x, @engine) and either @eninge is nil or the approach is wrong for the current version of Arel. We have some notes there, can you do some debugging and let me know? Just a little bit to busy to dig into this now but would gladly take a patch or help till then. FWIW, we could test for this too using SQLite in our own test suite, maybe. Either way, let me know what you find out.

metaskills commented 12 years ago

Whoops, forgot to mention, the AR test suite has two connections. It would be easy to add a test for this and as @metalbot has said, he confirmed just that. So perhaps do some debugging for me in the context of this project and it's test suite which would get us to a patch faster.

metalbot commented 12 years ago

I can duplicate this problem in a quick application that I threw together:

  1. Generate basic rails application (sqlite connection)
  2. Add appropriate gems to Gemfile to support activerecord-sqlserver-adapter
  3. Create a new entry in database.yml that points to a SQL Server database
  4. Create an abstract connection class that inherits from ActiveRecord::Base and sets the connection to my SQL server entry.
  5. Create a model that inherits from my connection class.
  6. Fire up rails console
  7. Model.offset(2) fails with identical error.

I've tried a couple of other permutations:

  1. Make my development database another connection to the same database as the abstract connector. In this case, everything works fine.
  2. Make my development database a connection to the activerecord_unittest database. In this case, Model.offset(3) fails with "object doesn't support #inspect"

I'll see if I can debug the problem, and that may help me produce a simpler failing unit test.

ivanoats commented 12 years ago

Thanks for chiming in! I am trying to use debug to see what's going on. It seems like the @engine.connection is being set to Mysql2Adapter somehow:

16:17:ivan@thuja:config [git:master]  → rails c --debugger
=> Debugger enabled
Loading development environment (Rails 3.2.2)
1.9.3-p125 :001 > BDP.offset(2)
  SQL (0.7ms)  USE [LEGACY_dev]
/Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-sqlserver-adapter-3.2.1/lib/arel/visitors/sqlserver.rb:367
t = table_from_select_statement(o)
(rdb:1) irb
irb(#<Arel::Visitors::SQLServer:0x007feaf3d88980>):001:0> o
=> #<Arel::Nodes::SelectStatement:0x007feaf730b940 @cores=[#<Arel::Nodes::SelectCore:0x007feaf730b918 @source=#<Arel::Nodes::JoinSource:0x007feaf730b8f0 @left=#<Arel::Table:0x007feaf3c998f8 @name="Campaign", @engine=ActiveRecord::Base, @columns=nil, @aliases=[], @table_alias=nil, @primary_key=nil>, @right=[]>, @top=nil, @set_quantifier=nil, @projections=[#<struct Arel::Attributes::Attribute relation=#<Arel::Table:0x007feaf3c998f8 @name="Campaign", @engine=ActiveRecord::Base, @columns=nil, @aliases=[], @table_alias=nil, @primary_key=nil>, name="*">], @wheres=[], @groups=[], @having=nil>], @orders=[], @limit=#<Arel::Nodes::Limit:0x007feaf730b210 @expr=9223372036854775807>, @lock=nil, @offset=#<Arel::Nodes::Offset:0x007feaf730b648 @expr=2>, @with=nil>
irb(#<Arel::Visitors::SQLServer:0x007feaf3d88980>):002:0> exit
/Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-sqlserver-adapter-3.2.1/lib/arel/visitors/sqlserver.rb:367
t = table_from_select_statement(o)
(rdb:1) next
/Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-sqlserver-adapter-3.2.1/lib/arel/visitors/sqlserver.rb:368
c = t.primary_key || t.columns.first
(rdb:1) p t
#<Arel::Table:0x007feaf3c998f8 @name="Campaign", @engine=ActiveRecord::Base, @columns=nil, @aliases=[], @table_alias=nil, @primary_key=nil>
(rdb:1) step
/Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/arel-3.0.2/lib/arel/table.rb:33
if $VERBOSE
(rdb:1) step
/Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/arel-3.0.2/lib/arel/table.rb:42
end
(rdb:1) p $VERBOSE
false
(rdb:1) step
/Users/ivan/.rvm/gems/ruby-1.9.3-p125/gems/arel-3.0.2/lib/arel/table.rb:39
primary_key_name = @engine.connection.primary_key(name)
(rdb:1) p @engine
ActiveRecord::Base
(rdb:1) p @engine.connection
#<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007feaf3c81c08 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x007feaf3c81b18>, @active=nil, @connection=#<Mysql2::Client:0x007feaf3c82040>, @in_use=true, @instrumenter=#<ActiveSupport::Notifications::Instrumenter:0x007feaf3f3a508 @id="18ab5ffa42b119539472", @notifier=#<ActiveSupport::Notifications::Fanout:0x007feaf44085a8 @subscribers=[#<ActiveSupport::Notifications::Fanout::Subscriber:0x007feaf43a2000 @pattern="sql.active_record", @delegate=#<ActiveRecord::LogSubscriber:0x007feaf439c880 @odd_or_even=true>>, #<ActiveSupport::Notifications::Fanout::Subscriber:0x007feaf43a1308 @pattern="identity.active_record", @delegate=#<ActiveRecord::LogSubscriber:0x007feaf439c880 @odd_or_even=true>>, #<ActiveSupport::Notifications::Fanout::Subscriber:0x007feaf439fd78 @pattern="odd?.active_record", @delegate=#<ActiveRecord::LogSubscriber:0x007feaf439c880 @odd_or_even=true>>, #<ActiveSupport::Notifications::Fanout::Subscriber:0x007feaf439e4c8 @pattern="logger.active_record", @delegate=#<ActiveRecord::LogSubscriber:0x007feaf439c880 @odd_or_even=true>>, #<ActiveSupport::Notifications::Fanout::Subscriber:0x007feaf43c3d40 @pattern="sql.active_record", @delegate=#<ActiveRecord::ExplainSubscriber:0x007feaf43c3db8>>], @listeners_for={"sql.active_record"=>[#<ActiveSupport::Notifications::Fanout::Subscriber:0x007feaf43a2000 @pattern="sql.active_record", @delegate=#<ActiveRecord::LogSubscriber:0x007feaf439c880 @odd_or_even=true>>, #<ActiveSupport::Notifications::Fanout::Subscriber:0x007feaf43c3d40 @pattern="sql.active_record", @delegate=#<ActiveRecord::ExplainSubscriber:0x007feaf43c3db8>>]}>>, @last_use=2012-03-12 16:19:09 -0700, @logger=#<ActiveSupport::TaggedLogging:0x007feaf414e718 @logger=#<ActiveSupport::BufferedLogger:0x007feaf414eec0 @level=0, @log_dest=#<File:/Users/ivan/dev/ipptest3/log/development.log>, @log=#<Logger:0x007feaf414edf8 @progname=nil, @level=0, @default_formatter=#<Logger::Formatter:0x007feaf414ed30 @datetime_format=nil>, @formatter=#<Logger::SimpleFormatter:0x007feaf414e740 @datetime_format=nil>, @logdev=#<Logger::LogDevice:0x007feaf414e830 @shift_size=nil, @shift_age=nil, @filename=nil, @dev=#<File:/Users/ivan/dev/ipptest3/log/development.log>, @mutex=#<Logger::LogDevice::LogDeviceMutex:0x007feaf414e808 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x007feaf414e7b8>>>>>, @tags={}>, @open_transactions=0, @pool=#<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007feaf3d1d7e8 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x007feaf3d1d798>, @spec=#<ActiveRecord::Base::ConnectionSpecification:0x007feaf3d42890 @config={:adapter=>"mysql2", :encoding=>"utf8", :reconnect=>false, :database=>"ipptest3_development", :pool=>5, :username=>"root", :password=>nil, :socket=>"/tmp/mysql.sock", :flags=>2}, @adapter_method="mysql2_connection">, @reserved_connections={70323542379740=>#<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007feaf3c81c08 ...>}, @queue=#<MonitorMixin::ConditionVariable:0x007feaf3d1d748 @monitor=#<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007feaf3d1d7e8 ...>, @cond=#<ConditionVariable:0x007feaf3d1d720 @waiters=[], @waiters_mutex=#<Mutex:0x007feaf3d1d6d0>>>, @timeout=5, @size=5, @connections=[#<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007feaf3c81c08 ...>], @automatic_reconnect=true>, @query_cache={}, @query_cache_enabled=false, @schema_cache=#<ActiveRecord::ConnectionAdapters::SchemaCache:0x007feaf3f3a210 @connection=#<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007feaf3c81c08 ...>, @tables={}, @columns={}, @columns_hash={}, @primary_keys={}>, @visitor=#<ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::BindSubstitution:0x007feaf3f39fe0 @block=nil, @connection=#<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007feaf3c81c08 ...>, @schema_cache=#<ActiveRecord::ConnectionAdapters::SchemaCache:0x007feaf3f3a210 @connection=#<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007feaf3c81c08 ...>, @tables={}, @columns={}, @columns_hash={}, @primary_keys={}>, @quoted_tables={}, @quoted_columns={}, @last_column=nil>, @config={:adapter=>"mysql2", :encoding=>"utf8", :reconnect=>false, :database=>"ipptest3_development", :pool=>5, :username=>"root", :password=>nil, :socket=>"/tmp/mysql.sock", :flags=>2}, @connection_options=[nil, "root", nil, "ipptest3_development", nil, "/tmp/mysql.sock", 0], @quoted_table_names={}, @quoted_column_names={}>
(rdb:1) 

I'll keep working on this to see if I can figure out why

metaskills commented 12 years ago

Thanks to both of you. I wonder if this is an issue with Arel too. I did not see any tickets on their page that suggested someone reported something similar. I also did not dig into issue in the rails github project either. So maybe a dive there too?

ivanoats commented 12 years ago

yeah, this is not right, right?

17:20:ivan@thuja:config [git:master+]  → rails c --debugger
=> Debugger enabled
Loading development environment (Rails 3.2.2)
1.9.3-p125 :001 > bdp = BDP.arel_table
 => #<Arel::Table:0x007fe8dd6ed9a8 @name="Campaign", @engine=ActiveRecord::Base, @columns=nil, @aliases=[], @table_alias=nil, @primary_key=nil> 
1.9.3-p125 :002 > bdp = BDP.arel_table.engine.connection
 => #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007fe8dbe3ab90 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x007fe8dbe3aa78>, @active=nil, @connection=#<Mysql2::Client:0x007fe8dbe3afa0>, @in_use=true, @instrumenter=#<ActiveSupport::Notifications::Instrumenter:0x007fe8dbe67460 @id="d9f207fec474517eb6f5", @notifier=#<ActiveSupport::Notifications::Fanout:0x007fe8dc25fce8 @subscribers=[#<ActiveSupport::Notifications::Fanout::Subscriber:0x007fe8dc1f96f0 @pattern="sql.active_record", @delegate=#<ActiveRecord::LogSubscriber:0x007fe8dc1f3f48 @odd_or_even=false>>, #<ActiveSupport::Notifications::Fanout::Subscriber:0x007fe8dc1f8570 @pattern="identity.active_record", @delegate=#<ActiveRecord::LogSubscriber:0x007fe8dc1f3f48 @odd_or_even=false>>, #<ActiveSupport::Notifications::Fanout::Subscriber:0x007fe8dc1f6fe0 @pattern="odd?.active_record", @delegate=#<ActiveRecord::LogSubscriber:0x007fe8dc1f3f48 @odd_or_even=false>>, #<ActiveSupport::Notifications::Fanout::Subscriber:0x007fe8dc1f5c08 @pattern="logger.active_record", @delegate=#<ActiveRecord::LogSubscriber:0x007fe8dc1f3f48 @odd_or_even=false>>, #<ActiveSupport::Notifications::Fanout::Subscriber:0x007fe8dc21b458 @pattern="sql.active_record", @delegate=#<ActiveRecord::ExplainSubscriber:0x007fe8dc21b4a8>>], @listeners_for={}>>, @last_use=2012-03-12 17:20:50 -0700, @logger=#<ActiveSupport::TaggedLogging:0x007fe8da928ce8 @logger=#<ActiveSupport::BufferedLogger:0x007fe8da929490 @level=0, @log_dest=#<File:/Users/ivan/dev/ipptest3/log/development.log>, @log=#<Logger:0x007fe8da9293f0 @progname=nil, @level=0, @default_formatter=#<Logger::Formatter:0x007fe8da929328 @datetime_format=nil>, @formatter=#<Logger::SimpleFormatter:0x007fe8da928d10 @datetime_format=nil>, @logdev=#<Logger::LogDevice:0x007fe8da928e00 @shift_size=nil, @shift_age=nil, @filename=nil, @dev=#<File:/Users/ivan/dev/ipptest3/log/development.log>, @mutex=#<Logger::LogDevice::LogDeviceMutex:0x007fe8da928dd8 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x007fe8da928d88>>>>>, @tags={}>, @open_transactions=0, @pool=#<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007fe8dbdb0580 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x007fe8dbdb0530>, @spec=#<ActiveRecord::Base::ConnectionSpecification:0x007fe8dbb35418 @config={:adapter=>"mysql2", :encoding=>"utf8", :reconnect=>false, :database=>"ipptest3_development", :pool=>5, :username=>"root", :password=>nil, :socket=>"/tmp/mysql.sock", :flags=>2}, @adapter_method="mysql2_connection">, @reserved_connections={70319033502940=>#<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007fe8dbe3ab90 ...>}, @queue=#<MonitorMixin::ConditionVariable:0x007fe8dbdb04e0 @monitor=#<ActiveRecord::ConnectionAdapters::ConnectionPool:0x007fe8dbdb0580 ...>, @cond=#<ConditionVariable:0x007fe8dbdb04b8 @waiters=[], @waiters_mutex=#<Mutex:0x007fe8dbdb0468>>>, @timeout=5, @size=5, @connections=[#<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007fe8dbe3ab90 ...>], @automatic_reconnect=true>, @query_cache={}, @query_cache_enabled=false, @schema_cache=#<ActiveRecord::ConnectionAdapters::SchemaCache:0x007fe8dbe67190 @connection=#<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007fe8dbe3ab90 ...>, @tables={}, @columns={}, @columns_hash={}, @primary_keys={}>, @visitor=#<ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::BindSubstitution:0x007fe8dbe66ec0 @block=nil, @connection=#<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007fe8dbe3ab90 ...>, @schema_cache=#<ActiveRecord::ConnectionAdapters::SchemaCache:0x007fe8dbe67190 @connection=#<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x007fe8dbe3ab90 ...>, @tables={}, @columns={}, @columns_hash={}, @primary_keys={}>, @quoted_tables={}, @quoted_columns={}, @last_column=nil>, @config={:adapter=>"mysql2", :encoding=>"utf8", :reconnect=>false, :database=>"ipptest3_development", :pool=>5, :username=>"root", :password=>nil, :socket=>"/tmp/mysql.sock", :flags=>2}, @connection_options=[nil, "root", nil, "ipptest3_development", nil, "/tmp/mysql.sock", 0], @quoted_table_names={}, @quoted_column_names={}> 
1.9.3-p125 :003 > 
metaskills commented 12 years ago

Perhaps a bug in the 3.2 connection pool code? Here is the arel stuff from ActiveRecord's base.rb

def arel_table
  @arel_table ||= Arel::Table.new(table_name, arel_engine)
end

def arel_engine
  @arel_engine ||= begin
    if self == ActiveRecord::Base
      ActiveRecord::Base
    else
      connection_handler.connection_pools[name] ? self : superclass.arel_engine
    end
  end
end

So this could be a bug in ActiveRecord. Or us learning ways the new connection pool works. I suggest looking in rails issues and let me know. Also, I remember Aaron Patterson talking about changes to the pool and maybe this is a regression. Lemme know what you find out.

metalbot commented 12 years ago

Curiouser and curiouser.

Now I'm not sure why anything would be working correctly. Even after I've performed operations on that table (find, where), it still seems to have an arel_table.engine.connection that points at the sqlite adapter. That would seem to imply that when individual finder methods are being called that they aren't actually using the arel_table that we have. If I have time, I'm going to make an educational dive into the find method of ActiveRecord and see how it actually uses the underlying Arel tables...

metalbot commented 12 years ago

Your instincts are right on.

With the help of a bit of "pry" in the arel_engine method, here's what I'm seeing:

  1. "name" is defined as "MyModelName".
  2. connection_handler.connection_pools is never going to find "MyModelName", because it's a hash, and the keys are all instances of ActiveRecord::Base::ConnectionSpecification.
  3. If I look at the keys currently present in ActiveRecord::Base::ConnectionSpecification, I see 2: one that corresponds to sqlite3, and another that corresponds to sqlserver. So the right connection pool is there, but ActiveRecord is using the wrong mechanism to look it up.

Should I go ahead and open a rails issue?

metaskills commented 12 years ago

So in your example name would be "BDP" right? And given your example superclass would be LegacyConnection so I am curious, what does LegacyConnection.arel_engine return?

metalbot commented 12 years ago

Both return ActiveRecord::Base for me.

metaskills commented 12 years ago

Yea, file a ticket on rails and keep this one open. I will ask Aaron to take a look and put some time into this too. If you could shoot a link here to that ticket.

metalbot commented 12 years ago

https://github.com/rails/rails/issues/5399

metalbot commented 12 years ago

That was fast:

https://github.com/rails/rails/issues/5399

Note that much of the functionality of base.rb was pulled out to core.rb, so anyone wanting to fix this on an earlier version of rails would need to apply the patch to base.rb rather than core.rb.

metaskills commented 12 years ago

Good work guys! Thanks for the back and forth!