授予和撤销应用程序中的权限

反复地执行与数据定义相关的一个任务:授予和撤销权限。由于必须频繁地授予和撤销权限,有可能是由不熟悉 SQL 的用户操作,因此一种策略是将 GRANT 和 REVOKE 语句打包在程序中,来提供给他们更简单、更方便的用户接口。

GRANT 和 REVOKE 语句特别适合于动态 SQL。每一语句采用下列参数:
  • 一个或多个权限的列表
  • 表名称
  • 用户的名称

您可能至少需要基于程序输入(来自于用户、命令行参数或文件)提供这些值的一部分,但都不可以主变量的形式提供。这些语句的语法不允许在任何位置使用主变量。

一个替代方案是将语句的各个部分组合到字符串内,并准备和执行组合好的语句。程序输入可作为字符串合并到准备好的语句内。

下列 GBase 8s ESQL/C 函数从参数组合 GRANT 语句,然后准备和执行它:
char priv_to_grant[100];
          char table_name[20];
          char user_id[20];
          
          table_grant(priv_to_grant, table_name, user_id)
          char *priv_to_grant;
          char *table_name;
          char *user_id;
          {
          EXEC SQL BEGIN DECLARE SECTION;
          char grant_stmt[200];
          EXEC SQL END DECLARE SECTION;
          
          sprintf(grant_stmt, " GRANT %s ON %s TO %s",
          priv_to_grant, table_name, user_id);
          PREPARE the_grant FROM :grant_stmt;
          if(SQLCODE == 0)
          EXEC SQL EXECUTE the_grant;
          else
          printf("Sorry, got error # %d attempting %s", 
          SQLCODE, grant_stmt);
          
          EXEC SQL FREE the_grant;
          }
下列示例展示的该函数的打开语句指定它的名称及其三个参数。这三个参数指定要授予的权限、对其授予权限的表的名称,以及要接收它们的用户的 ID。
table_grant(priv_to_grant, table_name, user_id)
          char *priv_to_grant;
          char *table_name;
          char *user_id;
该函数使用下例中的语句来定义本地变量 grant_stmt,使用其来组合并保存 GRANT 语句:
EXEC SQL BEGIN DECLARE SECTION;
          char grant_stmt[200];
          EXEC SQL END DECLARE SECTION;
如下例所示,通过将该语句的常量部分与函数参数连起来,创建该 GRANT 语句:
sprintf(grant_stmt, " GRANT %s ON %s TO %s",priv_to_grant, 
          table_name, user_id);
此语句将下列六个字符串连接起来:
  • 'GRANT'
  • 指定要授予的权限的参数
  • 'ON'
  • 指定表名称的参数
  • 'TO'
  • 指定用户的参数

结果是部分由程序输入组成的完整的 GRANT 语句。PREPARE 语句将组合的语句文本传给数据库服务器进行解析。

如果数据库服务器跟在 PREPARE 语句之后在 SQLCODE 中返回错误代码,则该函数显示错误消息。如果数据库服务器认可该语句的形式,则它设置零返回值。此活动并不保证正确地执行该语句;它仅意味着该语句的语法正确。它可能引用不存在的表或某些种类仅可在执行期间才能检测到的错误。该示例的下列部分在执行之前检查 the_grant 是否准备成功了:
if(SQLCODE == 0)
          EXEC SQL EXECUTE the_grant;
          else
          printf("Sorry, got error # %d attempting %s", SQLCODE, grant_stmt);

如果准备成功,则 SQLCODE = = 0,下一步执行准备好的语句。