Rails 3.1, Ruby 1.9.2, using a SQL Server 2008 database through the activerecord-sqlserver-adapter gem. I’m working with a legacy database, so this was not voluntary.
I’m running into an odd problem with ActiveAdmin. I’ve not used ActiveAdmin before, and added it after watching a Railscast. Followed the standard installation instructions, and I’m able to log into the admin console.
When I add a model:
rails generate active_admin:resource Payment
The model (in plural) is now visible on the ActiveAdmin dashboard. However, when I click on the link, I get the following error:
TinyTds::Error: No column name was specified for column 2 of '__rnt'.: EXEC
sp_executesql N'SELECT TOP (1) [__rnt].* FROM ( SELECT ROW_NUMBER() OVER (ORDER
BY [Payments].[UPaymentID] ASC) AS [__rn], 1 FROM [Payments] ) AS [__rnt]
WHERE [__rnt].[__rn] > (0) ORDER BY [__rnt].[__rn] ASC'
Now, this query returns the same error if I run it directly on the SQL Server database – it doesn’t like the unnamed column of “1”.
Started digging to see what the issue was. The obvious places to look would be in the transitions between activeadmin and activerecord, and then activerecord and the SQL Server adapter. Here’s the stack trace for the first intersection:
activerecord (3.1.0) lib/active_record/relation/finder_methods.rb:197:in `exists?'
activeadmin (0.4.2) lib/active_admin/views/pages/index.rb:41:in `items_in_collection?'
activeadmin (0.4.2) lib/active_admin/views/pages/index.rb:20:in `main_content'
It looks like items_in_collection? is calling exists? on a collection that has had order filters removed. At this point, we’re handing off to ActiveRecord. If we look at the transition from ActiveRecord to the SQL Server adapter, it looks as if the SELECT statement has already been formed:
activerecord-sqlserver-adapter (3.1.6) lib/active_record/connection_adapters/sqlserver/database_statements.rb:348:in `do_exec_query'
activerecord-sqlserver-adapter (3.1.6) lib/active_record/connection_adapters/sqlserver/database_statements.rb:24:in `exec_query'
activerecord-sqlserver-adapter (3.1.6) lib/active_record/connection_adapters/sqlserver/database_statements.rb:297:in `select'
activerecord (3.1.0) lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
activerecord (3.1.0) lib/active_record/connection_adapters/abstract/query_cache.rb:61:in `block in select_all'
I’m totally confused as to why the SQL would be generated the way that it is. There are a couple of candidate problem areas:
- I’m working on a legacy database with an odd schema. I’m having to set table names and primary key names within my models. I don’t think this is the issue, since the query that is coming out seems to use the appropriate primary key and table names.
- Problems with the
activerecord-sqlserver-adaptergem. However, I pulled the source code, and it sure doesn’t look like there is anything there that would be assembling this query in that way.
Has anyone run into anything similar to this? It may be that I’ll just need to debug my way through the whole stack to see what’s going on. Figured it would be worth checking here first though.
Edit: I’m now fairly sure this is a bug in activerecord-sqlserver-adapter. Will post resolution here once I have it.
Edit2: Can reproduce the error without ActiveAdmin at all. This is related to the way that the sql server adapter deals with offset queries. Calling
MyModel.offset(1).exists?
produces the same error. I have an ugly patch to the adapter which passes all the unit tests, but I’m going to try to find a more elegant solution before making a pull request.
I’m not sure this is exactly the answer, but I patched my local code and your query works for me now.
First, the github issue:
https://github.com/rails/rails/issues/1623
and then the pull request for arkadiyk’s fix:
https://github.com/arkadiyk/rails/commit/7e2ddddb303d17adc825ebb691097a93902fa539
The basic problem is finder_methods.rb, which has the existing code around line 187 or 188:
MSSQL barfs on the unnamed column this generates, so the following code fixes it:
Hope that helps.