ActiveAdmin 查询期间缺少列名称
Rails 3.1、Ruby 1.9.2,通过 activerecord-sqlserver-adapter gem 使用 SQL Server 2008 数据库。我正在使用旧数据库,所以这不是自愿的。
我在使用 ActiveAdmin 时遇到了一个奇怪的问题。我以前没有使用过ActiveAdmin,是在观看Railscast 后添加的。遵循标准安装说明,我可以登录管理控制台。
当我添加模型时:
rails generate active_admin:resource Payment
模型(复数形式)现在在 ActiveAdmin 仪表板上可见。但是,当我单击该链接时,出现以下错误:
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'
现在,如果我直接在 SQL Server 数据库上运行该查询,它会返回相同的错误 - 它不喜欢未命名的“1”列。
开始挖掘以了解问题所在。明显需要注意的地方是 activeadmin 和 activerecord 之间的转换,然后是 activerecord 和 SQL Server 适配器之间的转换。这是第一个交叉点的堆栈跟踪:
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'
它看起来像 items_in_collection?呼叫存在吗?在已删除订单过滤器的集合上。此时,我们将移交给 ActiveRecord。如果我们查看从 ActiveRecord 到 SQL Server 适配器的转换,就会发现 SELECT 语句似乎已经形成:
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'
我完全困惑为什么 SQL 会以这种方式生成。有几个候选问题领域:
- 我正在开发一个具有奇怪模式的遗留数据库。我必须在模型中设置表名称和主键名称。我不认为这是问题所在,因为出现的查询似乎使用了适当的主键和表名。
activerecord-sqlserver-adapter
gem 出现问题。但是,我提取了源代码,并且看起来确实没有任何内容可以以这种方式组装此查询。
有人遇到过类似的事情吗?可能我只需要调试整个堆栈来看看发生了什么。我认为值得先在这里检查一下。
编辑:我现在相当确定这是 activerecord-sqlserver-adapter 中的错误。一旦我有了解决方案,就会在这里发布解决方案。
Edit2:根本不需要 ActiveAdmin 就可以重现错误。这与sql server适配器处理偏移查询的方式有关。调用
MyModel.offset(1).exists?
会产生相同的错误。我的适配器有一个丑陋的补丁,它通过了所有单元测试,但我将在发出拉取请求之前尝试找到一个更优雅的解决方案。
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-adapter
gem. 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不确定这正是答案,但我修补了本地代码,您的查询现在对我有用。
首先,github问题:
https://github.com/rails/rails/issues/1623
然后是 arkadiyk 修复的拉取请求:
https://github.com/arkadiyk/rails/commit/7e2ddddb303d17adc825ebb691097a93902fa539
基本问题是finder_methods.rb,它在第187或188行附近有现有代码:
MSSQL barfs on the unnamed columns这会生成,因此以下代码修复它:
希望有帮助。
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.
修复此问题似乎有两种选择:在 Rails 中修复它,或在 activerecord-sqlserver-adapter 中修复它。
Raels 提供的链接可能是解决此问题的正确方法,但是,拉取请求尚未被接受到 Rails 中。我担心使用修补版本的 Rails,因为这将迫使我要么坚持使用修补版本,要么随着 Rails 的发展继续修补。
另一种选择是在 activerecord-sqlserver-adapter 中修复此问题。我在这里提交了拉取请求:
https://github.com/ Rails-sqlserver/activerecord-sqlserver-adapter/pull/171
active-sqlserver-adapter 的维护者可能会提出更优雅的修复方案。如果他这样做,我会更新这个答案。
There seem to be two alternatives to fixing this: fix it in rails, or fix it in activerecord-sqlserver-adapter.
The link that Raels has provided is probably the right way to fix this, however, the pull request has not been accepted into rails. I'm concerned about using a patched version of rails, as this will force me to either stick with my patched version, or continue to patch as rails evolves.
Al alternative is to fix this in activerecord-sqlserver-adapter. I've submitted a pull request here:
https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/171
It's possible that the maintainer of active-sqlserver-adapter will come up with a more elegant fix. If he does, I'll update this answer.