From 8301e76163245c299528ad0095071a81684df2aa Mon Sep 17 00:00:00 2001 From: Shalini Lohia Date: Tue, 21 Nov 2023 09:27:32 +0000 Subject: [PATCH 1/5] Stored the permissions in a single column using bits --- contrib/babelfishpg_tsql/sql/ownership.sql | 4 +- .../babelfishpg_tsql--3.3.0--3.4.0.sql | 4 +- contrib/babelfishpg_tsql/src/catalog.c | 313 +++++++++++++----- contrib/babelfishpg_tsql/src/catalog.h | 29 +- contrib/babelfishpg_tsql/src/pl_exec-2.c | 173 ++++++---- contrib/babelfishpg_tsql/src/pl_handler.c | 236 ++++++++----- contrib/babelfishpg_tsql/src/pltsql.h | 9 + contrib/babelfishpg_tsql/src/pltsql_utils.c | 33 +- test/JDBC/expected/GRANT_SCHEMA.out | 2 +- 9 files changed, 562 insertions(+), 241 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/ownership.sql b/contrib/babelfishpg_tsql/sql/ownership.sql index ee3a5446a43..d64265fa631 100644 --- a/contrib/babelfishpg_tsql/sql/ownership.sql +++ b/contrib/babelfishpg_tsql/sql/ownership.sql @@ -19,10 +19,10 @@ CREATE TABLE sys.babelfish_schema_permissions ( dbid smallint NOT NULL, schema_name NAME NOT NULL, object_name NAME NOT NULL, - permission NAME NOT NULL, + permission SMALLINT, grantee NAME NOT NULL, object_type NAME, - PRIMARY KEY(dbid, schema_name, object_name, permission, grantee) + PRIMARY KEY(dbid, schema_name, object_name, grantee) ); -- BABELFISH_FUNCTION_EXT diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql index fe141534577..00cfcff59b0 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql @@ -894,10 +894,10 @@ CREATE TABLE IF NOT EXISTS sys.babelfish_schema_permissions ( dbid smallint NOT NULL, schema_name NAME NOT NULL, object_name NAME NOT NULL, - permission NAME NOT NULL, + permission SMALLINT, grantee NAME NOT NULL, object_type NAME, - PRIMARY KEY(dbid, schema_name, object_name, permission, grantee) + PRIMARY KEY(dbid, schema_name, object_name, grantee) ); create or replace function sys.babelfish_timezone_mapping(IN tmz text) returns text diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 8f1f9bdc2a2..8d4f7ca4cd3 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -2832,7 +2832,7 @@ rename_procfunc_update_bbf_catalog(RenameStmt *stmt) void add_entry_to_bbf_schema(const char *schema_name, const char *object_name, - const char *permission, + int16 permission, const char *grantee, const char *object_type) { @@ -2855,7 +2855,7 @@ add_entry_to_bbf_schema(const char *schema_name, new_record_bbf_schema[BBF_SCHEMA_PERMS_DBID] = Int16GetDatum(dbid); new_record_bbf_schema[BBF_SCHEMA_PERMS_SCHEMA_NAME] = CStringGetDatum(pstrdup(schema_name)); new_record_bbf_schema[BBF_SCHEMA_PERMS_OBJECT_NAME] = CStringGetDatum(pstrdup(object_name)); - new_record_bbf_schema[BBF_SCHEMA_PERMS_PERMISSION] = CStringGetDatum(pstrdup(permission)); + new_record_bbf_schema[BBF_SCHEMA_PERMS_PERMISSION] = Int16GetDatum(permission); new_record_bbf_schema[BBF_SCHEMA_PERMS_GRANTEE] = CStringGetDatum(pstrdup(grantee)); if (object_type != NULL) new_record_bbf_schema[BBF_SCHEMA_PERMS_OBJECT_TYPE] = CStringGetDatum(pstrdup(object_type)); @@ -2876,16 +2876,160 @@ add_entry_to_bbf_schema(const char *schema_name, CommandCounterIncrement(); } +/* + * Get the value of permission column from BABELFISH_SCHEMA_PERMISSIONS table. + */ +int16 +get_bbf_schema_privilege(const char *schema_name, + const char *object_name, + const char *grantee) +{ + Relation bbf_schema_rel; + HeapTuple tuple_bbf_schema; + ScanKeyData key[4]; + TableScanDesc scan; + int16 dbid = get_cur_db_id(); + int16 permission = 0; + + bbf_schema_rel = table_open(get_bbf_schema_perms_oid(), + AccessShareLock); + ScanKeyInit(&key[0], + Anum_bbf_schema_perms_dbid, + BTEqualStrategyNumber, F_INT2EQ, + Int16GetDatum(dbid)); + ScanKeyInit(&key[1], + Anum_bbf_schema_perms_schema_name, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(schema_name)); + ScanKeyInit(&key[2], + Anum_bbf_schema_perms_object_name, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(object_name)); + ScanKeyInit(&key[3], + Anum_bbf_schema_perms_grantee, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(grantee)); + + scan = table_beginscan_catalog(bbf_schema_rel, 4, key); + tuple_bbf_schema = heap_getnext(scan, ForwardScanDirection); + if (HeapTupleIsValid(tuple_bbf_schema)) + { + Form_bbf_schema_perms bbf_schema = (Form_bbf_schema_perms) GETSTRUCT(tuple_bbf_schema); + permission = bbf_schema->permission; + } + + table_endscan(scan); + table_close(bbf_schema_rel, AccessShareLock); + return permission; +} + +/* + * Update permission column in the catalog when privilege on an object is changed. + */ +void +update_bbf_schema_privilege(const char *schema_name, + const char *object_name, + int16 new_priv, + int16 old_priv, + const char *grantee, + const char *object_type, + bool is_grant) +{ + Relation bbf_schema_rel; + HeapTuple tuple_bbf_schema; + TupleDesc bbf_schema_dsc; + HeapTuple new_tuple; + ScanKeyData key[5]; + TableScanDesc scan; + int16 dbid = get_cur_db_id(); + int16 permission = 0; + Datum new_record_bbf_schema[BBF_SCHEMA_PERMS_NUM_OF_COLS]; + bool new_record_nulls_bbf_schema[BBF_SCHEMA_PERMS_NUM_OF_COLS]; + bool new_record_repl_bbf_schema[BBF_SCHEMA_PERMS_NUM_OF_COLS]; + + if(is_grant) + { + /* + * In case of GRANT, we add the new privilege along with the previous privilege in the column. + */ + permission = new_priv | old_priv; + } + else + { + /* + * In case of REVOKE, we remove the new privilege and keep the previous privilege as it is. + */ + permission = ~new_priv & old_priv; + } + + if(permission == 0) + { + del_from_bbf_schema(schema_name, object_name, grantee); + return; + } + + bbf_schema_rel = table_open(get_bbf_schema_perms_oid(), + RowExclusiveLock); + + ScanKeyInit(&key[0], + Anum_bbf_schema_perms_dbid, + BTEqualStrategyNumber, F_INT2EQ, + Int16GetDatum(dbid)); + ScanKeyInit(&key[1], + Anum_bbf_schema_perms_schema_name, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(schema_name)); + ScanKeyInit(&key[2], + Anum_bbf_schema_perms_object_name, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(object_name)); + ScanKeyInit(&key[3], + Anum_bbf_schema_perms_permission, + BTEqualStrategyNumber, F_INT2EQ, + Int16GetDatum(old_priv)); + ScanKeyInit(&key[4], + Anum_bbf_schema_perms_grantee, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(grantee)); + + scan = table_beginscan_catalog(bbf_schema_rel, 5, key); + tuple_bbf_schema = heap_getnext(scan, ForwardScanDirection); + if (HeapTupleIsValid(tuple_bbf_schema)) + { + bbf_schema_dsc = RelationGetDescr(bbf_schema_rel); + /* Build a tuple to insert */ + MemSet(new_record_bbf_schema, 0, sizeof(new_record_bbf_schema)); + MemSet(new_record_nulls_bbf_schema, false, sizeof(new_record_nulls_bbf_schema)); + MemSet(new_record_repl_bbf_schema, false, sizeof(new_record_repl_bbf_schema)); + + new_record_bbf_schema[BBF_SCHEMA_PERMS_PERMISSION] = Int16GetDatum(permission); + new_record_repl_bbf_schema[BBF_SCHEMA_PERMS_PERMISSION] = true; + + new_tuple = heap_modify_tuple(tuple_bbf_schema, + bbf_schema_dsc, + new_record_bbf_schema, + new_record_nulls_bbf_schema, + new_record_repl_bbf_schema); + + CatalogTupleUpdate(bbf_schema_rel, &new_tuple->t_self, new_tuple); + heap_freetuple(new_tuple); + } + + table_endscan(scan); + table_close(bbf_schema_rel, RowExclusiveLock); + + CommandCounterIncrement(); +} + /* Check if the catalog entry exists. */ bool check_bbf_schema_for_entry(const char *schema_name, const char *object_name, - const char *permission, const char *grantee) { Relation bbf_schema_rel; HeapTuple tuple_bbf_schema; - ScanKeyData key[5]; + ScanKeyData key[4]; TableScanDesc scan; bool catalog_entry_exists = false; int16 dbid = get_cur_db_id(); @@ -2905,15 +3049,11 @@ check_bbf_schema_for_entry(const char *schema_name, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(object_name)); ScanKeyInit(&key[3], - Anum_bbf_schema_perms_permission, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(permission)); - ScanKeyInit(&key[4], Anum_bbf_schema_perms_grantee, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(grantee)); - scan = table_beginscan_catalog(bbf_schema_rel, 5, key); + scan = table_beginscan_catalog(bbf_schema_rel, 4, key); tuple_bbf_schema = heap_getnext(scan, ForwardScanDirection); if (HeapTupleIsValid(tuple_bbf_schema)) @@ -2924,17 +3064,21 @@ check_bbf_schema_for_entry(const char *schema_name, return catalog_entry_exists; } +/* + * Checks if the specified permission exists on a particular schema + * at the schema level in the catalog. + */ bool check_bbf_schema_for_schema(const char *schema_name, const char *object_name, - const char *permission) + int16 permission) { Relation bbf_schema_rel; HeapTuple tuple_bbf_schema; - ScanKeyData key[4]; + ScanKeyData key[3]; TableScanDesc scan; - bool catalog_entry_exists = false; int16 dbid = get_cur_db_id(); + int16 priv = 0; bbf_schema_rel = table_open(get_bbf_schema_perms_oid(), AccessShareLock); @@ -2950,31 +3094,32 @@ check_bbf_schema_for_schema(const char *schema_name, Anum_bbf_schema_perms_object_name, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(object_name)); - ScanKeyInit(&key[3], - Anum_bbf_schema_perms_permission, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(permission)); - scan = table_beginscan_catalog(bbf_schema_rel, 4, key); + scan = table_beginscan_catalog(bbf_schema_rel, 3, key); tuple_bbf_schema = heap_getnext(scan, ForwardScanDirection); - if (HeapTupleIsValid(tuple_bbf_schema)) - catalog_entry_exists = true; + while (HeapTupleIsValid(tuple_bbf_schema)) + { + Form_bbf_schema_perms schemaform; + schemaform = (Form_bbf_schema_perms) GETSTRUCT(tuple_bbf_schema); + priv = schemaform->permission; + if((permission & priv) == permission) + return true; + } table_endscan(scan); table_close(bbf_schema_rel, AccessShareLock); - return catalog_entry_exists; + return false; } void del_from_bbf_schema(const char *schema_name, const char *object_name, - const char *permission, const char *grantee) { Relation bbf_schema_rel; HeapTuple tuple_bbf_schema; - ScanKeyData key[5]; + ScanKeyData key[4]; TableScanDesc scan; int16 dbid = get_cur_db_id(); @@ -2993,15 +3138,11 @@ del_from_bbf_schema(const char *schema_name, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(object_name)); ScanKeyInit(&key[3], - Anum_bbf_schema_perms_permission, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(permission)); - ScanKeyInit(&key[4], Anum_bbf_schema_perms_grantee, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(grantee)); - scan = table_beginscan_catalog(bbf_schema_rel, 5, key); + scan = table_beginscan_catalog(bbf_schema_rel, 4, key); tuple_bbf_schema = heap_getnext(scan, ForwardScanDirection); @@ -3074,19 +3215,71 @@ clean_up_bbf_schema(const char *schema_name, table_close(bbf_schema_rel, RowExclusiveLock); } +void +grant_perms_to_each_obj(const char *db_name, + const char *object_type, + const char *schema_name, + const char *object_name, + const char *grantee, + const char *permission) +{ + StringInfoData query; + char *schema; + List *res; + Node *res_stmt; + PlannedStmt *wrapper; + + schema = get_physical_schema_name((char *)db_name, schema_name); + initStringInfo(&query); + if (strcmp(permission, "execute") != 0) + appendStringInfo(&query, "GRANT \"%s\" ON \"%s\".\"%s\" TO \"%s\"; ", permission, schema, object_name, grantee); + else + { + if (object_type != NULL && strcmp(object_type, "f") == 0) + appendStringInfo(&query, "GRANT \"%s\" ON FUNCTION \"%s\".\"%s\" TO \"%s\"; ", permission, schema, object_name, grantee); + else + appendStringInfo(&query, "GRANT \"%s\" ON PROCEDURE \"%s\".\"%s\" TO \"%s\"; ", permission, schema, object_name, grantee); + } + res = raw_parser(query.data, RAW_PARSE_DEFAULT); + res_stmt = ((RawStmt *) linitial(res))->stmt; + + /* need to make a wrapper PlannedStmt */ + wrapper = makeNode(PlannedStmt); + wrapper->commandType = CMD_UTILITY; + wrapper->canSetTag = false; + wrapper->utilityStmt = res_stmt; + wrapper->stmt_location = 0; + wrapper->stmt_len = 1; + + /* do this step */ + ProcessUtility(wrapper, + "(GRANT STATEMENT )", + false, + PROCESS_UTILITY_SUBCOMMAND, + NULL, + NULL, + None_Receiver, + NULL); + + /* make sure later steps can see the object created here */ + CommandCounterIncrement(); + pfree(query.data); +} + void grant_perms_to_objects_in_schema(const char *schema_name, - const char *permission, - const char *grantee) + int16 priv, + const char *grantee) { TableScanDesc scan; Relation bbf_schema_rel; HeapTuple tuple_bbf_schema; const char *object_name; const char *object_type; - ScanKeyData scanKey[4]; + ScanKeyData scanKey[3]; int16 dbid = get_cur_db_id(); const char *db_name = get_cur_db_name(); + int16 permission = 0; /* Fetch the relation */ bbf_schema_rel = table_open(get_bbf_schema_perms_oid(), @@ -3100,15 +3293,11 @@ grant_perms_to_objects_in_schema(const char *schema_name, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(schema_name)); ScanKeyInit(&scanKey[2], - Anum_bbf_schema_perms_permission, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(permission)); - ScanKeyInit(&scanKey[3], Anum_bbf_schema_perms_grantee, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(grantee)); - scan = table_beginscan_catalog(bbf_schema_rel, 4, scanKey); + scan = table_beginscan_catalog(bbf_schema_rel, 3, scanKey); tuple_bbf_schema = heap_getnext(scan, ForwardScanDirection); while (HeapTupleIsValid(tuple_bbf_schema)) @@ -3117,50 +3306,22 @@ grant_perms_to_objects_in_schema(const char *schema_name, schemaform = (Form_bbf_schema_perms) GETSTRUCT(tuple_bbf_schema); object_name = pstrdup(NameStr(schemaform->object_name)); object_type = pstrdup(NameStr(schemaform->object_type)); - + permission = (priv & (schemaform->permission)); /* For each object, grant the permission explicitly. */ if (strcmp(object_name, "ALL") != 0) { - StringInfoData query; - char *schema; - List *res; - Node *res_stmt; - PlannedStmt *wrapper; - - schema = get_physical_schema_name((char *)db_name, schema_name); - initStringInfo(&query); - if (strcmp(permission, "execute") != 0) - appendStringInfo(&query, "GRANT \"%s\" ON \"%s\".\"%s\" TO \"%s\"; ", permission, schema, object_name, grantee); - else - { - if (object_type != NULL && strcmp(object_type, "f") == 0) - appendStringInfo(&query, "GRANT \"%s\" ON FUNCTION \"%s\".\"%s\" TO \"%s\"; ", permission, schema, object_name, grantee); - else - appendStringInfo(&query, "GRANT \"%s\" ON PROCEDURE \"%s\".\"%s\" TO \"%s\"; ", permission, schema, object_name, grantee); - } - res = raw_parser(query.data, RAW_PARSE_DEFAULT); - res_stmt = ((RawStmt *) linitial(res))->stmt; - - /* need to make a wrapper PlannedStmt */ - wrapper = makeNode(PlannedStmt); - wrapper->commandType = CMD_UTILITY; - wrapper->canSetTag = false; - wrapper->utilityStmt = res_stmt; - wrapper->stmt_location = 0; - wrapper->stmt_len = 1; - - /* do this step */ - ProcessUtility(wrapper, - "(GRANT STATEMENT )", - false, - PROCESS_UTILITY_SUBCOMMAND, - NULL, - NULL, - None_Receiver, - NULL); - - /* make sure later steps can see the object created here */ - CommandCounterIncrement(); + if((permission & PRIVILEGE_EXECUTE) == PRIVILEGE_EXECUTE) + grant_perms_to_each_obj(db_name, object_type, schema_name, object_name, grantee, "execute"); + if((permission & PRIVILEGE_SELECT) == PRIVILEGE_SELECT) + grant_perms_to_each_obj(db_name, object_type, schema_name, object_name, grantee, "select"); + if((permission & PRIVILEGE_INSERT) == PRIVILEGE_INSERT) + grant_perms_to_each_obj(db_name, object_type, schema_name, object_name, grantee, "insert"); + if((permission & PRIVILEGE_UPDATE) == PRIVILEGE_UPDATE) + grant_perms_to_each_obj(db_name, object_type, schema_name, object_name, grantee, "update"); + if((permission & PRIVILEGE_DELETE) == PRIVILEGE_DELETE) + grant_perms_to_each_obj(db_name, object_type, schema_name, object_name, grantee, "delete"); + if((permission & PRIVILEGE_REFERENCES) == PRIVILEGE_REFERENCES) + grant_perms_to_each_obj(db_name, object_type, schema_name, object_name, grantee, "references"); } tuple_bbf_schema = heap_getnext(scan, ForwardScanDirection); } diff --git a/contrib/babelfishpg_tsql/src/catalog.h b/contrib/babelfishpg_tsql/src/catalog.h index 7b8ad195c27..b3b1b024c7d 100644 --- a/contrib/babelfishpg_tsql/src/catalog.h +++ b/contrib/babelfishpg_tsql/src/catalog.h @@ -310,7 +310,7 @@ typedef struct FormData_bbf_schema_perms int16 dbid; NameData schema_name; NameData object_name; - NameData permission; + int16 permission; NameData grantee; NameData object_type; } FormData_bbf_schema_perms; @@ -319,30 +319,47 @@ typedef FormData_bbf_schema_perms *Form_bbf_schema_perms; extern void add_entry_to_bbf_schema(const char *schema_name, const char *object_name, - const char *permission, + int16 permission, const char *grantee, const char *object_type); +extern int16 get_bbf_schema_privilege(const char *schema_name, + const char *object_name, + const char *grantee); + +extern void update_bbf_schema_privilege(const char *schema_name, + const char *object_name, + int16 new_priv, + int16 old_priv, + const char *grantee, + const char *object_type, + bool is_grant); + extern bool check_bbf_schema_for_entry(const char *schema_name, const char *object_name, - const char *permission, const char *grantee); extern void del_from_bbf_schema(const char *schema_name, const char *object_name, - const char *permission, const char *grantee); extern bool check_bbf_schema_for_schema(const char *schema_name, const char *object_name, - const char *permission); + int16 permission); extern void clean_up_bbf_schema(const char *schema_name, const char *object_name, bool is_schema); +extern void grant_perms_to_each_obj(const char *db_name, + const char *object_type, + const char *schema_name, + const char *object_name, + const char *grantee, + const char *permission); + extern void grant_perms_to_objects_in_schema(const char *schema_name, - const char *permission, + int16 permission, const char *grantee); /***************************************** diff --git a/contrib/babelfishpg_tsql/src/pl_exec-2.c b/contrib/babelfishpg_tsql/src/pl_exec-2.c index 4e948a0be0f..8845ee48d2b 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec-2.c +++ b/contrib/babelfishpg_tsql/src/pl_exec-2.c @@ -55,6 +55,7 @@ static int exec_stmt_usedb_explain(PLtsql_execstate *estate, PLtsql_stmt_usedb * static int exec_stmt_grantdb(PLtsql_execstate *estate, PLtsql_stmt_grantdb *stmt); static int exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt); static int exec_stmt_fulltextindex(PLtsql_execstate *estate, PLtsql_stmt_fulltextindex *stmt); +static void exec_gen_grantschema(char *schema_name, char *rolname, PLtsql_stmt_grantschema *stmt, char *priv_name); static int exec_stmt_insert_execute_select(PLtsql_execstate *estate, PLtsql_expr *expr); static int exec_stmt_insert_bulk(PLtsql_execstate *estate, PLtsql_stmt_insert_bulk *expr); static int exec_stmt_dbcc(PLtsql_execstate *estate, PLtsql_stmt_dbcc *stmt); @@ -3675,101 +3676,129 @@ get_insert_bulk_kilobytes_per_batch() return insert_bulk_kilobytes_per_batch; } -static int -exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt) +static void +exec_gen_grantschema(char *schema_name, char *rolname, PLtsql_stmt_grantschema *stmt, char *priv_name) { List *parsetree_list; ListCell *parsetree_item; - char *dbname = get_cur_db_name(); - char *login = GetUserNameFromId(GetSessionUserId(), false); + parsetree_list = gen_grantschema_subcmds(schema_name, rolname, stmt->is_grant, stmt->with_grant_option, priv_name); + /* Run all subcommands */ + foreach(parsetree_item, parsetree_list) + { + Node *stmt = ((RawStmt *) lfirst(parsetree_item))->stmt; + PlannedStmt *wrapper; + + /* need to make a wrapper PlannedStmt */ + wrapper = makeNode(PlannedStmt); + wrapper->commandType = CMD_UTILITY; + wrapper->canSetTag = false; + wrapper->utilityStmt = stmt; + wrapper->stmt_location = 0; + wrapper->stmt_len = 0; + + /* do this step */ + ProcessUtility(wrapper, + "(GRANT SCHEMA )", + false, + PROCESS_UTILITY_SUBCOMMAND, + NULL, + NULL, + None_Receiver, + NULL); + + /* make sure later steps can see the object created here */ + CommandCounterIncrement(); + } +} + +static int +exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt) +{ + char *dbname = get_cur_db_name(); + char *login = GetUserNameFromId(GetSessionUserId(), false); bool login_is_db_owner; - Oid datdba; char *rolname; char *schema_name; - ListCell *lc; - ListCell *lc1; - Oid schemaOid; + ListCell *lc; + Oid schemaOid; + int16 privilege_maskInt = create_privilege_bitmask(stmt->privileges, true); /* * If the login is not the db owner or the login is not the member of * sysadmin or login is not the schema owner, then it doesn't have the permission to GRANT/REVOKE. */ login_is_db_owner = 0 == strncmp(login, get_owner_of_db(dbname), NAMEDATALEN); - datdba = get_role_oid("sysadmin", false); schema_name = get_physical_schema_name(dbname, stmt->schema_name); - schemaOid = LookupExplicitNamespace(schema_name, true); + if(schema_name) + { + schemaOid = LookupExplicitNamespace(schema_name, true); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_SCHEMA), + errmsg("An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as \"\" or [] are not allowed. Change the alias to a valid name."))); + } if (!OidIsValid(schemaOid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_SCHEMA), errmsg("schema \"%s\" does not exist", schema_name))); - - if (!is_member_of_role(GetSessionUserId(), datdba) && !login_is_db_owner && !pg_namespace_ownercheck(schemaOid, GetUserId())) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("Cannot find the schema \"%s\", because it does not exist or you do not have permission.", stmt->schema_name))); - foreach(lc1, stmt->privileges) + foreach(lc, stmt->grantees) { - char *priv_name = (char *) lfirst(lc1); - foreach(lc, stmt->grantees) - { - char *grantee_name = (char *) lfirst(lc); - Oid role_oid; - bool grantee_is_db_owner; - rolname = get_physical_user_name(dbname, grantee_name); - role_oid = get_role_oid(rolname, true); - grantee_is_db_owner = 0 == strncmp(grantee_name, get_owner_of_db(dbname), NAMEDATALEN); - + char *grantee_name = (char *) lfirst(lc); + char *user = GetUserNameFromId(GetUserId(), false); + Oid role_oid; + int16 old_priv = 0; + rolname = get_physical_user_name(dbname, grantee_name); + role_oid = get_role_oid(rolname, true); - if (role_oid == InvalidOid) - ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("Cannot find the principal '%s', because it does not exist or you do not have permission.", grantee_name))); + if (role_oid == InvalidOid) + ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("Cannot find the principal '%s', because it does not exist or you do not have permission.", grantee_name))); - if (pg_namespace_ownercheck(schemaOid, role_oid) || is_member_of_role(role_oid, datdba) || grantee_is_db_owner) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself."))); + if ((strcmp(rolname, user) == 0) || pg_namespace_ownercheck(schemaOid, role_oid) || is_member_of_role(role_oid, get_sysadmin_oid())) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself."))); - parsetree_list = gen_grantschema_subcmds(schema_name, rolname, stmt->is_grant, stmt->with_grant_option, priv_name); - /* Run all subcommands */ - foreach(parsetree_item, parsetree_list) - { - Node *stmt = ((RawStmt *) lfirst(parsetree_item))->stmt; - PlannedStmt *wrapper; - - /* need to make a wrapper PlannedStmt */ - wrapper = makeNode(PlannedStmt); - wrapper->commandType = CMD_UTILITY; - wrapper->canSetTag = false; - wrapper->utilityStmt = stmt; - wrapper->stmt_location = 0; - wrapper->stmt_len = 0; - - /* do this step */ - ProcessUtility(wrapper, - "(GRANT SCHEMA )", - false, - PROCESS_UTILITY_SUBCOMMAND, - NULL, - NULL, - None_Receiver, - NULL); - - /* make sure later steps can see the object created here */ - CommandCounterIncrement(); - } - /* Add entry for each grant statement. */ - if (stmt->is_grant && !check_bbf_schema_for_entry(stmt->schema_name, "ALL", priv_name, rolname)) - add_entry_to_bbf_schema(stmt->schema_name, "ALL", priv_name, rolname, NULL); - /* Remove entry for each revoke statement. */ - if (!stmt->is_grant && check_bbf_schema_for_entry(stmt->schema_name, "ALL", priv_name, rolname)) - { - /* If any object in the schema has the OBJECT level permission. Then, internally grant that permission back. */ - grant_perms_to_objects_in_schema(stmt->schema_name, priv_name, rolname); - del_from_bbf_schema(stmt->schema_name, "ALL", priv_name, rolname); - } + if (!is_member_of_role(GetSessionUserId(), get_sysadmin_oid()) && !login_is_db_owner && !pg_namespace_ownercheck(schemaOid, GetUserId())) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("Cannot find the schema \"%s\", because it does not exist or you do not have permission.", stmt->schema_name))); + + if((privilege_maskInt & PRIVILEGE_EXECUTE) == PRIVILEGE_EXECUTE) + exec_gen_grantschema(schema_name, rolname, stmt, "execute"); + if((privilege_maskInt & PRIVILEGE_SELECT) == PRIVILEGE_SELECT) + exec_gen_grantschema(schema_name, rolname, stmt, "select"); + if((privilege_maskInt & PRIVILEGE_INSERT) == PRIVILEGE_INSERT) + exec_gen_grantschema(schema_name, rolname, stmt, "insert"); + if((privilege_maskInt & PRIVILEGE_UPDATE) == PRIVILEGE_UPDATE) + exec_gen_grantschema(schema_name, rolname, stmt, "update"); + if((privilege_maskInt & PRIVILEGE_DELETE) == PRIVILEGE_DELETE) + exec_gen_grantschema(schema_name, rolname, stmt, "delete"); + if((privilege_maskInt & PRIVILEGE_REFERENCES) == PRIVILEGE_REFERENCES) + exec_gen_grantschema(schema_name, rolname, stmt, "references"); + + /* Add entry for each grant statement. */ + if (stmt->is_grant && !check_bbf_schema_for_entry(stmt->schema_name, "ALL", rolname)) + add_entry_to_bbf_schema(stmt->schema_name, "ALL", privilege_maskInt, rolname, NULL); + else if(stmt->is_grant) + { + int16 old_priv = get_bbf_schema_privilege(stmt->schema_name, "ALL", rolname); + if(old_priv!= privilege_maskInt || ((old_priv|privilege_maskInt) != old_priv)) + update_bbf_schema_privilege(stmt->schema_name, "ALL", privilege_maskInt, old_priv, rolname, NULL, stmt->is_grant); + } + /* Remove entry for each revoke statement. */ + else if (!stmt->is_grant && check_bbf_schema_for_entry(stmt->schema_name, "ALL", rolname)) + { + /* If any object in the schema has the OBJECT level permission. Then, internally grant that permission back. */ + grant_perms_to_objects_in_schema(stmt->schema_name, privilege_maskInt, rolname); + old_priv = get_bbf_schema_privilege(stmt->schema_name, "ALL", rolname); + if(old_priv!= privilege_maskInt || ((old_priv)&(~privilege_maskInt)) != old_priv) + update_bbf_schema_privilege(stmt->schema_name, "ALL", privilege_maskInt, old_priv, rolname, NULL, stmt->is_grant); } } return PLTSQL_RC_OK; @@ -3936,4 +3965,4 @@ exec_stmt_fulltextindex(PLtsql_execstate *estate, PLtsql_stmt_fulltextindex *stm */ exec_utility_cmd_helper(query_str); return PLTSQL_RC_OK; -} \ No newline at end of file +} diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index 10297b0c90e..306c7398e87 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3608,6 +3608,9 @@ bbf_ProcessUtility(PlannedStmt *pstmt, GrantStmt *grant = (GrantStmt *) parsetree; char *dbname = get_cur_db_name(); const char *current_user = GetUserNameFromId(GetUserId(), false); + int16 privilege_maskInt = create_privilege_bitmask(grant->privileges, false); + ListCell *lc1; + /* Ignore when GRANT statement has no specific named object. */ if (sql_dialect != SQL_DIALECT_TSQL || grant->targtype != ACL_TARGET_OBJECT) break; @@ -3623,7 +3626,6 @@ bbf_ProcessUtility(PlannedStmt *pstmt, const char *logical_schema = NULL; char *obj = rv->relname; ListCell *lc; - ListCell *lc1; const char *obj_type = "r"; if (rv->schemaname != NULL) logical_schema = get_logical_schema_name(rv->schemaname, true); @@ -3637,12 +3639,18 @@ bbf_ProcessUtility(PlannedStmt *pstmt, foreach(lc, grant->grantees) { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - int i = 0; - char *permissions[] = {"select", "insert", "update", "references", "delete"}; - for(i = 0; i < 5; i++) + if((rol_spec->rolename != NULL)) { - if ((rol_spec->rolename != NULL) && !check_bbf_schema_for_entry(logical_schema, obj, permissions[i], rol_spec->rolename)) - add_entry_to_bbf_schema(logical_schema, obj, permissions[i], rol_spec->rolename, obj_type); + if (!check_bbf_schema_for_entry(logical_schema, obj,rol_spec->rolename)) + { + add_entry_to_bbf_schema(logical_schema, obj, 31, rol_spec->rolename, obj_type); + } + else + { + int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); + if(old_priv!= 31 || (old_priv|(31)) != old_priv) + update_bbf_schema_privilege(logical_schema, obj, 31, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + } } } break; @@ -3652,15 +3660,17 @@ bbf_ProcessUtility(PlannedStmt *pstmt, foreach(lc, grant->grantees) { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - int i = 0; bool has_schema_perms = false; - char *permissions[] = {"select", "insert", "update", "references", "delete"}; - for(i = 0; i < 5; i++) + if((rol_spec->rolename != NULL)) { - if ((rol_spec->rolename != NULL) && check_bbf_schema_for_entry(logical_schema, "ALL", permissions[i], rol_spec->rolename) && !has_schema_perms) + if (check_bbf_schema_for_entry(logical_schema, "ALL", rol_spec->rolename) && !has_schema_perms) has_schema_perms = true; - if ((rol_spec->rolename != NULL) && check_bbf_schema_for_entry(logical_schema, obj, permissions[i], rol_spec->rolename)) - del_from_bbf_schema(logical_schema, obj, permissions[i], rol_spec->rolename); + if (check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) + { + int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); + if(old_priv!= 31 || ((old_priv)&(~(31))) != old_priv) + update_bbf_schema_privilege(logical_schema, obj, 31, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + } } if (has_schema_perms) return; @@ -3668,52 +3678,85 @@ bbf_ProcessUtility(PlannedStmt *pstmt, break; } } - foreach(lc1, grant->privileges) + if (grant->is_grant) { - AccessPriv *ap = (AccessPriv *) lfirst(lc1); - if (grant->is_grant) + /* + * 1. Execute the GRANT statement. + * 2. Add its corresponding entry in the catalog, if doesn't exist already. + * 3. Don't add an entry, if the permission is granted on column list. + */ + if (prev_ProcessUtility) + prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + queryEnv, dest, qc); + else + standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + queryEnv, dest, qc); + foreach(lc, grant->grantees) { - /* - * 1. Execute the GRANT statement. - * 2. Add its corresponding entry in the catalog, if doesn't exist already. - * 3. Don't add an entry, if the permission is granted on column list. - */ - if (prev_ProcessUtility) - prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, - queryEnv, dest, qc); - else - standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, - queryEnv, dest, qc); - foreach(lc, grant->grantees) + RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); + bool flag = false; + foreach(lc1, grant->privileges) { - RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - if ((ap->cols == NULL) && (rol_spec->rolename != NULL) && !check_bbf_schema_for_entry(logical_schema, obj, ap->priv_name, rol_spec->rolename)) - add_entry_to_bbf_schema(logical_schema, obj, ap->priv_name, rol_spec->rolename, obj_type); + AccessPriv *ap = (AccessPriv *) lfirst(lc1); + if(ap->cols != NULL) + { + flag = true; + break; + } + } + if(flag) + break; + if((rol_spec->rolename != NULL) && (strcmp(rol_spec->rolename, "public") != 0)) + { + if (!check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) + add_entry_to_bbf_schema(logical_schema, obj, privilege_maskInt, rol_spec->rolename, obj_type); + else + { + int16 old_priv = get_bbf_schema_privilege(logical_schema, obj, rol_spec->rolename); + if(old_priv!= privilege_maskInt || ((old_priv)|(privilege_maskInt)) != old_priv) + update_bbf_schema_privilege(logical_schema, obj, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + } } } - else + } + else + { + foreach(lc, grant->grantees) { - foreach(lc, grant->grantees) + RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); + bool flag = false; + /* + * 1. If GRANT on schema does not exist, execute REVOKE statement and remove the catalog entry if exists. + * 2. If GRANT on schema exist, only remove the entry from the catalog if exists. + */ + if ((logical_schema != NULL) && !check_bbf_schema_for_entry(logical_schema, "ALL", rol_spec->rolename)) { - RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - /* - * 1. If GRANT on schema does not exist, execute REVOKE statement and remove the catalog entry if exists. - * 2. If GRANT on schema exist, only remove the entry from the catalog if exists. - */ - if ((logical_schema != NULL) && (rol_spec->rolename != NULL) && !check_bbf_schema_for_entry(logical_schema, "ALL", ap->priv_name, rol_spec->rolename)) - { - if (prev_ProcessUtility) - prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + if (prev_ProcessUtility) + prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + queryEnv, dest, qc); + else + standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc); - else - standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, - queryEnv, dest, qc); + } + foreach(lc1, grant->privileges) + { + AccessPriv *ap = (AccessPriv *) lfirst(lc1); + if(ap->cols != NULL) + { + flag = true; + break; } - if ((ap->cols == NULL) && (rol_spec->rolename != NULL) && check_bbf_schema_for_entry(logical_schema, obj, ap->priv_name, rol_spec->rolename)) - del_from_bbf_schema(logical_schema, obj, ap->priv_name, rol_spec->rolename); + } + if(flag) + continue; + if ((rol_spec->rolename != NULL) && check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) + { + int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); + if(old_priv!= privilege_maskInt || ((old_priv)&(~(privilege_maskInt))) != old_priv) + update_bbf_schema_privilege(logical_schema, obj, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } } - } + } return; } } @@ -3721,7 +3764,6 @@ bbf_ProcessUtility(PlannedStmt *pstmt, { ObjectWithArgs *ob = (ObjectWithArgs *) linitial(grant->objects); ListCell *lc; - ListCell *lc1; const char *logicalschema = NULL; char *funcname = NULL; const char *obj_type = NULL; @@ -3749,8 +3791,10 @@ bbf_ProcessUtility(PlannedStmt *pstmt, */ if (pstmt->stmt_len == 0 && list_length(grant->privileges) == 0) { - if(check_bbf_schema_for_schema(logicalschema, "ALL", "execute")) + if(check_bbf_schema_for_schema(logicalschema, "ALL", PRIVILEGE_EXECUTE)) + { return; + } break; } /* If ALL PRIVILEGES is granted/revoked. */ @@ -3761,8 +3805,17 @@ bbf_ProcessUtility(PlannedStmt *pstmt, foreach(lc, grant->grantees) { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - if ((rol_spec->rolename != NULL) && !check_bbf_schema_for_entry(logicalschema, funcname, "execute", rol_spec->rolename)) - add_entry_to_bbf_schema(logicalschema, funcname, "execute", rol_spec->rolename, obj_type); + if((rol_spec->rolename != NULL)) + { + if (!check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) + add_entry_to_bbf_schema(logicalschema, funcname, 32, rol_spec->rolename, obj_type); + else + { + int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname, rol_spec->rolename); + if(old_priv!= 32 || ((old_priv)|(32)) != old_priv) + update_bbf_schema_privilege(logicalschema, funcname, 32, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + } + } } break; } @@ -3772,47 +3825,64 @@ bbf_ProcessUtility(PlannedStmt *pstmt, { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); bool has_schema_perms = false; - if ((rol_spec->rolename != NULL) && check_bbf_schema_for_entry(logicalschema, "ALL", "execute", rol_spec->rolename) && !has_schema_perms) - has_schema_perms = true; - if ((rol_spec->rolename != NULL) && check_bbf_schema_for_entry(logicalschema, funcname, "execute", rol_spec->rolename)) - del_from_bbf_schema(logicalschema, funcname, "execute", rol_spec->rolename); + if((rol_spec->rolename != NULL)) + { + if (check_bbf_schema_for_entry(logicalschema, "ALL", rol_spec->rolename) && !has_schema_perms) + has_schema_perms = true; + + if (check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) + { + int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname,rol_spec->rolename); + if(old_priv!= 32 || ((old_priv)&(~(32))) != old_priv) + update_bbf_schema_privilege(logicalschema, funcname, 32, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + } + } if (has_schema_perms) return; } break; } } - foreach(lc1, grant->privileges) + + if (grant->is_grant) { - AccessPriv *ap = (AccessPriv *) lfirst(lc1); - if (grant->is_grant) + /* Execute the GRANT statement. */ + if (prev_ProcessUtility) + prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + queryEnv, dest, qc); + else + standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + queryEnv, dest, qc); + /* Add entry to the catalog if it doesn't exist already. */ + foreach(lc, grant->grantees) { - /* Execute the GRANT statement. */ - if (prev_ProcessUtility) - prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, - queryEnv, dest, qc); - else - standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, - queryEnv, dest, qc); - /* Add entry to the catalog if it doesn't exist already. */ - foreach(lc, grant->grantees) + RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); + /* Don't store a row in catalog, if permission is granted for column */ + if ((rol_spec->rolename != NULL)) { - RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - /* Don't store a row in catalog, if permission is granted for column */ - if ((rol_spec->rolename != NULL) && !check_bbf_schema_for_entry(logicalschema, funcname, ap->priv_name, rol_spec->rolename)) - add_entry_to_bbf_schema(logicalschema, funcname, ap->priv_name, rol_spec->rolename, obj_type); + if (!check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) + add_entry_to_bbf_schema(logicalschema, funcname, privilege_maskInt, rol_spec->rolename, obj_type); + else + { + int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname, rol_spec->rolename); + if(old_priv!= privilege_maskInt || ((old_priv)|(privilege_maskInt)) != old_priv) + update_bbf_schema_privilege(logicalschema, funcname, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + } } } - else + } + else + { + foreach(lc, grant->grantees) { - foreach(lc, grant->grantees) + RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); + /* + * 1. If GRANT on schema does not exist, execute REVOKE statement and remove the catalog entry if exists. + * 2. If GRANT on schema exist, only remove the entry from the catalog if exists. + */ + if ((rol_spec->rolename != NULL)) { - RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - /* - * 1. If GRANT on schema does not exist, execute REVOKE statement and remove the catalog entry if exists. - * 2. If GRANT on schema exist, only remove the entry from the catalog if exists. - */ - if ((rol_spec->rolename != NULL) && !check_bbf_schema_for_entry(logicalschema, "ALL", ap->priv_name, rol_spec->rolename)) + if (!check_bbf_schema_for_entry(logicalschema, "ALL", rol_spec->rolename)) { /* Execute REVOKE statement. */ if (prev_ProcessUtility) @@ -3822,8 +3892,12 @@ bbf_ProcessUtility(PlannedStmt *pstmt, standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc); } - if ((rol_spec->rolename != NULL) && check_bbf_schema_for_entry(logicalschema, funcname, ap->priv_name, rol_spec->rolename)) - del_from_bbf_schema(logicalschema, funcname, ap->priv_name, rol_spec->rolename); + if (check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) + { + int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname, rol_spec->rolename); + if(old_priv!= privilege_maskInt || ((old_priv)&(~(privilege_maskInt))) != old_priv) + update_bbf_schema_privilege(logicalschema, funcname, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + } } } } diff --git a/contrib/babelfishpg_tsql/src/pltsql.h b/contrib/babelfishpg_tsql/src/pltsql.h index ae94b0ddf16..169316e8ae3 100644 --- a/contrib/babelfishpg_tsql/src/pltsql.h +++ b/contrib/babelfishpg_tsql/src/pltsql.h @@ -1914,6 +1914,14 @@ extern int insert_bulk_rows_per_batch; extern int insert_bulk_kilobytes_per_batch; extern bool insert_bulk_keep_nulls; +/* Privilege Bits for GRANT SCHEMA */ +#define PRIVILEGE_EXECUTE 32 +#define PRIVILEGE_SELECT 16 +#define PRIVILEGE_INSERT 8 +#define PRIVILEGE_UPDATE 4 +#define PRIVILEGE_DELETE 2 +#define PRIVILEGE_REFERENCES 1 + /********************************************************************** * Function declarations **********************************************************************/ @@ -2119,6 +2127,7 @@ extern bool pltsql_createFunction(ParseState *pstate, PlannedStmt *pstmt, const ParamListInfo params); extern Oid get_sys_varcharoid(void); extern Oid get_sysadmin_oid(void); +extern int16 create_privilege_bitmask(const List *l, bool grant_schema_stmt); typedef struct { diff --git a/contrib/babelfishpg_tsql/src/pltsql_utils.c b/contrib/babelfishpg_tsql/src/pltsql_utils.c index df3c57df719..a393d5b50cf 100644 --- a/contrib/babelfishpg_tsql/src/pltsql_utils.c +++ b/contrib/babelfishpg_tsql/src/pltsql_utils.c @@ -1036,7 +1036,6 @@ update_GrantStmt(Node *n, const char *object, const char *obj_schema, const char if (grantee && stmt->grantees) { RoleSpec *tmp = (RoleSpec *) llast(stmt->grantees); - tmp->rolename = pstrdup(grantee); } @@ -1996,3 +1995,35 @@ char appendStringInfo(&query, "\"%s\".\"%s\"", schema_name, index_name); return query.data; } + +/* Creates integer bitmask for permissions to be referenced in the catalog. */ +int16 +create_privilege_bitmask(const List *l, bool grant_schema_stmt) +{ + int16 privilege_maskInt = 0; + ListCell *lc; + foreach(lc, l) + { + char *priv_name; + if (grant_schema_stmt) + priv_name = (char *) lfirst(lc); + else + { + AccessPriv *ap = (AccessPriv *) lfirst(lc); + priv_name = ap->priv_name; + } + if (!strcmp(priv_name,"execute")) + privilege_maskInt |= PRIVILEGE_EXECUTE; + else if (!strcmp(priv_name,"select")) + privilege_maskInt |= PRIVILEGE_SELECT; + else if (!strcmp(priv_name,"insert")) + privilege_maskInt |= PRIVILEGE_INSERT; + else if (!strcmp(priv_name,"update")) + privilege_maskInt |= PRIVILEGE_UPDATE; + else if (!strcmp(priv_name,"delete")) + privilege_maskInt |= PRIVILEGE_DELETE; + else if (!strcmp(priv_name,"references")) + privilege_maskInt |= PRIVILEGE_REFERENCES; + } + return privilege_maskInt; +} diff --git a/test/JDBC/expected/GRANT_SCHEMA.out b/test/JDBC/expected/GRANT_SCHEMA.out index 1891d685978..bd1d12663bd 100644 --- a/test/JDBC/expected/GRANT_SCHEMA.out +++ b/test/JDBC/expected/GRANT_SCHEMA.out @@ -242,7 +242,7 @@ grant select on schema::babel_4344_s1 to babel_4344_u1; -- should fail go ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: Cannot find the schema "babel_4344_s1", because it does not exist or you do not have permission.)~~ +~~ERROR (Message: Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself.)~~ use master; go From e05f06ffe29e427652cd48500a2fd9463cda0be7 Mon Sep 17 00:00:00 2001 From: Shalini Lohia Date: Tue, 21 Nov 2023 12:20:49 +0000 Subject: [PATCH 2/5] Define macros --- contrib/babelfishpg_tsql/src/catalog.c | 2 +- contrib/babelfishpg_tsql/src/pl_exec-2.c | 14 +-- contrib/babelfishpg_tsql/src/pl_handler.c | 135 +++++++++------------- contrib/babelfishpg_tsql/src/pltsql.h | 1 + 4 files changed, 63 insertions(+), 89 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 84aaf3cb5f9..93e89ebe43b 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -3182,7 +3182,7 @@ del_from_bbf_schema(const char *schema_name, CStringGetDatum(grantee)); scan = systable_beginscan(bbf_schema_rel, get_bbf_schema_perms_idx_oid(), - true, NULL, 5, scanKey); + true, NULL, 4, scanKey); tuple_bbf_schema = systable_getnext(scan); diff --git a/contrib/babelfishpg_tsql/src/pl_exec-2.c b/contrib/babelfishpg_tsql/src/pl_exec-2.c index 58640730ff6..0285b191c9a 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec-2.c +++ b/contrib/babelfishpg_tsql/src/pl_exec-2.c @@ -3789,22 +3789,22 @@ exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt) exec_gen_grantschema(schema_name, rolname, stmt, "references"); /* Add entry for each grant statement. */ - if (stmt->is_grant && !check_bbf_schema_for_entry(stmt->schema_name, "ALL", rolname)) - add_entry_to_bbf_schema(stmt->schema_name, "ALL", privilege_maskInt, rolname, NULL); + if (stmt->is_grant && !check_bbf_schema_for_entry(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname)) + add_entry_to_bbf_schema(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, privilege_maskInt, rolname, NULL); else if(stmt->is_grant) { - int16 old_priv = get_bbf_schema_privilege(stmt->schema_name, "ALL", rolname); + int16 old_priv = get_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname); if(old_priv!= privilege_maskInt || ((old_priv|privilege_maskInt) != old_priv)) - update_bbf_schema_privilege(stmt->schema_name, "ALL", privilege_maskInt, old_priv, rolname, NULL, stmt->is_grant); + update_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, privilege_maskInt, old_priv, rolname, NULL, stmt->is_grant); } /* Remove entry for each revoke statement. */ - else if (!stmt->is_grant && check_bbf_schema_for_entry(stmt->schema_name, "ALL", rolname)) + else if (!stmt->is_grant && check_bbf_schema_for_entry(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname)) { /* If any object in the schema has the OBJECT level permission. Then, internally grant that permission back. */ grant_perms_to_objects_in_schema(stmt->schema_name, privilege_maskInt, rolname); - old_priv = get_bbf_schema_privilege(stmt->schema_name, "ALL", rolname); + old_priv = get_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname); if(old_priv!= privilege_maskInt || ((old_priv)&(~privilege_maskInt)) != old_priv) - update_bbf_schema_privilege(stmt->schema_name, "ALL", privilege_maskInt, old_priv, rolname, NULL, stmt->is_grant); + update_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, privilege_maskInt, old_priv, rolname, NULL, stmt->is_grant); } pfree(rolname); } diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index 5bd1a0d4123..e5463c61a94 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3639,18 +3639,15 @@ bbf_ProcessUtility(PlannedStmt *pstmt, foreach(lc, grant->grantees) { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - if((rol_spec->rolename != NULL)) + if (!check_bbf_schema_for_entry(logical_schema, obj,rol_spec->rolename)) { - if (!check_bbf_schema_for_entry(logical_schema, obj,rol_spec->rolename)) - { - add_entry_to_bbf_schema(logical_schema, obj, 31, rol_spec->rolename, obj_type); - } - else - { - int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); - if(old_priv!= 31 || (old_priv|(31)) != old_priv) - update_bbf_schema_privilege(logical_schema, obj, 31, old_priv, rol_spec->rolename, obj_type, grant->is_grant); - } + add_entry_to_bbf_schema(logical_schema, obj, ALL_PRIVILEGE_EXCEPT_EXECUTE, rol_spec->rolename, obj_type); + } + else + { + int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); + if(old_priv!= ALL_PRIVILEGE_EXCEPT_EXECUTE || (old_priv|(ALL_PRIVILEGE_EXCEPT_EXECUTE)) != old_priv) + update_bbf_schema_privilege(logical_schema, obj, ALL_PRIVILEGE_EXCEPT_EXECUTE, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } } break; @@ -3661,16 +3658,13 @@ bbf_ProcessUtility(PlannedStmt *pstmt, { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); bool has_schema_perms = false; - if((rol_spec->rolename != NULL)) + if (check_bbf_schema_for_entry(logical_schema, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rol_spec->rolename) && !has_schema_perms) + has_schema_perms = true; + if (check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) { - if (check_bbf_schema_for_entry(logical_schema, "ALL", rol_spec->rolename) && !has_schema_perms) - has_schema_perms = true; - if (check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) - { - int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); - if(old_priv!= 31 || ((old_priv)&(~(31))) != old_priv) - update_bbf_schema_privilege(logical_schema, obj, 31, old_priv, rol_spec->rolename, obj_type, grant->is_grant); - } + int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); + if(old_priv!= ALL_PRIVILEGE_EXCEPT_EXECUTE || ((old_priv)&(~(ALL_PRIVILEGE_EXCEPT_EXECUTE))) != old_priv) + update_bbf_schema_privilege(logical_schema, obj, ALL_PRIVILEGE_EXCEPT_EXECUTE, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } if (has_schema_perms) return; @@ -3706,16 +3700,13 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } if(flag) break; - if((rol_spec->rolename != NULL) && (strcmp(rol_spec->rolename, "public") != 0)) + if (!check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) + add_entry_to_bbf_schema(logical_schema, obj, privilege_maskInt, rol_spec->rolename, obj_type); + else { - if (!check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) - add_entry_to_bbf_schema(logical_schema, obj, privilege_maskInt, rol_spec->rolename, obj_type); - else - { - int16 old_priv = get_bbf_schema_privilege(logical_schema, obj, rol_spec->rolename); - if(old_priv!= privilege_maskInt || ((old_priv)|(privilege_maskInt)) != old_priv) - update_bbf_schema_privilege(logical_schema, obj, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); - } + int16 old_priv = get_bbf_schema_privilege(logical_schema, obj, rol_spec->rolename); + if(old_priv!= privilege_maskInt || ((old_priv)|(privilege_maskInt)) != old_priv) + update_bbf_schema_privilege(logical_schema, obj, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } } } @@ -3729,7 +3720,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, * 1. If GRANT on schema does not exist, execute REVOKE statement and remove the catalog entry if exists. * 2. If GRANT on schema exist, only remove the entry from the catalog if exists. */ - if ((logical_schema != NULL) && !check_bbf_schema_for_entry(logical_schema, "ALL", rol_spec->rolename)) + if ((logical_schema != NULL) && !check_bbf_schema_for_entry(logical_schema, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rol_spec->rolename)) { if (prev_ProcessUtility) prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, @@ -3749,7 +3740,7 @@ bbf_ProcessUtility(PlannedStmt *pstmt, } if(flag) continue; - if ((rol_spec->rolename != NULL) && check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) + if (check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) { int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); if(old_priv!= privilege_maskInt || ((old_priv)&(~(privilege_maskInt))) != old_priv) @@ -3803,16 +3794,13 @@ bbf_ProcessUtility(PlannedStmt *pstmt, foreach(lc, grant->grantees) { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - if((rol_spec->rolename != NULL)) + if (!check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) + add_entry_to_bbf_schema(logicalschema, funcname, 32, rol_spec->rolename, obj_type); + else { - if (!check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) - add_entry_to_bbf_schema(logicalschema, funcname, 32, rol_spec->rolename, obj_type); - else - { - int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname, rol_spec->rolename); - if(old_priv!= 32 || ((old_priv)|(32)) != old_priv) - update_bbf_schema_privilege(logicalschema, funcname, 32, old_priv, rol_spec->rolename, obj_type, grant->is_grant); - } + int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname, rol_spec->rolename); + if(old_priv!= 32 || ((old_priv)|(32)) != old_priv) + update_bbf_schema_privilege(logicalschema, funcname, 32, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } } } @@ -3822,17 +3810,14 @@ bbf_ProcessUtility(PlannedStmt *pstmt, { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); bool has_schema_perms = false; - if((rol_spec->rolename != NULL)) - { - if (check_bbf_schema_for_entry(logicalschema, "ALL", rol_spec->rolename) && !has_schema_perms) - has_schema_perms = true; + if (check_bbf_schema_for_entry(logicalschema, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rol_spec->rolename) && !has_schema_perms) + has_schema_perms = true; - if (check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) - { - int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname,rol_spec->rolename); - if(old_priv!= 32 || ((old_priv)&(~(32))) != old_priv) - update_bbf_schema_privilege(logicalschema, funcname, 32, old_priv, rol_spec->rolename, obj_type, grant->is_grant); - } + if (check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) + { + int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname,rol_spec->rolename); + if(old_priv!= 32 || ((old_priv)&(~(32))) != old_priv) + update_bbf_schema_privilege(logicalschema, funcname, 32, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } if (has_schema_perms) return; @@ -3854,17 +3839,13 @@ bbf_ProcessUtility(PlannedStmt *pstmt, foreach(lc, grant->grantees) { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - /* Don't store a row in catalog, if permission is granted for column */ - if ((rol_spec->rolename != NULL)) + if (!check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) + add_entry_to_bbf_schema(logicalschema, funcname, privilege_maskInt, rol_spec->rolename, obj_type); + else { - if (!check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) - add_entry_to_bbf_schema(logicalschema, funcname, privilege_maskInt, rol_spec->rolename, obj_type); - else - { - int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname, rol_spec->rolename); - if(old_priv!= privilege_maskInt || ((old_priv)|(privilege_maskInt)) != old_priv) - update_bbf_schema_privilege(logicalschema, funcname, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); - } + int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname, rol_spec->rolename); + if(old_priv!= privilege_maskInt || ((old_priv)|(privilege_maskInt)) != old_priv) + update_bbf_schema_privilege(logicalschema, funcname, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } } } @@ -3877,29 +3858,21 @@ bbf_ProcessUtility(PlannedStmt *pstmt, * 1. If GRANT on schema does not exist, execute REVOKE statement and remove the catalog entry if exists. * 2. If GRANT on schema exist, only remove the entry from the catalog if exists. */ - if ((rol_spec->rolename != NULL)) + if (!check_bbf_schema_for_entry(logicalschema, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rol_spec->rolename)) { - RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - /* - * 1. If GRANT on schema does not exist, execute REVOKE statement and remove the catalog entry if exists. - * 2. If GRANT on schema exist, only remove the entry from the catalog if exists. - */ - if (!check_bbf_schema_for_entry(logicalschema, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rol_spec->rolename)) - { - /* Execute REVOKE statement. */ - if (prev_ProcessUtility) - prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + /* Execute REVOKE statement. */ + if (prev_ProcessUtility) + prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + queryEnv, dest, qc); + else + standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc); - else - standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, - queryEnv, dest, qc); - } - if (check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) - { - int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname, rol_spec->rolename); - if(old_priv!= privilege_maskInt || ((old_priv)&(~(privilege_maskInt))) != old_priv) - update_bbf_schema_privilege(logicalschema, funcname, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); - } + } + if (check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) + { + int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname, rol_spec->rolename); + if(old_priv!= privilege_maskInt || ((old_priv)&(~(privilege_maskInt))) != old_priv) + update_bbf_schema_privilege(logicalschema, funcname, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } } } diff --git a/contrib/babelfishpg_tsql/src/pltsql.h b/contrib/babelfishpg_tsql/src/pltsql.h index 64116605ba5..be7bb071bc1 100644 --- a/contrib/babelfishpg_tsql/src/pltsql.h +++ b/contrib/babelfishpg_tsql/src/pltsql.h @@ -1916,6 +1916,7 @@ extern bool insert_bulk_keep_nulls; /* Privilege Bits for GRANT SCHEMA */ #define PRIVILEGE_BIT_FOR_EXECUTE 32 +#define ALL_PRIVILEGE_EXCEPT_EXECUTE 31 #define PRIVILEGE_BIT_FOR_SELECT 16 #define PRIVILEGE_BIT_FOR_INSERT 8 #define PRIVILEGE_BIT_FOR_UPDATE 4 From b40b2f2017f0d81598650083fc43e89a0adf7527 Mon Sep 17 00:00:00 2001 From: Shalini Lohia Date: Tue, 21 Nov 2023 12:50:56 +0000 Subject: [PATCH 3/5] Fix tests --- contrib/babelfishpg_tsql/src/catalog.c | 65 ++++++++++++++++-------- contrib/babelfishpg_tsql/src/pl_exec-2.c | 4 +- test/JDBC/expected/GRANT_SCHEMA.out | 8 ++- 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 93e89ebe43b..7f39b4324b6 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -2890,39 +2890,51 @@ get_bbf_schema_privilege(const char *schema_name, { Relation bbf_schema_rel; HeapTuple tuple_bbf_schema; - ScanKeyData key[4]; - TableScanDesc scan; + ScanKeyData scanKey[4]; + SysScanDesc scan; int16 dbid = get_cur_db_id(); int16 permission = 0; bbf_schema_rel = table_open(get_bbf_schema_perms_oid(), AccessShareLock); - ScanKeyInit(&key[0], + ScanKeyInit(&scanKey[0], Anum_bbf_schema_perms_dbid, BTEqualStrategyNumber, F_INT2EQ, Int16GetDatum(dbid)); - ScanKeyInit(&key[1], + ScanKeyEntryInitialize(&scanKey[1], 0, Anum_bbf_schema_perms_schema_name, - BTEqualStrategyNumber, F_NAMEEQ, + BTEqualStrategyNumber, + InvalidOid, + tsql_get_server_collation_oid_internal(false), + F_NAMEEQ, CStringGetDatum(schema_name)); - ScanKeyInit(&key[2], + ScanKeyEntryInitialize(&scanKey[2], 0, Anum_bbf_schema_perms_object_name, - BTEqualStrategyNumber, F_NAMEEQ, + BTEqualStrategyNumber, + InvalidOid, + tsql_get_server_collation_oid_internal(false), + F_NAMEEQ, CStringGetDatum(object_name)); - ScanKeyInit(&key[3], + ScanKeyEntryInitialize(&scanKey[3], 0, Anum_bbf_schema_perms_grantee, - BTEqualStrategyNumber, F_NAMEEQ, + BTEqualStrategyNumber, + InvalidOid, + tsql_get_server_collation_oid_internal(false), + F_NAMEEQ, CStringGetDatum(grantee)); - scan = table_beginscan_catalog(bbf_schema_rel, 4, key); - tuple_bbf_schema = heap_getnext(scan, ForwardScanDirection); + scan = systable_beginscan(bbf_schema_rel, + get_bbf_schema_perms_idx_oid(), + true, NULL, 4, scanKey); + tuple_bbf_schema = systable_getnext(scan); + if (HeapTupleIsValid(tuple_bbf_schema)) { Form_bbf_schema_perms bbf_schema = (Form_bbf_schema_perms) GETSTRUCT(tuple_bbf_schema); permission = bbf_schema->permission; } - table_endscan(scan); + systable_endscan(scan); table_close(bbf_schema_rel, AccessShareLock); return permission; } @@ -2943,7 +2955,7 @@ update_bbf_schema_privilege(const char *schema_name, HeapTuple tuple_bbf_schema; TupleDesc bbf_schema_dsc; HeapTuple new_tuple; - ScanKeyData key[5]; + ScanKeyData scanKey[5]; TableScanDesc scan; int16 dbid = get_cur_db_id(); int16 permission = 0; @@ -2975,28 +2987,37 @@ update_bbf_schema_privilege(const char *schema_name, bbf_schema_rel = table_open(get_bbf_schema_perms_oid(), RowExclusiveLock); - ScanKeyInit(&key[0], + ScanKeyInit(&scanKey[0], Anum_bbf_schema_perms_dbid, BTEqualStrategyNumber, F_INT2EQ, Int16GetDatum(dbid)); - ScanKeyInit(&key[1], + ScanKeyEntryInitialize(&scanKey[1], 0, Anum_bbf_schema_perms_schema_name, - BTEqualStrategyNumber, F_NAMEEQ, + BTEqualStrategyNumber, + InvalidOid, + tsql_get_server_collation_oid_internal(false), + F_NAMEEQ, CStringGetDatum(schema_name)); - ScanKeyInit(&key[2], + ScanKeyEntryInitialize(&scanKey[2], 0, Anum_bbf_schema_perms_object_name, - BTEqualStrategyNumber, F_NAMEEQ, + BTEqualStrategyNumber, + InvalidOid, + tsql_get_server_collation_oid_internal(false), + F_NAMEEQ, CStringGetDatum(object_name)); - ScanKeyInit(&key[3], + ScanKeyInit(&scanKey[3], Anum_bbf_schema_perms_permission, BTEqualStrategyNumber, F_INT2EQ, Int16GetDatum(old_priv)); - ScanKeyInit(&key[4], + ScanKeyEntryInitialize(&scanKey[4], 0, Anum_bbf_schema_perms_grantee, - BTEqualStrategyNumber, F_NAMEEQ, + BTEqualStrategyNumber, + InvalidOid, + tsql_get_server_collation_oid_internal(false), + F_NAMEEQ, CStringGetDatum(grantee)); - scan = table_beginscan_catalog(bbf_schema_rel, 5, key); + scan = table_beginscan_catalog(bbf_schema_rel, 5, scanKey); tuple_bbf_schema = heap_getnext(scan, ForwardScanDirection); if (HeapTupleIsValid(tuple_bbf_schema)) { diff --git a/contrib/babelfishpg_tsql/src/pl_exec-2.c b/contrib/babelfishpg_tsql/src/pl_exec-2.c index 0285b191c9a..f9252bf5938 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec-2.c +++ b/contrib/babelfishpg_tsql/src/pl_exec-2.c @@ -3722,7 +3722,7 @@ exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt) ListCell *lc; Oid schemaOid; int16 privilege_maskInt = create_privilege_bitmask(stmt->privileges, true); - char *user = GetUserNameFromId(GetUserId(), false); + char *user = GetUserNameFromId(GetUserId(), false); /* * If the login is not the db owner or the login is not the member of @@ -3751,14 +3751,12 @@ exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt) foreach(lc, stmt->grantees) { char *grantee_name = (char *) lfirst(lc); - char *user = GetUserNameFromId(GetUserId(), false); Oid role_oid; int16 old_priv = 0; if (strcmp(grantee_name, "public") != 0) rolname = get_physical_user_name(dbname, grantee_name); else rolname = pstrdup("public"); - //rolname = get_physical_user_name(dbname, grantee_name); role_oid = get_role_oid(rolname, true); if (strcmp(grantee_name, "public") != 0 && role_oid == InvalidOid) diff --git a/test/JDBC/expected/GRANT_SCHEMA.out b/test/JDBC/expected/GRANT_SCHEMA.out index 935acbe2f53..9e87407783a 100644 --- a/test/JDBC/expected/GRANT_SCHEMA.out +++ b/test/JDBC/expected/GRANT_SCHEMA.out @@ -372,10 +372,8 @@ select schema_name, object_name, permission, grantee from sys.babelfish_schema_p where schema_name = 'babel_4344_s1' collate "C" and object_name = 'ALL' collate "C" order by permission; go ~~START~~ -name#!#name#!#name#!#name -babel_4344_s1#!#ALL#!#execute#!#babel_4344_d1_babel_4344_u1 -babel_4344_s1#!#ALL#!#insert#!#babel_4344_d1_babel_4344_u1 -babel_4344_s1#!#ALL#!#select#!#babel_4344_d1_babel_4344_u1 +name#!#name#!#int2#!#name +babel_4344_s1#!#ALL#!#56#!#babel_4344_d1_babel_4344_u1 ~~END~~ @@ -626,7 +624,7 @@ go select * from sys.babelfish_schema_permissions where schema_name = 'babel_4344_s1' collate sys.database_default; go ~~START~~ -int2#!#name#!#name#!#name#!#name#!#name +int2#!#name#!#name#!#int2#!#name#!#name ~~END~~ From a9bbf12734da416f0ad5b58308c8c858fa9c6761 Mon Sep 17 00:00:00 2001 From: Shalini Lohia Date: Tue, 21 Nov 2023 14:07:53 +0000 Subject: [PATCH 4/5] Add a comment --- contrib/babelfishpg_tsql/src/catalog.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 7f39b4324b6..16909df5377 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -3283,12 +3283,6 @@ clean_up_bbf_schema(const char *schema_name, table_close(bbf_schema_rel, RowExclusiveLock); } -/* - * For all objects belonging to a schema which has OBJECT level permission, - * It grants the permission explicitly when REVOKE has been executed on that - * specific schema. - */ - void grant_perms_to_each_obj(const char *db_name, const char *object_type, @@ -3340,6 +3334,13 @@ grant_perms_to_each_obj(const char *db_name, pfree(query.data); } + +/* + * For all objects belonging to a schema which has OBJECT level permission, + * It grants the permission explicitly when REVOKE has been executed on that + * specific schema. + */ + void grant_perms_to_objects_in_schema(const char *schema_name, int16 priv, @@ -3389,7 +3390,7 @@ grant_perms_to_objects_in_schema(const char *schema_name, object_type = pstrdup(NameStr(schemaform->object_type)); permission = (priv & (schemaform->permission)); /* For each object, grant the permission explicitly. */ - if (strcmp(object_name, "ALL") != 0) + if (strcmp(object_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA) != 0) { if((permission & PRIVILEGE_BIT_FOR_EXECUTE) == PRIVILEGE_BIT_FOR_EXECUTE) grant_perms_to_each_obj(db_name, object_type, schema_name, object_name, grantee, "execute"); From 119a217781a44ce7912e9ca14d360e39f3dfebdf Mon Sep 17 00:00:00 2001 From: Shalini Lohia Date: Tue, 21 Nov 2023 20:22:18 +0000 Subject: [PATCH 5/5] Removed unnecessary checks --- contrib/babelfishpg_tsql/sql/ownership.sql | 2 +- .../babelfishpg_tsql--3.3.0--3.4.0.sql | 2 +- contrib/babelfishpg_tsql/src/catalog.c | 17 +- contrib/babelfishpg_tsql/src/pl_exec-2.c | 37 +-- contrib/babelfishpg_tsql/src/pl_handler.c | 216 +++++++++--------- 5 files changed, 139 insertions(+), 135 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/ownership.sql b/contrib/babelfishpg_tsql/sql/ownership.sql index 1b0af43e697..a5e831a41a2 100644 --- a/contrib/babelfishpg_tsql/sql/ownership.sql +++ b/contrib/babelfishpg_tsql/sql/ownership.sql @@ -19,7 +19,7 @@ CREATE TABLE sys.babelfish_schema_permissions ( dbid smallint NOT NULL, schema_name NAME NOT NULL COLLATE sys.database_default, object_name NAME NOT NULL COLLATE sys.database_default, - permission SMALLINT, + permission SMALLINT NOT NULL, grantee NAME NOT NULL COLLATE sys.database_default, object_type NAME COLLATE sys.database_default, PRIMARY KEY(dbid, schema_name, object_name, grantee) diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql index 0f33dff48b0..d80b44411a8 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql @@ -894,7 +894,7 @@ CREATE TABLE IF NOT EXISTS sys.babelfish_schema_permissions ( dbid smallint NOT NULL, schema_name NAME NOT NULL COLLATE sys.database_default, object_name NAME NOT NULL COLLATE sys.database_default, - permission SMALLINT, + permission SMALLINT NOT NULL, grantee NAME NOT NULL COLLATE sys.database_default, object_type NAME COLLATE sys.database_default, PRIMARY KEY(dbid, schema_name, object_name, grantee) diff --git a/contrib/babelfishpg_tsql/src/catalog.c b/contrib/babelfishpg_tsql/src/catalog.c index 16909df5377..53f713d8ca6 100644 --- a/contrib/babelfishpg_tsql/src/catalog.c +++ b/contrib/babelfishpg_tsql/src/catalog.c @@ -3042,8 +3042,6 @@ update_bbf_schema_privilege(const char *schema_name, table_endscan(scan); table_close(bbf_schema_rel, RowExclusiveLock); - - CommandCounterIncrement(); } /* Check if the catalog entry exists. */ @@ -3113,10 +3111,11 @@ check_bbf_schema_for_schema(const char *schema_name, { Relation bbf_schema_rel; HeapTuple tuple_bbf_schema; - ScanKeyData key[3]; - SysScanDesc scan; - int16 dbid = get_cur_db_id(); - int16 priv = 0; + ScanKeyData key[3]; + SysScanDesc scan; + int16 dbid = get_cur_db_id(); + int16 priv = 0; + bool permission_exists_on_schema = false; bbf_schema_rel = table_open(get_bbf_schema_perms_oid(), AccessShareLock); @@ -3144,19 +3143,19 @@ check_bbf_schema_for_schema(const char *schema_name, true, NULL, 3, key); tuple_bbf_schema = systable_getnext(scan); - while (HeapTupleIsValid(tuple_bbf_schema)) + if (HeapTupleIsValid(tuple_bbf_schema)) { Form_bbf_schema_perms schemaform; schemaform = (Form_bbf_schema_perms) GETSTRUCT(tuple_bbf_schema); priv = schemaform->permission; if((permission & priv) == permission) - return true; + permission_exists_on_schema = true; } systable_endscan(scan); table_close(bbf_schema_rel, AccessShareLock); - return false; + return permission_exists_on_schema; } void diff --git a/contrib/babelfishpg_tsql/src/pl_exec-2.c b/contrib/babelfishpg_tsql/src/pl_exec-2.c index f9252bf5938..3d051c30e0b 100644 --- a/contrib/babelfishpg_tsql/src/pl_exec-2.c +++ b/contrib/babelfishpg_tsql/src/pl_exec-2.c @@ -3786,23 +3786,32 @@ exec_stmt_grantschema(PLtsql_execstate *estate, PLtsql_stmt_grantschema *stmt) if((privilege_maskInt & PRIVILEGE_BIT_FOR_REFERENCES) == PRIVILEGE_BIT_FOR_REFERENCES) exec_gen_grantschema(schema_name, rolname, stmt, "references"); - /* Add entry for each grant statement. */ - if (stmt->is_grant && !check_bbf_schema_for_entry(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname)) - add_entry_to_bbf_schema(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, privilege_maskInt, rolname, NULL); - else if(stmt->is_grant) + /* Add/update an entry for a GRANT Statement. */ + if (stmt->is_grant) { - int16 old_priv = get_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname); - if(old_priv!= privilege_maskInt || ((old_priv|privilege_maskInt) != old_priv)) - update_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, privilege_maskInt, old_priv, rolname, NULL, stmt->is_grant); + /* Add an entry if it doesn't exist already. */ + if (!check_bbf_schema_for_entry(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname)) + add_entry_to_bbf_schema(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, privilege_maskInt, rolname, NULL); + else + { + /* Update the entry if it exists already. */ + int16 old_priv = get_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname); + if(old_priv!= privilege_maskInt || ((old_priv|privilege_maskInt) != old_priv)) + update_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, privilege_maskInt, old_priv, rolname, NULL, stmt->is_grant); + } } - /* Remove entry for each revoke statement. */ - else if (!stmt->is_grant && check_bbf_schema_for_entry(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname)) + /* Either update the entry or do nothing for REVOKE Statement. */ + else { - /* If any object in the schema has the OBJECT level permission. Then, internally grant that permission back. */ - grant_perms_to_objects_in_schema(stmt->schema_name, privilege_maskInt, rolname); - old_priv = get_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname); - if(old_priv!= privilege_maskInt || ((old_priv)&(~privilege_maskInt)) != old_priv) - update_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, privilege_maskInt, old_priv, rolname, NULL, stmt->is_grant); + /* Update the entry if it exists already. Otherwise, do nothing. */ + if (check_bbf_schema_for_entry(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname)) + { + /* If any object in the schema has the OBJECT level permission. Then, internally grant that permission back. */ + grant_perms_to_objects_in_schema(stmt->schema_name, privilege_maskInt, rolname); + old_priv = get_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rolname); + if(old_priv!= privilege_maskInt || ((old_priv)&(~privilege_maskInt)) != old_priv) + update_bbf_schema_privilege(stmt->schema_name, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, privilege_maskInt, old_priv, rolname, NULL, stmt->is_grant); + } } pfree(rolname); } diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index e5463c61a94..4c4369e6bfd 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -3619,137 +3619,133 @@ bbf_ProcessUtility(PlannedStmt *pstmt, break; else if (grant->objtype == OBJECT_TABLE) { - /* Ignore CREATE database subcommands */ - if (strcmp("(CREATE LOGICAL DATABASE )", queryString) != 0) + RangeVar *rv = (RangeVar *) linitial(grant->objects); + const char *logical_schema = NULL; + char *obj = rv->relname; + ListCell *lc; + const char *obj_type = "r"; + if (rv->schemaname != NULL) + logical_schema = get_logical_schema_name(rv->schemaname, true); + else + logical_schema = get_authid_user_ext_schema_name(dbname, current_user); + /* If ALL PRIVILEGES is granted/revoked. */ + if (list_length(grant->privileges) == 0) { - RangeVar *rv = (RangeVar *) linitial(grant->objects); - const char *logical_schema = NULL; - char *obj = rv->relname; - ListCell *lc; - const char *obj_type = "r"; - if (rv->schemaname != NULL) - logical_schema = get_logical_schema_name(rv->schemaname, true); - else - logical_schema = get_authid_user_ext_schema_name(dbname, current_user); - /* If ALL PRIVILEGES is granted/revoked. */ - if (list_length(grant->privileges) == 0) - { - if (grant->is_grant) - { - foreach(lc, grant->grantees) - { - RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - if (!check_bbf_schema_for_entry(logical_schema, obj,rol_spec->rolename)) - { - add_entry_to_bbf_schema(logical_schema, obj, ALL_PRIVILEGE_EXCEPT_EXECUTE, rol_spec->rolename, obj_type); - } - else - { - int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); - if(old_priv!= ALL_PRIVILEGE_EXCEPT_EXECUTE || (old_priv|(ALL_PRIVILEGE_EXCEPT_EXECUTE)) != old_priv) - update_bbf_schema_privilege(logical_schema, obj, ALL_PRIVILEGE_EXCEPT_EXECUTE, old_priv, rol_spec->rolename, obj_type, grant->is_grant); - } - } - break; - } - else - { - foreach(lc, grant->grantees) - { - RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - bool has_schema_perms = false; - if (check_bbf_schema_for_entry(logical_schema, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rol_spec->rolename) && !has_schema_perms) - has_schema_perms = true; - if (check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) - { - int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); - if(old_priv!= ALL_PRIVILEGE_EXCEPT_EXECUTE || ((old_priv)&(~(ALL_PRIVILEGE_EXCEPT_EXECUTE))) != old_priv) - update_bbf_schema_privilege(logical_schema, obj, ALL_PRIVILEGE_EXCEPT_EXECUTE, old_priv, rol_spec->rolename, obj_type, grant->is_grant); - } - if (has_schema_perms) - return; - } - break; - } - } if (grant->is_grant) { - /* - * 1. Execute the GRANT statement. - * 2. Add its corresponding entry in the catalog, if doesn't exist already. - * 3. Don't add an entry, if the permission is granted on column list. - */ - if (prev_ProcessUtility) - prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, - queryEnv, dest, qc); - else - standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, - queryEnv, dest, qc); foreach(lc, grant->grantees) { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - bool flag = false; - foreach(lc1, grant->privileges) + if (!check_bbf_schema_for_entry(logical_schema, obj,rol_spec->rolename)) { - AccessPriv *ap = (AccessPriv *) lfirst(lc1); - if(ap->cols != NULL) - { - flag = true; - break; - } + add_entry_to_bbf_schema(logical_schema, obj, ALL_PRIVILEGE_EXCEPT_EXECUTE, rol_spec->rolename, obj_type); } - if(flag) - break; - if (!check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) - add_entry_to_bbf_schema(logical_schema, obj, privilege_maskInt, rol_spec->rolename, obj_type); else { - int16 old_priv = get_bbf_schema_privilege(logical_schema, obj, rol_spec->rolename); - if(old_priv!= privilege_maskInt || ((old_priv)|(privilege_maskInt)) != old_priv) - update_bbf_schema_privilege(logical_schema, obj, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); + if(old_priv!= ALL_PRIVILEGE_EXCEPT_EXECUTE || (old_priv|(ALL_PRIVILEGE_EXCEPT_EXECUTE)) != old_priv) + update_bbf_schema_privilege(logical_schema, obj, ALL_PRIVILEGE_EXCEPT_EXECUTE, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } } + break; } else { foreach(lc, grant->grantees) { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); - bool flag = false; - /* - * 1. If GRANT on schema does not exist, execute REVOKE statement and remove the catalog entry if exists. - * 2. If GRANT on schema exist, only remove the entry from the catalog if exists. - */ - if ((logical_schema != NULL) && !check_bbf_schema_for_entry(logical_schema, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rol_spec->rolename)) + bool has_schema_perms = false; + if (check_bbf_schema_for_entry(logical_schema, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rol_spec->rolename) && !has_schema_perms) + has_schema_perms = true; + if (check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) { - if (prev_ProcessUtility) - prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, - queryEnv, dest, qc); - else - standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, - queryEnv, dest, qc); + int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); + if(old_priv!= ALL_PRIVILEGE_EXCEPT_EXECUTE || ((old_priv)&(~(ALL_PRIVILEGE_EXCEPT_EXECUTE))) != old_priv) + update_bbf_schema_privilege(logical_schema, obj, ALL_PRIVILEGE_EXCEPT_EXECUTE, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } - foreach(lc1, grant->privileges) + if (has_schema_perms) + return; + } + break; + } + } + if (grant->is_grant) + { + /* + * 1. Execute the GRANT statement. + * 2. Add its corresponding entry in the catalog, if doesn't exist already. + * 3. Don't add an entry, if the permission is granted on column list. + */ + if (prev_ProcessUtility) + prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + queryEnv, dest, qc); + else + standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + queryEnv, dest, qc); + foreach(lc, grant->grantees) + { + RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); + bool permission_is_granted_on_column = false; + foreach(lc1, grant->privileges) + { + AccessPriv *ap = (AccessPriv *) lfirst(lc1); + if(ap->cols != NULL) { - AccessPriv *ap = (AccessPriv *) lfirst(lc1); - if(ap->cols != NULL) - { - flag = true; - break; - } + permission_is_granted_on_column = true; + break; } - if(flag) - continue; - if (check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) + } + if(permission_is_granted_on_column) + break; + if (!check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) + add_entry_to_bbf_schema(logical_schema, obj, privilege_maskInt, rol_spec->rolename, obj_type); + else + { + int16 old_priv = get_bbf_schema_privilege(logical_schema, obj, rol_spec->rolename); + if(old_priv!= privilege_maskInt || ((old_priv)|(privilege_maskInt)) != old_priv) + update_bbf_schema_privilege(logical_schema, obj, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + } + } + } + else + { + foreach(lc, grant->grantees) + { + RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); + bool permission_is_granted_on_column = false; + /* + * 1. If GRANT on schema does not exist, execute REVOKE statement and remove the catalog entry if exists. + * 2. If GRANT on schema exist, only remove the entry from the catalog if exists. + */ + if ((logical_schema != NULL) && !check_bbf_schema_for_entry(logical_schema, PERMISSIONS_FOR_ALL_OBJECTS_IN_SCHEMA, rol_spec->rolename)) + { + if (prev_ProcessUtility) + prev_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + queryEnv, dest, qc); + else + standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, + queryEnv, dest, qc); + } + foreach(lc1, grant->privileges) + { + AccessPriv *ap = (AccessPriv *) lfirst(lc1); + if(ap->cols != NULL) { - int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); - if(old_priv!= privilege_maskInt || ((old_priv)&(~(privilege_maskInt))) != old_priv) - update_bbf_schema_privilege(logical_schema, obj, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + permission_is_granted_on_column = true; + break; } } - } - return; + if(permission_is_granted_on_column) + continue; + if (check_bbf_schema_for_entry(logical_schema, obj, rol_spec->rolename)) + { + int16 old_priv = get_bbf_schema_privilege(logical_schema, obj,rol_spec->rolename); + if(old_priv!= privilege_maskInt || ((old_priv)&(~(privilege_maskInt))) != old_priv) + update_bbf_schema_privilege(logical_schema, obj, privilege_maskInt, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + } + } } + return; } else if ((grant->objtype == OBJECT_PROCEDURE) || (grant->objtype == OBJECT_FUNCTION)) { @@ -3795,12 +3791,12 @@ bbf_ProcessUtility(PlannedStmt *pstmt, { RoleSpec *rol_spec = (RoleSpec *) lfirst(lc); if (!check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) - add_entry_to_bbf_schema(logicalschema, funcname, 32, rol_spec->rolename, obj_type); + add_entry_to_bbf_schema(logicalschema, funcname, PRIVILEGE_BIT_FOR_EXECUTE, rol_spec->rolename, obj_type); else { int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname, rol_spec->rolename); - if(old_priv!= 32 || ((old_priv)|(32)) != old_priv) - update_bbf_schema_privilege(logicalschema, funcname, 32, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + if(old_priv!= PRIVILEGE_BIT_FOR_EXECUTE || ((old_priv)|(PRIVILEGE_BIT_FOR_EXECUTE)) != old_priv) + update_bbf_schema_privilege(logicalschema, funcname, PRIVILEGE_BIT_FOR_EXECUTE, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } } } @@ -3816,8 +3812,8 @@ bbf_ProcessUtility(PlannedStmt *pstmt, if (check_bbf_schema_for_entry(logicalschema, funcname, rol_spec->rolename)) { int16 old_priv = get_bbf_schema_privilege(logicalschema, funcname,rol_spec->rolename); - if(old_priv!= 32 || ((old_priv)&(~(32))) != old_priv) - update_bbf_schema_privilege(logicalschema, funcname, 32, old_priv, rol_spec->rolename, obj_type, grant->is_grant); + if(old_priv!= PRIVILEGE_BIT_FOR_EXECUTE || ((old_priv)&(~(PRIVILEGE_BIT_FOR_EXECUTE))) != old_priv) + update_bbf_schema_privilege(logicalschema, funcname, PRIVILEGE_BIT_FOR_EXECUTE, old_priv, rol_spec->rolename, obj_type, grant->is_grant); } if (has_schema_perms) return;