转储文件中视图预定义的目的是什么

What is the purpose of views' predefinitions in dump file

我正在处理我们使用 :sql schema format Active Record 转储程序的项目(以支持更复杂的逻辑,如触发器)。

我们有很多视图,我可以在 database/structure.sql 文件中看到其中一些具有 "predefined" 架构,其中 NULL 如下:

CREATE VIEW public.my_view AS
  SELECT
    NULL::integer AS record_id,
    NULL::integer AS another_record_id,
    NULL::double precision AS some_field;

然后,数千行之后,定义中添加:

CREATE OR REPLACE VIEW public.my_view AS
  -- actual query

我在 SQL 查询中看不到架构 "predefinition" 和定义之间对视图的任何引用。此外,还有其他立即创建的视图(没有该架构 "predefinition")。

我正在查看 Active Record 文档,但找不到任何提示。 Rails 在幕后使用 pg_dump 但我在 pg_dump 文档中也没有看到任何相关内容。

为什么有些视图需要提前预定义模式,而有些则不需要,即使其中 none 在 database/structure.sql 文件中的预定义和实际定义之间被引用?是为了防止在使用另一种结构(如物化视图等)时出现某些竞争条件吗?

这是因为视图可以有这样的循环依赖:

CREATE SCHEMA s;
CREATE OR REPLACE VIEW s.v AS SELECT 1 a;
CREATE OR REPLACE VIEW s.w AS SELECT a FROM s.v;
CREATE OR REPLACE VIEW s.v AS SELECT a FROM s.w;

无法在此表单中查询这些视图。例如。 select * from s.w 产生:

SQL Error [42P17]: ERROR: infinite recursion detected in rules for relation "w"

但是运行下面的pg_dump命令:

pg_dump -U postgres -d postgres -s -n s

产生这个输出:

CREATE SCHEMA s;

CREATE VIEW s.v AS
SELECT
    NULL::integer AS a;

CREATE VIEW s.w AS
 SELECT v.a
   FROM s.v;

CREATE OR REPLACE VIEW s.v AS
 SELECT w.a
   FROM s.w;

如您所见,必须创建虚拟视图,因为 s.v 在创建时无法访问 not-yet 现有的 s.w

您还可以在 pg_dump.c's createDummyViewAsClause function 中找到此逻辑,其文档如下:

/*
 * Create a dummy AS clause for a view.  This is used when the real view
 * definition has to be postponed because of circular dependencies.
 * We must duplicate the view's external properties -- column names and types
 * (including collation) -- so that it works for subsequent references. [...]
 */