Rails 3.1,Ruby 1.9.2,通過activerecord-sqlserver-adapter gem使用SQL Server 2008數據庫。我正在使用遺留數據庫,所以這不是自願的。在ActiveAdmin查詢期間缺少列名稱
我遇到了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
寶石。但是,我拉取了源代碼,並且確實看起來沒有任何東西會以這種方式組裝這個查詢。
有沒有人碰到過類似的東西?這可能是我只需要在整個堆棧中調試我的方式以查看發生了什麼。首先,儘管它首先在這裏檢查。
編輯:我現在很確定這是activerecord-sqlserver-adapter中的一個錯誤。一旦擁有了,我會在這裏發佈解決方案。
Edit2:可以在沒有ActiveAdmin的情況下重現錯誤。這與sql server適配器處理偏移量查詢的方式有關。調用
MyModel.offset(1).exists?
產生相同的錯誤。我對通過所有單元測試的適配器有一個醜陋的補丁,但我會在提出請求之前嘗試找到更優雅的解決方案。
謝謝。對於解決這個問題的恰當地點,我感慨萬分。很顯然,rails可以通過別名選擇1的列來使我們的生活更輕鬆,但是我想不應該這樣做,因爲這更像是數據庫特有的問題。我在activerecord-sqlserver-adapter上有一個修補程序,可以完成同樣的事情,但以更加醜陋的方式執行(基本上在選擇處理期間訪問節點,並在節點僅爲「1」時追加別名列)。我會發佈一個答案以及鏈接回我的拉請求。 – 2012-03-08 14:00:52
同意。我還可以看到一個通用適配器功能,它可以生成臨時列名稱,然後從查詢和處理結束時的結果集中清除它們。這將允許適配器管理它引入的列,以及可能允許用戶爲列名指定不同的生成器。只是一個想法。我沒有仔細查看代碼,看看什麼是最合理的。 – Raels 2012-03-23 13:48:30