我有以下迁移。
execute <<-SQL
CREATE TABLE test_table(
name char(20)
);
INSERT INTO test_table(name) values ('test name');
CREATE MATERIALIZED VIEW test AS
SELECT * from test_table
WITH DATA;
SQL
请注意,我添加了 "WITH DATA".这并没有填充数据(因为当我试图对视图进行并发刷新时,我得到了 "materialized view has not been populated "的错误信息),并在 "WITH NO DATA "中添加了 "WITH NO DATA"。structure.sql
:
CREATE MATERIALIZED VIEW public.test AS
SELECT test_table.name
FROM public.test_table
WITH NO DATA;
我做错了什么?Postgres关于实体化视图的文档说 在发出命令时,执行查询并用于填充视图(除非使用WITH NO DATA)。 所以即使没有指定 "WITH DATA",它也应该默认生成 "WITH DATA",但我得到的却是 "WITH NO DATA"。
我的问题似乎类似于 ActiveRecord迁移不填充Postgres物质化视图。
编辑我了解到,其实数据是在开发环境下填充的(虽然它设置了 WITH NO DATA
在 structure.sql
). 问题出在测试环境中,有时不会填充数据。还在调查原因... 但是... structure.sql
不幸的是,绝对不正确。
我希望这不是十八个月后才有用,但这是我解决这个问题的方法。
假设你正在使用(强烈推荐!)的 scenic
gem。
假设你的物化视图支持的模型是这样的。我已经修改了 refresh
方法稍作 concurrently
作为一个参数。
class Foo < ApplicationRecord
# if you're using the excellent "scenic" gem
def self.refresh(concurrently:)
Scenic.database.refresh_materialized_view(table_name, concurrently: concurrently, cascade: false)
end
# if you're not using the excellent "scenic" gem (why not?)
# have not tested this but should work
def self.refresh(concurrently:)
concurrently_string = concurrently ? "CONCURRENTLY" : ""
ActiveRecord::Base.connection.execute(
"REFRESH MATERIALIZED VIEW #{table_name} #{concurrently_string} WITH DATA"
)
end
private
def readonly?
true
end
end
然后,在 spec/rails_helper.rb
,只需为您的每一个物化视图支持的模型做这个工作。
config.before(:suite) do
Foo.refresh(concurrently: false)
Bar.refresh(concurrently: false)
# etc.
end
请注意,在您的个别测试中,您仍然可能需要调用 #refresh
在某些情况下,如果你想让它们反映出你已经插入到底层表中的数据,则需要手动操作。