在Rails与SQL Server Adapter中正确使用limit()关联子查询的问题
实际表现
limit()方法并未添加到生成的子查询(实际为Model::ActiveRecord_Relation)中,反而会触发执行并抛出错误:
ActiveRecord::StatementInvalid Exception: 表不存在
代码及复现步骤
class Doc < ApplicationRecord self.table_name = "D_docs" has_many :doc_dirs has_many :dirs, through: :doc_dirs default_scope -> { where(inactive: false, is_version_1: true)} scope :doc_collection, -> do str_sql = " ( SELECT [D_docs].[fileType], [D_docs].[inactive], [D_docs].[isVisible] FROM [D_docs] ) [D_docs] " doc_collec = Doc.from(str_sql).limit(10) # byebug doc_collec end end
在Rails控制台中,在doc_collec = Doc.from(str_sql).limit(10)和doc_collec之间添加调试,执行doc_collec.to_sql会得到:
ActiveRecord::StatementInvalid Exception: 表 '( SELECT [D_docs].[fileType], [D_docs].[inactive], [D_docs].[isVisible] FROM [D_docs] ) [D_docs]' 不存在
需要注意的是,Doc.from(str_sql).to_sql会生成:SELECT [D_docs].* FROM ( SELECT [D_docs].[fileType], [D_docs].[inactive], [D_docs].[isVisible] FROM [D_docs] ) [D_docs]
在旧版Rails(6.1.7)及SQL Server Adapter 6.x.x中,Doc.from(str_sql).limit(10)可正常工作,生成的正确查询语句为:
SELECT [D_docs].* FROM ( SELECT [D_docs].[fileType], [D_docs].[inactive], [D_docs].[isVisible] FROM [D_docs] ) [D_docs] OFFSET 0 FETCH NEXT 10 ROWS ONLY
另外,Doc.from(str_sql).order(:pkid)可正常执行。
版本信息:
- Rails版本:
7.1.2 - SQL Server Adapter版本:
7.1.0 - TinyTDS版本:
2.1.5
更新
感谢@engineersmnky的帮助,将doc_collec = Doc.from(str_sql).limit(10)修改为:
doc_collec = Doc.from(Arel::Nodes::TableAlias.new(Arel::Nodes::TableAlias.new(Doc.select(:fileType,:inactive,:isVisible).arel, self.table_name))).limit(10)
现在生成的查询语句为:
SELECT [D_docs].* FROM (SELECT [D_docs].[fileType], [D_docs].[inactive], [D_docs].[isVisible] FROM [D_docs]) [D_docs] ORDER BY [D_docs].[docName] ORDER BY [D_docs][pkid] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY
该语句可正常执行(需调整查询);但我希望能移除自动添加的ORDER BY [D_docs].[pkid],因为后续计划添加UNION查询,请问如何实现?
内容的提问来源于stack exchange,提问作者Adrián

