postgresql 错误:扩展“btree_gist”必须安装在模式“heroku_ext”中

ecr0jaav  于 2022-11-04  发布在  PostgreSQL
关注(0)|答案(8)|浏览(334)

Heroku更改了postgressql扩展的安装方式
这是搞砸了新的轨道审查应用程序在heroku与以下错误。
错误:扩展“btree_gist”必须安装在模式“heroku_ext”中
这会把事情搞砸,因为我需要删除现有的扩展并重新启用heroku_ext模式。我使用bin/rails db:structure:load,这是在运行迁移之前。
此外,structure.sql也会出现分歧,因为heroku在review应用程序中添加了架构,我们需要在本地dev机器中手动运行创建。
有人遇到过这个问题吗?

oprakyz7

oprakyz71#

我已经开发了一个monkey-patch解决方案,这绝对是一个黑客,但比提前迁移或从schema. rb中删除行要好。
把这个放进config/initializers,我把我的叫做_enable_extension_hack.rb,以确保它早点加载。

module EnableExtensionHerokuMonkeypatch
  # Earl was here
  def self.apply_patch!
    adapter_const = begin
      Kernel.const_get('ActiveRecord::ConnectionAdapters::PostgreSQLAdapter')
    rescue NameError => ne
      puts "#{self.name} -- #{ne}"
    end

    if adapter_const
      patched_method = adapter_const.instance_method(:enable_extension)

      # Only patch this method if it's method signature matches what we're expecting
      if 1 == patched_method&.arity
        adapter_const.prepend InstanceMethods
      end
    end
  end

  module InstanceMethods
    def enable_extension(name)
      name_override = name

      if schema_exists?('heroku_ext')
        puts "enable_extension -- Adding SCHEMA heroku_ext"
        name_override = "#{name}\" SCHEMA heroku_ext -- Ignore trailing double quote"
      end

      super name_override
    end
  end
end

EnableExtensionHerokuMonkeypatch.apply_patch!

它的作用是什么?它对db/schema.rb中导致问题的enable_extension调用进行monkey-patch。具体来说,如果它发现有一个名为"heroku_ext"的模式,它将 * 修饰 * 给enable_extension的参数,以便执行的SQL指定"heroku_ext"模式。如下所示:

CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" SCHEMA heroku_ext -- Ignore trailing double quote"

如果不使用此技巧,生成的SQL将如下所示:

CREATE EXTENSION IF NOT EXISTS "pg_stat_statements"
bxpogfeg

bxpogfeg2#

这是更干净的修补schema.rb的方法


# config/initializers/patch_enable_extension.rb

require 'active_record/connection_adapters/postgresql_adapter'

# NOTE: patch for https://devcenter.heroku.com/changelog-items/2446

module EnableExtensionHerokuPatch
  def enable_extension(name,**)
    return super unless schema_exists?("heroku_ext")

    exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\" SCHEMA heroku_ext").tap { reload_type_map }
  end
end

module ActiveRecord
  module ConnectionAdapters
    class PostgreSQLAdapter
      prepend EnableExtensionHerokuPatch
    end
  end
end
3pvhb19x

3pvhb19x3#

编辑:这是官方的修改日志,作为参考https://devcenter.heroku.com/changelog-items/2446
你需要做一些不可思议的事情,因为最近的Heroku更改和修改过去的迁移文件,让你的评论应用程序与新的Heroku系统一起工作。
1.在第一个迁移文件connection.execute 'CREATE SCHEMA IF NOT EXISTS heroku_ext'的顶部添加一个日期早于或
1.还可以向database.yml添加一个包含heroku_ext的schema_search_path(或者,如果尚未自定义,则将其设置为public,heroku_ext

  1. Grep所有enable_extension('extension_name')
    1.将它们全部替换为connection.execute('CREATE EXTENSION IF NOT EXISTS "extension_name" WITH SCHEMA "heroku_ext"
    1.祈祷这足以解决问题
    在进行这些更改后,我们仍然必须联系heroku支持,因为,为了:
  • 一个pgaudit stack is not empty错误
  • 这里的修复是运行两次维护(因为计划维护的postgres插件早于架构/扩展更改)
  • 一个ERROR: function pg_stat_statements_reset(oid, oid, bigint) does not exist错误
  • 这里的修复是heroku对数据库的手动干预。这是由于heroku试图在每次创建模式时运行pg_stat_statements_reset造成的。
dba5bblo

dba5bblo4#

下面的脚本在app.json的postdeploy步骤中运行。


# !/bin/bash -xue

# Create extensions in the schema where Heroku requires them to be created

# The plpgsql extension has already been created before this script is run

heroku pg:psql -a $HEROKU_APP_NAME -c 'create extension if not exists citext schema heroku_ext'
heroku pg:psql -a $HEROKU_APP_NAME -c 'create extension if not exists pg_stat_statements schema heroku_ext'

# Remove enable_extension statements from schema.rb before loading it, since

# even 'create extension if not exists' fails when the schema is not heroku_ext

mv db/schema.rb{,.orig}
grep -v enable_extension db/schema.rb.orig > db/schema.rb
rails db:schema:load
gj3fmq9x

gj3fmq9x5#

截至2022年8月16日星期二,我们发现似乎不再需要补丁,enable_extension似乎可以正常无缝工作,而无需显式指定模式。
当我在Heroku Support的持续讨论中提到这一点时,他们说他们在解决https://status.heroku.com/incidents/2450时可能已经发布了一些关于heroku_ext更改的修复程序,但仍有更多的修复程序在开发中,尚未发布-所以我猜这个特定的问题是那些已经修复的问题之一!

x6h2sr28

x6h2sr286#

dzirtusss提供的答案让我大部分时间都在那里,为了让我的Rails应用程序工作,我必须做的最后一件事是编辑config/database.yml中的搜索路径,以包括heroku_ext。这是我附加到默认配置中的内容。


# config/database.yml

default:
  schema_search_path: public,heroku_ext

在添加初始化脚本和database.yml编辑之后,我能够成功地从一个应用程序向另一个应用程序运行heroku pg:copy,没有错误,也没有意外行为。

kiz8lqtg

kiz8lqtg7#

Heroku最近引入了一个--extensions标志,这有助于解决问题。请参阅FAQ
例如,如果您正在使用btree_gist扩展,则可以在运行迁移之前使用heroku run pg:reset --extensions 'btree_gist' --app YOUR_APP_NAME,这样它们就可以在不更改代码库的情况下运行。

sulc1iza

sulc1iza8#

1.使用Heroku数据存储持久性工具在源数据库或heroku pg:backups:capture -a <SOURCE_APP>上创建备份。
1.确定数据库使用哪些pg扩展名(可以使用\dx从psql检查)
1.创建一个以逗号分隔的扩展名字符串(例如:(单位:fuzzystrmatch,pg_stat_statements,pg_trgm,pgcrypto,plpgsql,unaccent,uuid-ossp'
1.确保您的Heroku CLI至少更新到7.63.0版(使用heroku update进行更新)
1.运行此命令:

heroku pg:backups:restore $(heroku pg:backups public-url -a <SOURCE_APP>) DATABASE_URL --extensions '<EXTENSIONS>' -a <TARGET_APP>

1.重置TARGET_APP上的动态

相关问题