【PostgreSQL内核学习(二十四) —— (ALTER MATERIALIZED VIEW)】

ALTER MATERIALIZED VIEW

  • 概述
  • 源码解析
    • 修改物化视图的属性和行为
      • AlterTableStmt 结构体
      • AlterTableMoveAllStmt 结构体
    • 重命名
      • RenameStmt 结构体
    • 设置对象依赖于扩展
      • AlterObjectDependsStmt 结构体
  • 测试用例

声明:本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果,力求遵循合理使用原则,并在适用的情况下注明引用来源。
本文主要参考了 postgresql-10.1 的开源代码和《OpenGauss数据库源码解析》和《PostgresSQL数据库内核分析》一书以及一些相关资料。

概述

  ALTER MATERIALIZED VIEW 是一个 SQL 命令,用于修改一个已经存在的物化视图(Materialized View)的定义或行为。物化视图是一种特殊的数据库对象,它存储了查询结果的实际数据,与普通视图(仅保存查询逻辑)不同。这使得物化视图在处理复杂查询和提高数据检索效率方面非常有用,特别是在涉及大量数据和复杂联结的情况下。
  使用 ALTER MATERIALIZED VIEW 命令,您可以进行各种修改,比如重命名物化视图更改其底层查询逻辑更新或刷新其中的数据更改存储参数或者修改与物化视图相关的安全和访问规则。这个命令提供了灵活性来维护和优化物化视图,确保它们保持最新并有效地服务于数据库应用程序的需求。
  在 PostgreSQL 数据库中,ALTER MATERIALIZED VIEW 命令的完整语法格式相对灵活,提供了多种选项来修改物化视图的定义和行为。以下是该命令的一般语法结构:

ALTER MATERIALIZED VIEW [ IF EXISTS ] name
    action [, ... ]

其中 action 可以是以下之一:

    ALTER COLUMN column_name SET DATA TYPE data_type [ COLLATE collation ] [ USING expression ]
    ALTER COLUMN column_name SET DEFAULT expression
    ALTER COLUMN column_name DROP DEFAULT
    ALTER COLUMN column_name { SET | DROP } NOT NULL
    ALTER COLUMN column_name SET STATISTICS integer
    ALTER COLUMN column_name SET ( attribute_option = value [, ... ] )
    ALTER COLUMN column_name RESET ( attribute_option [, ... ] )
    CLUSTER ON index_name
    SET WITHOUT CLUSTER
    SET TABLESPACE tablespace_name
    SET ( storage_parameter [= value] [, ... ] )
    RESET ( storage_parameter [, ... ] )
    OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
    RENAME TO new_name
    RENAME COLUMN column_name TO new_column_name
    ADD { COLUMN | table_constraint_using_index } [ IF NOT EXISTS ]
    DROP [ COLUMN ] column_name [ IF EXISTS ] { RESTRICT | CASCADE }
    ENABLE TRIGGER [ ALL | trigger_name ]
    DISABLE TRIGGER [ ALL | trigger_name ]
    ENABLE REPLICA TRIGGER trigger_name
    ENABLE ALWAYS TRIGGER trigger_name
    DISABLE RULE rewrite_rule_name
    ENABLE RULE rewrite_rule_name
    ENABLE REPLICA RULE rewrite_rule_name
    ENABLE ALWAYS RULE rewrite_rule_name
    REFRESH MATERIALIZED VIEW [ CONCURRENTLY ] [ WITH [ NO ] DATA ]

  这个命令允许对物化视图执行多种操作,例如更改列的数据类型设置或删除默认值添加或删除列修改物化视图的存储参数更改所有者重命名视图或列,以及刷新视图中的数据
  特别要注意的是 REFRESH MATERIALIZED VIEW 选项,它用于更新物化视图中的数据以反映底层数据的任何更改。可选的 CONCURRENTLY 关键字允许在刷新物化视图时仍然允许对其进行读取,虽然这会增加一些性能开销。
  使用这些选项时,应该根据物化视图的具体用途和数据库的性能要求来选择合适的操作。

源码解析

修改物化视图的属性和行为

  以下是 gram.y 文件中的一段代码,是用于数据库管理的,具体来说是用于修改数据库视图(Views)和物化视图(Materialized Views)的 SQL 语句的解析部分。这段代码看起来是用 C 语言写的,特别是用于 PostgreSQL 或类似的关系型数据库系统。每一部分都定义了特定的 SQL 语句如何被解析和转换为内部的数据结构。其源码如下所示:(路径:src\backend\parser\gram.y

|	ALTER MATERIALIZED VIEW qualified_name alter_table_cmds
		{
			AlterTableStmt *n = makeNode(AlterTableStmt);
			n->relation = $4;
			n->cmds = $5;
			n->relkind = OBJECT_MATVIEW;
			n->missing_ok = false;
			$$ = (Node *)n;
		}
|	ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name alter_table_cmds
		{
			AlterTableStmt *n = makeNode(AlterTableStmt);
			n->relation = $6;
			n->cmds = $7;
			n->relkind = OBJECT_MATVIEW;
			n->missing_ok = true;
			$$ = (Node *)n;
		}
|	ALTER MATERIALIZED VIEW ALL IN_P TABLESPACE name SET TABLESPACE name opt_nowait
		{
			AlterTableMoveAllStmt *n =
				makeNode(AlterTableMoveAllStmt);
			n->orig_tablespacename = $7;
			n->objtype = OBJECT_MATVIEW;
			n->roles = NIL;
			n->new_tablespacename = $10;
			n->nowait = $11;
			$$ = (Node *)n;
		}
|	ALTER MATERIALIZED VIEW ALL IN_P TABLESPACE name OWNED BY role_list SET TABLESPACE name opt_nowait
		{
			AlterTableMoveAllStmt *n =
				makeNode(AlterTableMoveAllStmt);
			n->orig_tablespacename = $7;
			n->objtype = OBJECT_MATVIEW;
			n->roles = $10;
			n->new_tablespacename = $13;
			n->nowait = $14;
			$$ = (Node *)n;
		}

  下面是对每一部分的解释:

语法 解释
ALTER MATERIALIZED VIEW qualified_name alter_table_cmds 这部分针对的是物化视图。物化视图与普通视图不同,它会将数据实际存储在物理存储上。这里的 OBJECT_MATVIEW 表示这是一个物化视图对象。
ALTER MATERIALIZED VIEW IF EXISTS qualified_name 这部分是上一条的变种,用于 ALTER MATERIALIZED VIEW IF EXISTS 语句。它在指定的物化视图存在时进行修改,不存在时不会产生错误。
ALTER MATERIALIZED VIEW ALL IN TABLESPACE name SET TABLESPACE name opt_nowait 这条语句用于将所有物化视图从一个表空间移动到另一个表空间。orig_tablespacenamenew_tablespacename 分别存储原始和新的表空间名称。nowait选项指示在移动时是否需要等待。
ALTER MATERIALIZED VIEW ALL IN TABLESPACE name OWNED BY role_list SET TABLESPACE name opt_nowait 这是上一条命令的扩展,它不仅移动物化视图,还可以指定所属的角色列表。这允许更细粒度的控制,例如,只移动特定用户或角色拥有的物化视图。

  其中,AlterTableStmtAlterTableMoveAllStmt 是数据库管理系统中用于表示不同类型的修改表操作的结构。尽管它们都用于 ALTER 语句,但它们的用途和作用范围有所不同。

AlterTableStmt 结构体

  AlterTableStmt 结构体是一个 C 语言中的结构体定义,用于在数据库系统(如 PostgreSQL)中表示 ALTER TABLE 语句。结构体 AlterTableStmt 用于保存执行 ALTER TABLE 操作所需的所有信息。以下是对代码中每一行的详细中文注释:(路径:src\include\nodes\parsenodes.h

/* ----------------------
 *	Alter Table
 * ----------------------
 */

/* 定义一个结构体,名为 AlterTableStmt */
typedef struct AlterTableStmt
{
    NodeTag     type;           /* 结构体类型标识,用于节点处理 */
    RangeVar   *relation;       /* 指向要修改的表的结构体指针 */
    List       *cmds;          /* 修改命令的列表,可以包含多个子命令 */
    ObjectType  relkind;        /* 对象类型,指定是表、视图等 */
    bool        missing_ok;     /* 如果指定的表不存在,是否忽略错误 */
} AlterTableStmt;

AlterTableMoveAllStmt 结构体

  AlterTableMoveAllStmt 结构体用于在数据库管理系统中(例如 PostgreSQL)表示对多个对象进行表空间移动的 ALTER TABLE 操作。以下是对这个结构体中每个字段的详细中文注释:(路径:src\include\nodes\parsenodes.h

typedef struct AlterTableMoveAllStmt
{
    NodeTag     type;               /* 结构体类型标识,用于节点处理 */
    char       *orig_tablespacename;/* 原始表空间的名称 */
    ObjectType  objtype;            /* 要移动的对象类型,如表或物化视图 */
    List       *roles;              /* 要移动的对象所属的角色列表 */
    char       *new_tablespacename; /* 目标表空间的名称 */
    bool        nowait;             /* 如果为真,则在移动操作中不等待 */
} AlterTableMoveAllStmt;

重命名

  以下代码是数据库管理系统(如 PostgreSQL)中解析 SQL 语句的一部分,特别是处理 ALTER MATERIALIZED VIEW 命令的重命名操作。这里的代码显示了如何解析两种不同形式的 ALTER MATERIALIZED VIEW … RENAME TO … 语句,并将它们转换为内部的数据结构。后两条用于解析和处理 SQL 语句,特别是涉及重命名物化视图中列的 ALTER MATERIALIZED VIEW 命令。代码展示了如何解析两种形式的重命名操作,并将其转换为内部的数据结构。我们来逐行分析:(路径:src\backend\parser\gram.y

| ALTER MATERIALIZED VIEW qualified_name RENAME TO name
	{
		RenameStmt *n = makeNode(RenameStmt);
		n->renameType = OBJECT_MATVIEW;
		n->relation = $4;
		n->subname = NULL;
		n->newname = $7;
		n->missing_ok = false;
		$$ = (Node *)n;
	}
| ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME TO name
	{
		RenameStmt *n = makeNode(RenameStmt);
		n->renameType = OBJECT_MATVIEW;
		n->relation = $6;
		n->subname = NULL;
		n->newname = $9;
		n->missing_ok = true;
		$$ = (Node *)n;
	}
| ALTER MATERIALIZED VIEW qualified_name RENAME opt_column name TO name
	{
		RenameStmt *n = makeNode(RenameStmt);
		n->renameType = OBJECT_COLUMN;
		n->relationType = OBJECT_MATVIEW;
		n->relation = $4;
		n->subname = $7;
		n->newname = $9;
		n->missing_ok = false;
		$$ = (Node *)n;
	}
| ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name
	{
		RenameStmt *n = makeNode(RenameStmt);
		n->renameType = OBJECT_COLUMN;
		n->relationType = OBJECT_MATVIEW;
		n->relation = $6;
		n->subname = $9;
		n->newname = $11;
		n->missing_ok = true;
		$$ = (Node *)n;
	}
  1. 第一部分 - ALTER MATERIALIZED VIEW qualified_name RENAME TO name:
  • 这部分处理标准的重命名物化视图操作
  • 创建一个 RenameStmt 结构体实例,该结构用于表示重命名操作。
  • renameType 设置为 OBJECT_MATVIEW,表明重命名的对象是一个物化视图。
  • relation 指向被重命名的物化视图。
  • subname 为空,因为这不是对物化视图的子对象的重命名。
  • newname 存储新的物化视图名称。
  • missing_ok 设置为 false,意味着如果物化视图不存在,操作将失败。
  1. 第二部分 - ALTER MATERIALIZED VIEW IF EXISTS qualified_name RENAME TO name:
  • 这部分处理当物化视图存在时的重命名操作
  • 同样创建一个 RenameStmt 结构体实例。
  • renameType 仍然是 OBJECT_MATVIEW
  • relation 指向被重命名的物化视图,但位置不同,这是因为 IF EXISTS 子句改变了语法解析的结构。
  • subname 同样为空。
  • newname 存储新的物化视图名称,位置也根据语法解析结构有所变化。
  • missing_ok 设置为 true,意味着如果物化视图不存在,操作将不会失败,而是简单地不执行任何操作。
  1. 第三部分 - ALTER MATERIALIZED VIEW qualified_name RENAME opt_column name TO name:
  • 这部分处理物化视图中列的标准重命名操作
  • 创建一个 RenameStmt 结构体实例,表示重命名操作。
  • renameType 设置为 OBJECT_COLUMN,表明重命名的是一个列。
  • relationType 设置为 OBJECT_MATVIEW,指明重命名操作发生在物化视图中。
  • relation 指向要修改的物化视图。
  • subname 存储要重命名的列的原始名称。
  • newname 存储新的列名称。
  • missing_ok 设置为 false,意味着如果指定的列不存在,操作将失败。
  1. 第二部分 - ALTER MATERIALIZED VIEW IF EXISTS qualified_name RENAME opt_column name TO name:
  • 这部分处理当物化视图存在时的列重命名操作
  • 同样创建一个 RenameStmt 结构体实例。
  • renameType 仍然是 OBJECT_COLUMN
  • relationType 保持为 OBJECT_MATVIEW
  • relation 指向被重命名的物化视图,但位置根据 IF EXISTS 子句而变化。
  • subname 存储原始列名称,位置也因语法解析结构的变化而有所不同。
  • newname 存储新的列名称。
  • missing_ok 设置为 true,意味着如果指定的列不存在,操作将不会失败,而是简单地不执行任何操作。

  这些代码段与前面提到的代码部分的主要区别在于,它们专门处理物化视图中列的重命名操作,而不是整个物化视图或其他属性的修改。这些代码是数据库管理系统解析和执行 SQL 命令的关键部分,确保正确地理解和实施用户的命令。

RenameStmt 结构体

  RenameStmt 结构体在数据库管理系统中(如 PostgreSQL)用于表示重命名操作的 ALTER 语句。下面是对该结构体中各字段的详细中文注释:(路径:src\include\nodes\parsenodes.h

/* ----------------------
 *      Alter Object Rename Statement
 * ----------------------
 */

/* 定义一个结构体,名为 RenameStmt */
typedef struct RenameStmt
{
    NodeTag     type;           /* 结构体类型标识,用于节点处理 */
    ObjectType  renameType;     /* 要重命名的对象类型,如 OBJECT_TABLE, OBJECT_COLUMN 等 */
    ObjectType  relationType;   /* 如果是列名,关联的表的类型 */
    RangeVar   *relation;       /* 如果是表,指向表的结构体指针 */
    Node       *object;         /* 如果是其他对象,指向该对象的指针 */
    char       *subname;        /* 包含对象的名称(列、规则、触发器等) */
    char       *newname;        /* 新名称 */
    DropBehavior behavior;      /* 删除行为,RESTRICT 或 CASCADE */
    bool        missing_ok;     /* 如果对象不存在,是否跳过错误? */
} RenameStmt;

设置对象依赖于扩展

  以下代码是数据库管理系统(例如 PostgreSQL)中的一部分,用于解析特定的 ALTER 语句,特别是与设置对象依赖于扩展(Extension)相关的命令。代码展示了如何解析 ALTER MATERIALIZED VIEWALTER INDEX 命令中的 DEPENDS ON EXTENSION 子句,并将其转换为内部的数据结构。具体来看:(路径:src\backend\parser\gram.y

	| ALTER MATERIALIZED VIEW qualified_name DEPENDS ON EXTENSION name
	{
		AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
		n->objectType = OBJECT_MATVIEW;
		n->relation = $4;
		n->extname = makeString($8);
		$$ = (Node *)n;
	}
| ALTER INDEX qualified_name DEPENDS ON EXTENSION name
	{
		AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
		n->objectType = OBJECT_INDEX;
		n->relation = $3;
		n->extname = makeString($7);
		$$ = (Node *)n;
	}
  1. ALTER MATERIALIZED VIEW qualified_name DEPENDS ON EXTENSION name:
  • 这部分处理的是为物化视图设置依赖于特定扩展的操作
  • 创建一个 AlterObjectDependsStmt 结构体实例,用于表示设置依赖关系的操作。
  • objectType 设置为 OBJECT_MATVIEW,表明修改的对象是物化视图。
  • relation 指向要修改的物化视图。
  • extname 存储扩展的名称,这是物化视图将依赖的扩展。
  • 结构体实例最后转换成节点(Node)并返回,以便进一步处理。
  1. ALTER INDEX qualified_name DEPENDS ON EXTENSION name:
  • 这部分处理的是为索引设置依赖于特定扩展的操作
  • 同样创建一个 AlterObjectDependsStmt 结构体实例。
  • objectType 设置为 OBJECT_INDEX,表明修改的对象是索引。
  • relation 指向要修改的索引。
  • extname 存储扩展的名称,这是索引将依赖的扩展。

  y以上代码段专门处理设置数据库对象(如物化视图和索引)依赖于特定扩展的操作。通过这种方式,数据库管理系统可以确保在删除或修改这些扩展时正确处理依赖关系,避免破坏数据库的完整性和一致性。这是数据库管理和维护中的一个重要功能,确保数据库对象与其依赖的扩展之间的关系得到适当管理。

AlterObjectDependsStmt 结构体

  AlterObjectDependsStmt 的结构体用于在数据库管理系统中(如 PostgreSQL)表示 ALTER object DEPENDS ON EXTENSION extname 语句。这个结构体用于存储和传递执行依赖于扩展的 ALTER 操作所必需的所有信息。以下是对代码中每一行的详细中文注释:(路径:src\include\nodes\parsenodes.h

/* ----------------------
 * ALTER object DEPENDS ON EXTENSION extname
 * ----------------------
 */

/* 定义一个结构体,名为 AlterObjectDependsStmt */
typedef struct AlterObjectDependsStmt
{
    NodeTag     type;           /* 结构体类型标识,用于节点处理 */
    ObjectType  objectType;     /* 要修改的对象类型,如 OBJECT_FUNCTION, OBJECT_TRIGGER 等 */
    RangeVar   *relation;       /* 如果涉及表,指向表的结构体指针 */
    Node       *object;         /* 要修改的对象的名称 */
    Value      *extname;        /* 依赖的扩展名 */
} AlterObjectDependsStmt;

  AlterObjectDependsStmt 结构体在数据库中扮演重要角色,用于表示和处理 SQL 中的设置对象依赖于特定扩展的操作确保数据库可以正确解析和执行这类命令。通过这种方式,数据库管理系统可以正确地处理数据库对象与其依赖的扩展之间的关系。

测试用例

  下面我们提供一些用于实际测试的模板 SQL 用例覆盖 ALTER MATERIALIZED VIEW 和 ALTER INDEX 语句,以及重命名操作和设置依赖于扩展的操作。请注意,这些测试用例需要根据您的数据库环境进行调整,确保在执行之前,相应的物化视图、索引和扩展已经存在于您的数据库中

在执行这些测试用例之前,请确保:

  • 替换 your_table, your_column, 和 your_extension 为您数据库中实际存在的表名、列名和扩展名
  • 确认您的数据库环境支持所有的操作,特别是物化视图扩展相关的操作
-- 测试用例 1: 创建物化视图
CREATE MATERIALIZED VIEW test_matview AS
SELECT * FROM your_table;

-- 测试用例 2: 修改物化视图名称
ALTER MATERIALIZED VIEW test_matview RENAME TO new_test_matview;

-- 测试用例 3: 如果物化视图存在,则修改物化视图名称
ALTER MATERIALIZED VIEW IF EXISTS new_test_matview RENAME TO test_matview;

-- 测试用例 4: 为物化视图添加依赖的扩展
ALTER MATERIALIZED VIEW test_matview DEPENDS ON EXTENSION your_extension;

-- 测试用例 5: 创建索引
CREATE INDEX test_index ON your_table (your_column);

-- 测试用例 6: 修改索引名称
ALTER INDEX test_index RENAME TO new_test_index;

-- 测试用例 7: 如果索引存在,则修改索引名称
ALTER INDEX IF EXISTS new_test_index RENAME TO test_index;

-- 测试用例 8: 为索引添加依赖的扩展
ALTER INDEX test_index DEPENDS ON EXTENSION your_extension;

-- 清理:删除测试用的物化视图和索引
DROP MATERIALIZED VIEW IF EXISTS test_matview;
DROP INDEX IF EXISTS test_index;

你可能感兴趣的:(PostgerSQL,postgresql,数据库)