我要进行以下迁移:
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”。
这不会填充数据(当我尝试在视图上进行并发刷新时,由于出现“未填充实体化视图”错误),因此在structure.sql
中添加了“ WITH NO DATA”:
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 migration not populating a Postgres materialized view
编辑
我了解到数据实际上是在开发环境中填充的(尽管它在WITH NO DATA
中设置了structure.sql
)。问题出在测试环境中,有时它不会填充数据。仍在调查原因...但是不幸的是,structure.sql
绝对是不正确的。
答案 0 :(得分:1)
我希望现在还不晚18个月才有用,但这是我解决此问题的方法。
假设您正在使用(强烈推荐!)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
。