PG::UndefinedObject: ERROR: operator class “pgroonga_text_term_search_ops“ does not exist for acces

PG::UndefinedObject: ERROR: operator class "pgroonga_text_term_search_ops" does not exist for access method "pgroonga"

前言

筆者的環境如下:

  • Ubuntu 20.04
  • ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
  • Rails 5.2.4.2
  • Redmine 4.1.1
  • 為Redmine安裝了full_text_search插件

這是筆者在redmine根目錄裡執行:

RAILS_ENV=production rake db:reset DISABLE_DATABASE_ENVIRONMENT_CHECK=1 --trace

時所出現的錯。

錯誤訊息

錯誤訊息如下(重點已用螢光標註):

Caused by:
PG::UndefinedObject: ERROR: operator class “pgroonga_text_term_search_ops” does not exist for access method “pgroonga”
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:75:in async_exec' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:75:inblock (2 levels) in execute’
/usr/share/rvm/gems/ruby-2.7.0/gems/activesupport-5.2.4.2/lib/active_support/dependencies/interlock.rb:48:in block in permit_concurrent_loads' /usr/share/rvm/gems/ruby-2.7.0/gems/activesupport-5.2.4.2/lib/active_support/concurrency/share_lock.rb:187:inyield_shares’
/usr/share/rvm/gems/ruby-2.7.0/gems/activesupport-5.2.4.2/lib/active_support/dependencies/interlock.rb:47:in permit_concurrent_loads' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:74:inblock in execute’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/abstract_adapter.rb:581:in block (2 levels) in log' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/abstract_adapter.rb:580:insynchronize’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/abstract_adapter.rb:580:in block in log' /usr/share/rvm/gems/ruby-2.7.0/gems/activesupport-5.2.4.2/lib/active_support/notifications/instrumenter.rb:23:ininstrument’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/abstract_adapter.rb:571:in log' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:73:inexecute’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/postgresql/schema_statements.rb:466:in add_index' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/abstract/schema_statements.rb:315:inblock in create_table’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/abstract/schema_statements.rb:314:in each' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/connection_adapters/abstract/schema_statements.rb:314:increate_table’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/migration.rb:871:in block in method_missing' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/migration.rb:840:inblock in say_with_time’
/usr/share/rvm/rubies/ruby-2.7.0/lib/ruby/2.7.0/benchmark.rb:293:in measure' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/migration.rb:840:insay_with_time’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/migration.rb:860:in method_missing' /home/redmine/redmine/db/schema.rb:405:inblock in <top (required)>’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/schema.rb:50:in instance_eval' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/schema.rb:50:indefine’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/schema.rb:46:in define' /home/redmine/redmine/db/schema.rb:13:in<top (required)>’
/usr/share/rvm/gems/ruby-2.7.0/gems/activesupport-5.2.4.2/lib/active_support/dependencies.rb:285:in load' /usr/share/rvm/gems/ruby-2.7.0/gems/activesupport-5.2.4.2/lib/active_support/dependencies.rb:285:inblock in load’
/usr/share/rvm/gems/ruby-2.7.0/gems/activesupport-5.2.4.2/lib/active_support/dependencies.rb:257:in load_dependency' /usr/share/rvm/gems/ruby-2.7.0/gems/activesupport-5.2.4.2/lib/active_support/dependencies.rb:285:inload’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/tasks/database_tasks.rb:245:in load_schema' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/tasks/database_tasks.rb:266:inblock in load_schema_current’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/tasks/database_tasks.rb:316:in block in each_current_configuration' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/tasks/database_tasks.rb:313:ineach’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/tasks/database_tasks.rb:313:in each_current_configuration' /usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/tasks/database_tasks.rb:265:inload_schema_current’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/railties/databases.rake:258:in block (3 levels) in <top (required)>' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:281:inblock in execute’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:281:in each' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:281:inexecute’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:219:in block in invoke_with_call_chain' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:199:insynchronize’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:199:in invoke_with_call_chain' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:188:ininvoke’
/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-5.2.4.2/lib/active_record/railties/databases.rake:262:in block (3 levels) in <top (required)>' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:281:inblock in execute’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:281:in each' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:281:inexecute’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:219:in block in invoke_with_call_chain' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:199:insynchronize’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:199:in invoke_with_call_chain' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:243:inblock in invoke_prerequisites’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:241:in each' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:241:ininvoke_prerequisites’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:218:in block in invoke_with_call_chain' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:199:insynchronize’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:199:in invoke_with_call_chain' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:243:inblock in invoke_prerequisites’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:241:in each' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:241:ininvoke_prerequisites’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:218:in block in invoke_with_call_chain' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:199:insynchronize’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:199:in invoke_with_call_chain' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/task.rb:188:ininvoke’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/application.rb:160:in invoke_task' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/application.rb:116:inblock (2 levels) in top_level’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/application.rb:116:in each' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/application.rb:116:inblock in top_level’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/application.rb:125:in run_with_threads' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/application.rb:110:intop_level’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/application.rb:83:in block in run' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/application.rb:186:instandard_exception_handling’
/usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/lib/rake/application.rb:80:in run' /usr/share/rvm/gems/ruby-2.7.0/gems/rake-13.0.3/exe/rake:27:in<top (required)>’
/usr/share/rvm/gems/ruby-2.7.0/bin/rake:23:in load' /usr/share/rvm/gems/ruby-2.7.0/bin/rake:23:in<main>’
/usr/share/rvm/gems/ruby-2.7.0/bin/ruby_executable_hooks:24:in eval' /usr/share/rvm/gems/ruby-2.7.0/bin/ruby_executable_hooks:24:in<main>’
Tasks: TOP => db:schema:load

從錯誤訊息的第一行可以看出是跟pgroonga_text_term_search_ops有關。在<redmine_home>裡尋找線索:

grep pgroonga_text_term_search_ops -rn .

./db/schema.rb:410: t.index [“source”, “destination”], name: “fts_query_expansions_index_pgroonga”, opclass: :pgroonga_text_term_search_ops, using: :pgroonga
./plugins/full_text_search/db/migrate/20190807085000_create_fts_query_expansions.rb:24: “source pgroonga_text_term_search_ops_v2”,
./plugins/full_text_search/db/migrate/20190807085000_create_fts_query_expansions.rb:25: “destination pgroonga_text_term_search_ops_v2”,

可以看到,在plugins/full_text_search/db/migrate/20190807085000_create_fts_query_expansions.rb裡,operator class的名字是叫pgroonga_text_term_search_ops_v2,但是在db/schema.rb裡面,卻把它的名字誤植為pgroonga_text_term_search_ops

解決方式

一個權宜之計是手動編輯db/schema.rb,把裡面的pgroonga_text_term_search_ops加上_v2即可。

改完之後就能成功執行db:reset的指令了!

發生原因

rails的Github上有人提了issue並提出了他的解決方式:

首先要找到redmine所用的rails版本,筆者的是5.2.4.2,這點可以從上面的錯誤訊息中看出來。

然後修改:/usr/share/rvm/gems/ruby-2.7.0/gems/activerecord-<rails_version>/lib/active_record/connection_adapters/postgresql/schema_statements.rb這個檔案:

把:

expressions.scan(/(?<column>\w+)"?\s?(?<opclass>\w+_ops)?\s?(?<desc>DESC)?\s?(?<nulls>NULLS (?:FIRST|LAST))?/).each do |column, opclass, desc, nulls|

改成:

expressions.scan(/(?<column>\w+)"?\s?(?<opclass>\w+_ops(_\w+)?)?\s?(?<desc>DESC)?\s?(?<nulls>NULLS (?:FIRST|LAST))?/).each do |column, opclass, desc, nulls|

這樣rails在生成db/schema.rb時才能找到正確的operator class名稱。看起來這才是治本的方法。

參考連結

Rails 5 how to clear or delete production postgres database

AR PG opclass schema dumper regex extracts wrong opclass when opclass does not end with _ops

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值