一、概述
Grant 在 He3DB 中用于用于执行SQL授权语句的函数,具体来说,它处理GRANT语句,用于赋予用户或角色特定的权限。
二、GrantRole 命令的执行流程
- PostgresMain
- exec_simple_query →执行简单的 SQL 查询;
- StartTransactionCommand → 开始事务;
- pg_parse_query →解析为内部的抽象语法树(AST);
- PortalRun
- standard_ProcessUtility →权限检查和准备;
- ExecuteGrantStm→授予或撤销用户对数据库的权限;
- CommandCounterIncrement→增量更新当前的命令计数器;
- CommitTransactionCommand→ 提交当前事务;
- finish_xact_command→ 在事务结束时,执行必要的清理和关闭操作;

三、核心结构体介绍
(一) 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

最低0.47元/天 解锁文章
758

被折叠的 条评论
为什么被折叠?



