Ruby on rails ActiveRecord::语句无效:PG InFailedSqlTransaction
我正在尝试创建一个ActiveRecord对象,但在创建它时出现了此错误Ruby on rails ActiveRecord::语句无效:PG InFailedSqlTransaction,ruby-on-rails,postgresql,activerecord,rollback,pg,Ruby On Rails,Postgresql,Activerecord,Rollback,Pg,我正在尝试创建一个ActiveRecord对象,但在创建它时出现了此错误 (0.1ms) ROLLBACK ActiveRecord::StatementInvalid: PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block 大家对这个问题有什么看法。我有这个问题。只要重新启动Rails服务器,它就应该可
(0.1ms) ROLLBACK
ActiveRecord::StatementInvalid: PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block
大家对这个问题有什么看法。我有这个问题。只要重新启动Rails服务器,它就应该可以工作了这个问题发生在我的测试环境中,是因为每个测试都被包装在自己的事务中 我使用的是数据库_cleanergem,并对其进行了配置,以便在使用javascript时不会将测试包装到事务中。所以为了解决这个问题,我在每个导致这个问题的规范中添加了
js:true
。(尽管规范实际上没有使用javascript,但这是确保测试不会被封装在事务中的最方便的方法。不过,我相信有更少的黑客方法可以做到这一点)
以下是spec/support/database\u cleaner.rb
中的数据库\u cleaner配置,仅供参考:
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with :deletion
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, :js => true) do
DatabaseCleaner.strategy = :deletion
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
如果您没有使用database_cleaner,那么将测试包装在事务中的原因可能是
use_transactional_fixtures
选项在spec/spec\u helper.rb
中设置为true
。尝试将其设置为false。你可以在postgresql日志中看到真正发生的情况,我花了很多时间深入研究这个问题,最终发现我们误用upsert gem导致PG错误,只有在postgresql日志中才有真正的信息
我在引用规范中不再存在的列时遇到此错误。确保您的数据库是最新的,并且您的代码不希望出现不存在的列。其他答案都无法解决问题的根本原因 问题是,当Postgres引发异常时,它会毒害同一连接上的未来事务 解决方法是回滚有问题的事务:
begin
ActiveRecord...do something...
rescue Exception => e
puts "SQL error in #{ __method__ }"
ActiveRecord::Base.connection.execute 'ROLLBACK'
raise e
end
请参阅。在将Rails从4.2.2升级到4.2.5后出现类似问题,我必须升级
pg
gem,问题开始出现
9) WorkPolicy#is_publicly_viewable? is publicly visible hides work if deleted
Failure/Error: before { DatabaseCleaner.clean_with :deletion }
ActiveRecord::StatementInvalid:
PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block
: SELECT tablename
FROM pg_tables
WHERE schemaname = ANY (current_schemas(false))
从这个意义上讲,这是正确的,只是总结一下问题:
有时,当您将DatabaseCleaner.clean_与:deletion一起使用时,可能会干扰PostgreSQL事务
因此,我的解决方案是在部分测试中将DatabaseCleaner.clean_替换为:deletion
,而这是由DatabaseCleaner.clean_导致的,使用:truncation
对谷歌用户来说,还有一件事。如果您注意到此堆栈跟踪:
An error occurred in an `after(:context)` hook.
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "table_rows" does not exist
LINE 1: ...ion_schema.tables WHERE table_schema = 'test' AND table_rows...
^
…这可能是由此问题引起的问题:
程序执行错误的SQL语句。错误的SQL语句是问题的根本原因
在错误的SQL语句之后,程序不会立即回滚或释放保存点
程序在错误的SQL语句之后执行SQL语句
PostgreSQL引发错误:当前事务被中止,在事务块结束之前忽略命令
解决方案:
查找不正确的SQL语句并更正它。
如果不想更正SQL语句,请在不正确的SQL语句后使用回滚或释放保存点。在我的例子中,我收到此错误只是因为我没有rake我的测试数据库 在我的例子中,位于/usr/local/var/Postgres/postgresql.conf
的Postgres配置的日期类型是国际格式的dmy
将日期类型更改为美国格式的mdy
为我解决了这个问题。我遇到了这个问题。
我发现这是我的疑问。
这意味着当我在不指定表列的情况下使用关联进行查询时。
例:
如果您禁用事务性装置而不插入DatabaseCleaner之类的东西,那么您的测试数据库将继续累积每次运行的数据。您可以为集成规范设置它,而不是为每个不按预期工作的规范设置js:true
。请记住,使用:deletation
而不是:transaction
的速度要慢得多,因此在可行的情况下,最好使用事务。在这一点上,我发现与默认事务测试相比,DB Cleaner增加的复杂性非常困难(也就是出现更多错误)。但我的问题是,在同一个it
块中有两个请求,如get…
。将其移出修复了此错误。我不认为添加js:true
是修复此问题的最佳方法。它不能解决问题,而且删除策略非常缓慢。通过切换到事务策略,我将测试速度提高了2.5倍。请看下面我的答案。事实上,我刚刚遇到了这个问题,重新启动服务器确实解决了它。有人对这种行为有解释吗?我在测试环境中也有同样的问题(rspec抛出错误)rakedb:drop
+rakedb:create
+rakedb:migrate
解决了这个问题。也许我把迁移搞砸了。我在rails控制台中测试。重新加载不足,需要重新启动控制台。谢谢这不是一个可行的解决方案,当服务应该自动运行时,重新启动服务器不是一个选项。问题是PG连接处于错误状态,需要重新连接,或者需要执行回滚
以退出当前事务。这在升级到PG12和Ruby 2.6.6后发生。我使用rvm,升级到2.6.6需要为新的gemset重建pg gem。一个rakedb:test:prepare
不起作用,但是一个rakedb:drop db:create db:migrate
解决了这个问题。这个链接没有什么帮助,但是检查postgres日志的想法完全起作用了。在我的例子中,它是一个未准备好的测试数据库。谢谢Rails中也提到了请不要从异常中解救,正如这里所说的:异常是Ruby异常层次结构的根,所以当你解救异常时,你会从一切中解救出来,包括子类,如SyntaxError、LoadError和Int
class Holiday < ApplicationRecord
belongs_to :company
end
class Company < ApplicationRecord
has_many :timeoffs
end
company.timeoffs.where("(start_date <= ? and end_date >= ?) and id != ?", begin_date, begin_date, 1)
company.timeoffs.where("(start_date <= ? and end_date >= ?) and time_offs.id != ?", begin_date, begin_date, 1)