Rails 4 - MS SQL select * statement returning total count

1.3k views Asked by At

I'm trying to run a select statement on a table in a MS SQL Server 2008 database from within a Rails application This is related to the Gem acts-as-taggable-on if that helps any.

There is no model/controller/ActiveRecord for this table, so doing something like Tags.all (or any of the normal methods) won't do anything.

I'm on Arch Linux, Ruby 2.1.6 Rails 4.1.11.

I want the "name" field returned, but for now I'll settle on just returning all of the fields with a select * statement.

From the rails console, these are the commands I'm running.

sql = "SELECT * FROM Tags"  
ActiveRecord::Base.connection.execute(sql)

Which returns:

SELECT * FROM Tags  
=> 191

What I expected was all 191 rows of all the fields

(id:integer 4, name:string 255, taggings_count:integer 4)

Running a similar select statement from within the MS SQL Server Manager software returns the expected output.

The database.yml is properly connected to the MS SQL database.

Its like the sql statement is trying to run a count(*) query instead of a * query. But, if I run a count(*) query, it returns 1 instead of 191.

I'm completely lost, as are my co-workers, on what could be causing this. And internet searches resulted nothing of any use.

UPDATE: (6/25/15 1PM)
Out of curiosity I switched the database back to sqlite, and the queries work. So it must be an incompatibility with sql server 2008 and something in my app.

Gemfile:

source 'https://rubygems.org'

gem 'rails', '4.1.11'
gem 'railties'
gem 'actionpack'
gem 'activesupport'
gem 'will_paginate'
gem 'sqlite3'
gem 'icalendar', '2.3.0'
gem 'formtastic'
gem 'rubycas-client'
gem 'rake', '10.4.2'
gem 'tiny_tds'
gem 'selenium-webdriver', '2.46.2'
gem 'tilt'
gem 'websocket', '1.2.2'
gem 'xpath', '2.0.0'
gem 'rails3-jquery-autocomplete'
gem 'rack'
gem 'auto_complete'
gem 'dynamic_form'
gem 'jquery-timepicker-addon-rails'
gem 'email_spec'
gem 'acts-as-taggable-on'
gem 'rails-dom-testing'
gem 'globalid'
gem 'sprockets-rails'
gem 'rspec-rails'
gem 'person_record', :path => "vendor/gems/person_record-0_0_2", :require => "person_record"
gem 'activerecord-sqlserver-adapter'
gem 'test-unit', '1.2.3'
gem 'arel'


gem 'sass-rails'
gem 'coffee-rails'
gem 'uglifier'

group :development, :test do
  gem 'capybara', '2.4.4'
  gem 'rubyzip', '1.1.7'
  gem 'mocha', '1.1.0', :require => false
  gem 'byebug'
  gem 'spring'
end

group :test do
  gem 'cucumber-rails', :require => false
  gem 'webrat'
  gem 'database_cleaner'
end

# Deploy with Capistrano
gem 'capistrano'
gem 'capistrano-rails', '1.1.3'
gem 'rvm-capistrano', :require => false
3

There are 3 answers

6
Philip Devine On

Try explicitly naming all fields in the select. Also, make sure you store the result:

result = ActiveRecord::Base.connection.execute(sql)

result.fetch_row.first;

For debugging, could also try:

result.each do |row|
  p row.id
  p row.name
  etc.
end
0
Magne On

execute Rails API documentation:

Executes the SQL statement in the context of this connection and returns the raw result from the connection adapter. Note: depending on your database connector, the result returned by this method may be manually memory managed. Consider using the #exec_query wrapper instead.

http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html#method-i-execute

Basically, SQLite does nothing fancy with the raw SQL, so:

ActiveRecord::Base.connection.execute("Select * FROM users")

will output all the users (not in a result set, but as hash objects in an array).

Whereas in SQLServer that will only give out the count. Because of the fancy memory management the doc above mentions. The SQLServer adapter in Rails probably wants to make sure people don't impede performance by executing queries giving out large result sets.

Notice the different resulting SQL calls the Rails adapter makes in SQLServer for :

irb(main):036:0> ActiveRecord::Base.connection.execute("Select * FROM users")
D, [2017-11-01T11:13:11.942930 #29223] DEBUG -- :    (272.6ms)  Select * FROM users
=> 36613

irb(main):050:0> ActiveRecord::Base.connection.exec_query("Select * FROM users")
D, [2017-11-01T13:10:09.218935 #29223] DEBUG -- :   SQL (1063.8ms)  EXEC sp_executesql N'Select * FROM users'

irb(main):035:0> ActiveRecord::Base.connection.select_all("Select * FROM users")
D, [2017-11-01T11:13:01.574966 #29223] DEBUG -- :    (1211.2ms)  EXEC sp_executesql N'Select * FROM users'

So, in SQLServer you'd have to instead use:

ActiveRecord::Base.connection.exec_query("Select * FROM users")

or, like @kwerle said:

ActiveRecord::Base.connection.select_all("Select * FROM users")

0
kwerle On
ActiveRecord::Base.connection.select_all(sql)