海山数据库(He3DB)源码解读:T_GrantStmt原理浅析

一、概述

   Grant 在 He3DB 中用于用于执行SQL授权语句的函数,具体来说,它处理GRANT语句,用于赋予用户或角色特定的权限。

二、GrantRole 命令的执行流程

  1. PostgresMain
  2. exec_simple_query →执行简单的 SQL 查询;
  3. StartTransactionCommand → 开始事务;
  4. pg_parse_query →解析为内部的抽象语法树(AST);
  5. PortalRun
  6. standard_ProcessUtility →权限检查和准备;
  7. ExecuteGrantStm→授予或撤销用户对数据库的权限;
  8. CommandCounterIncrement→增量更新当前的命令计数器;
  9. CommitTransactionCommand→ 提交当前事务;
  10. finish_xact_command→ 在事务结束时,执行必要的清理和关闭操作;
    在这里插入图片描述
图1 Grant 命令的执行流程图

三、核心结构体介绍

 (一)  GrantStmt 是一个表示 GRANT 或 REVOKE 语句的结构体。 该结构体用于存储和处理对数据库对象权限的授予或撤销信息。。以下是每个变量的详细解释:

typedef struct GrantStmt
{
   
   
	NodeTag		type;
	bool		is_grant;		/* true = GRANT, false = REVOKE */
	GrantTargetType targtype;	/* type of the grant target */
	ObjectType	objtype;		/* kind of object being operated on */
	List	   *objects;		/* list of RangeVar nodes, ObjectWithArgs
								 * nodes, or plain names (as String values) */
	List	   *privileges;		/* list of AccessPriv nodes */
	/* privileges == NIL denotes ALL PRIVILEGES */
	List	   *grantees;		/* list of RoleSpec nodes */
	bool		grant_option;	/* grant or revoke grant option */
	RoleSpec   *grantor;
	DropBehavior behavior;		/* drop behavior (for REVOKE) */
} GrantStmt;
  • NodeTag type; 用于标识该节点的类型,通常在抽象语法树(AST)中用于区分不同节点的类型。
  • bool is_grant; 布尔值,指示该操作是 GRANT(true)还是 REVOKE(false)。
  • GrantTargetType targtype;表示授权目标的类型,通常可能是角色、数据库、表等。该类型可能是枚举类型,具体定义在某个头文件中。
  • ObjectType objtype; 表示被操作对象的类型,比如表、视图、序列等,这通常是一个枚举类型。
  • List *objects; 表示授权的目标对象列表,这里可能包含多个 RangeVar(范围变量),ObjectWithArgs(带参数的对象)或普通的字符串(对象名称)。
  • List *privileges;表示要授予或撤销的权限列表。每一个权限可能用 AccessPriv 类型表示。如果该列表为 NIL,表示是授予/撤销所有权限。
  • List *grantees; 表示接收授予或撤销权限的角色列表,这里使用 RoleSpec 类型表示角色。
  • bool grant_option; 布尔值,指示是否授予或撤销授予权限的选项。如果为 true,表示可以将权限进一步授予给其他角色。
  • RoleSpec *grantor;表示进行权限授予或撤销操作的执行者角色。
  • DropBehavior behavior;表示在 REVOKE操作时的删除行为,包括是否强制(CASCADE)或继续保持依赖关系(RESTRICT)。

InternalGrant 结构体是数据库系统内部用于处理权限操作的数据结构。与 GrantStmt 相比,它对权限的表示方式更为简洁和直接,使用 AclMode 类型表示权限位掩码,而不是一个权限列表。这种设计更适合在数据库内部进行高效的权限处理和操作。

typedef struct
{
   
   
	bool		is_grant;
	ObjectType	objtype;
	List	   *objects;
	bool		all_privs;
	AclMode		privileges;
	List	   *col_privs;
	List	   *grantees;
	bool		grant_option;
	DropBehavior behavior;
} InternalGrant;
  • is_grant: 指示操作类型(GRANT 或 REVOKE)。
  • objtype: 被操作对象的类型。
  • objects:被操作的对象列表。
  • all_privs: 是否授予或撤销所有权限。
  • privileges: 具体的权限模式(位掩码形式)。
  • col_privs: 列级权限列表。
  • grantees: 被授予或撤销权限的角色列表。
  • grant_option: 是否授予或撤销授予权限的选项。
  • behavior: REVOKE 操作时的删除行为。

四、核心代码解析

   在 He3DB 的源代码中, ExecuteGrantStmt (@src\backend\catalog\aclchk.c)的函数,用于处理 PostgreSQL 中的 GRANT 和 REVOKE 语句。它将输入的 GrantStmt 结构转换为内部处理的 InternalGrant 结构,然后执行权限授予或撤销操作。以下是对代码中每个部分的详细解析:

void
ExecuteGrantStmt(GrantStmt *stmt)
{
   
   

函数名为 ExecuteGrantStmt,接受一个 GrantStmt 类型的指针 stmt 作为参数。

	InternalGrant istmt;
	ListCell *cell = NULL;
	const char *errormsg = NULL;
	AclMode all_privileges;

istmt:用于存储转换后的内部授权语句。
cell:用于遍历链表的指针。
errormsg:用于存储错误信息。
all_privileges:用于存储所有可能的权限。

	if (stmt->grantor)
	{
   
   
		Oid grantor = 0;

		grantor = get_rolespec_oid(stmt->grantor, false);

		/*
		 * Currently, this clause is only for SQL compatibility, not very
		 * interesting otherwise.
		 */
		if (grantor != GetUserId())
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("grantor must be current user")));
	}

如果 stmt->grantor 不为空,则获取 grantor 的 Oid。
如果 grantor 不是当前用户,则抛出一个错误,表示 grantor 必须是当前用户。

	/*
	 * Turn the regular GrantStmt into the InternalGrant form.
	 */
	istmt.is_grant = stmt->is_grant;
	istmt.objtype = stmt->objtype;

将 stmt->is_grant 和 stmt->objtype 直接赋值给 istmt 的相应字段。

	/* Collect the OIDs of the target objects */
	switch (stmt->targtype)
	{
   
   
		case ACL_TARGET_OBJECT:
			istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects, stmt->is_grant);
			break;
		case ACL_TARGET_ALL_IN_SCHEMA:
			istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
			break;
		/* ACL_TARGET_DEFAULTS should not be seen here */
		default:
			elog(ERROR, "unrecognized GrantStmt.targtype: %d", (int) stmt->targtype);
	}

根据 stmt->targtype 的不同,调用不同的函数将对象名转换为 OID。
如果 targtype 无法识别,则抛出错误。

	/* all_privs to be filled below */
	/* privileges to be filled belo
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值