From 204616252a55435568c158ea1bb2391b1f099862 Mon Sep 17 00:00:00 2001 From: Grzegorz Michalski Date: Wed, 18 Feb 2026 13:27:12 +0100 Subject: [PATCH] Add pRestoreGrants parameter to CREATE_EXTERNAL_TABLES_SET for grant preservation during table recreation --- .../MARS-1057/new_version/FILE_MANAGER.pkb | 130 +++++++++++++++++- .../MARS-1057/new_version/FILE_MANAGER.pkg | 26 +++- .../new_version/FILE_MANAGER_ODS.pkb | 22 ++- .../new_version/FILE_MANAGER_ODS.pkg | 31 +++-- 4 files changed, 182 insertions(+), 27 deletions(-) diff --git a/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER.pkb b/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER.pkb index 3f51144..f79de19 100644 --- a/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER.pkb +++ b/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER.pkb @@ -1968,9 +1968,22 @@ AS PROCEDURE CREATE_EXTERNAL_TABLES_SET ( pSourceFileConfigKey IN NUMBER, - pRecreate IN BOOLEAN DEFAULT FALSE + pRecreate IN BOOLEAN DEFAULT FALSE, + pRestoreGrants IN BOOLEAN DEFAULT TRUE ) IS + -- Type for storing grant information + TYPE tGrantRecord IS RECORD ( + grantee VARCHAR2(128), + privilege VARCHAR2(40), + grantable VARCHAR2(3) + ); + TYPE tGrantList IS TABLE OF tGrantRecord; + + vInboxGrants tGrantList; + vOdsGrants tGrantList; + vArchiveGrants tGrantList; + vSourceKey VARCHAR2(50); vSourceFileId VARCHAR2(100); vTableId VARCHAR2(100); @@ -1989,6 +2002,92 @@ AS vTableExists NUMBER; vParameters VARCHAR2(4000); + -- Nested procedure to save table grants before DROP + PROCEDURE SAVE_GRANTS(pTableName VARCHAR2, pGrantList OUT tGrantList) IS + BEGIN + ENV_MANAGER.LOG_PROCESS_EVENT('Saving grants for table: ' || pTableName, 'DEBUG'); + + SELECT grantee, privilege, grantable + BULK COLLECT INTO pGrantList + FROM DBA_TAB_PRIVS + WHERE owner = 'ODS' + AND table_name = pTableName + AND grantee NOT IN ('SYS', 'SYSTEM', 'PUBLIC') -- Exclude system accounts + ORDER BY grantee, privilege; + + ENV_MANAGER.LOG_PROCESS_EVENT( + 'Saved ' || pGrantList.COUNT || ' grants for table: ODS.' || pTableName, + 'INFO' + ); + EXCEPTION + WHEN NO_DATA_FOUND THEN + pGrantList := tGrantList(); -- Empty list + ENV_MANAGER.LOG_PROCESS_EVENT('No grants found for table: ' || pTableName, 'INFO'); + WHEN OTHERS THEN + ENV_MANAGER.LOG_PROCESS_EVENT( + 'Warning: Could not save grants for ' || pTableName || ': ' || SQLERRM, + 'WARNING' + ); + pGrantList := tGrantList(); -- Empty list on error + END SAVE_GRANTS; + + -- Nested procedure to restore table grants after CREATE + PROCEDURE RESTORE_GRANTS(pTableName VARCHAR2, pGrantList tGrantList) IS + vGrantSQL VARCHAR2(500); + vGrantCount NUMBER := 0; + vFailCount NUMBER := 0; + BEGIN + IF pGrantList IS NULL OR pGrantList.COUNT = 0 THEN + ENV_MANAGER.LOG_PROCESS_EVENT( + 'No grants to restore for table: ' || pTableName, + 'INFO' + ); + RETURN; + END IF; + + ENV_MANAGER.LOG_PROCESS_EVENT( + 'Restoring ' || pGrantList.COUNT || ' grants for table: ' || pTableName, + 'DEBUG' + ); + + FOR i IN 1..pGrantList.COUNT LOOP + BEGIN + vGrantSQL := 'GRANT ' || pGrantList(i).privilege || + ' ON ODS.' || pTableName || + ' TO ' || pGrantList(i).grantee; + + IF pGrantList(i).grantable = 'YES' THEN + vGrantSQL := vGrantSQL || ' WITH GRANT OPTION'; + END IF; + + EXECUTE IMMEDIATE vGrantSQL; + vGrantCount := vGrantCount + 1; + + ENV_MANAGER.LOG_PROCESS_EVENT( + 'Restored grant: ' || pGrantList(i).privilege || + ' TO ' || pGrantList(i).grantee || + CASE WHEN pGrantList(i).grantable = 'YES' THEN ' WITH GRANT OPTION' ELSE '' END, + 'DEBUG' + ); + EXCEPTION + WHEN OTHERS THEN + vFailCount := vFailCount + 1; + ENV_MANAGER.LOG_PROCESS_EVENT( + 'Warning: Could not restore grant (' || pGrantList(i).privilege || + ' TO ' || pGrantList(i).grantee || ') on ' || pTableName || ': ' || SQLERRM, + 'WARNING' + ); + END; + END LOOP; + + ENV_MANAGER.LOG_PROCESS_EVENT( + 'Restored ' || vGrantCount || ' of ' || pGrantList.COUNT || + ' grants for table: ODS.' || pTableName || + CASE WHEN vFailCount > 0 THEN ' (' || vFailCount || ' failed)' ELSE '' END, + 'INFO' + ); + END RESTORE_GRANTS; + PROCEDURE DROP_IF_EXISTS(pTableName VARCHAR2) IS BEGIN SELECT COUNT(*) INTO vTableExists @@ -2007,7 +2106,8 @@ AS BEGIN vParameters := ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST( 'pSourceFileConfigKey => ' || NVL(TO_CHAR(pSourceFileConfigKey), 'NULL'), - 'pRecreate => ' || CASE WHEN pRecreate THEN 'TRUE' ELSE 'FALSE' END + 'pRecreate => ' || CASE WHEN pRecreate THEN 'TRUE' ELSE 'FALSE' END, + 'pRestoreGrants => ' || CASE WHEN pRestoreGrants THEN 'TRUE' ELSE 'FALSE' END )); ENV_MANAGER.LOG_PROCESS_EVENT('Start CREATE_EXTERNAL_TABLES_SET', 'INFO', vParameters); @@ -2046,6 +2146,15 @@ AS -- 4. DROP existing tables if pRecreate = TRUE IF pRecreate THEN + -- Save grants before dropping tables (if pRestoreGrants = TRUE) + IF pRestoreGrants THEN + ENV_MANAGER.LOG_PROCESS_EVENT('Saving grants before dropping tables...', 'INFO'); + SAVE_GRANTS(vInboxTableName, vInboxGrants); + SAVE_GRANTS(vOdsTableName, vOdsGrants); + SAVE_GRANTS(vArchiveTableName, vArchiveGrants); + END IF; + + -- Drop existing tables DROP_IF_EXISTS(vInboxTableName); DROP_IF_EXISTS(vOdsTableName); DROP_IF_EXISTS(vArchiveTableName); @@ -2084,6 +2193,14 @@ AS pEncoding => vEncoding ); + -- 8. Restore grants after creating tables (if pRecreate = TRUE and pRestoreGrants = TRUE) + IF pRecreate AND pRestoreGrants THEN + ENV_MANAGER.LOG_PROCESS_EVENT('Restoring grants after creating tables...', 'INFO'); + RESTORE_GRANTS(vInboxTableName, vInboxGrants); + RESTORE_GRANTS(vOdsTableName, vOdsGrants); + RESTORE_GRANTS(vArchiveTableName, vArchiveGrants); + END IF; + ENV_MANAGER.LOG_PROCESS_EVENT( 'End CREATE_EXTERNAL_TABLES_SET - Successfully created all 3 external tables for config: ' || pSourceFileConfigKey, 'INFO', @@ -2103,7 +2220,8 @@ AS pSourceKey IN VARCHAR2 DEFAULT NULL, pSourceFileId IN VARCHAR2 DEFAULT NULL, pTableId IN VARCHAR2 DEFAULT NULL, - pRecreate IN BOOLEAN DEFAULT FALSE + pRecreate IN BOOLEAN DEFAULT FALSE, + pRestoreGrants IN BOOLEAN DEFAULT TRUE ) IS vCount NUMBER := 0; @@ -2115,7 +2233,8 @@ AS 'pSourceKey => ''' || NVL(pSourceKey, 'NULL') || '''', 'pSourceFileId => ''' || NVL(pSourceFileId, 'NULL') || '''', 'pTableId => ''' || NVL(pTableId, 'NULL') || '''', - 'pRecreate => ' || CASE WHEN pRecreate THEN 'TRUE' ELSE 'FALSE' END + 'pRecreate => ' || CASE WHEN pRecreate THEN 'TRUE' ELSE 'FALSE' END, + 'pRestoreGrants => ' || CASE WHEN pRestoreGrants THEN 'TRUE' ELSE 'FALSE' END )); ENV_MANAGER.LOG_PROCESS_EVENT('Start CREATE_EXTERNAL_TABLES_BATCH', 'INFO', vParameters); @@ -2142,7 +2261,8 @@ AS -- Call procedure to create set of 3 tables CREATE_EXTERNAL_TABLES_SET( pSourceFileConfigKey => rec.A_SOURCE_FILE_CONFIG_KEY, - pRecreate => pRecreate + pRecreate => pRecreate, + pRestoreGrants => pRestoreGrants ); vProcessed := vProcessed + 1; diff --git a/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER.pkg b/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER.pkg index 90d69dd..c348808 100644 --- a/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER.pkg +++ b/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER.pkg @@ -605,22 +605,28 @@ AS * @desc Creates a complete set of 3 external tables (INBOX, ODS, ARCHIVE) for a single configuration * from A_SOURCE_FILE_CONFIG table. Automatically generates table names and paths following * official path patterns. Optionally drops and recreates existing tables. + * If pRestoreGrants is TRUE, saves and restores table grants during recreate operation. * @param pSourceFileConfigKey - Primary key from A_SOURCE_FILE_CONFIG table * @param pRecreate - If TRUE, drops existing tables before creating new ones; if FALSE, fails if tables exist + * @param pRestoreGrants - If TRUE, saves grants before DROP and restores after CREATE (only when pRecreate=TRUE) + * Uses DBA_TAB_PRIVS - requires SELECT ANY DICTIONARY or SELECT ON DBA_TAB_PRIVS privilege * @example BEGIN * FILE_MANAGER.CREATE_EXTERNAL_TABLES_SET( * pSourceFileConfigKey => 123, - * pRecreate => FALSE + * pRecreate => TRUE, + * pRestoreGrants => TRUE * ); * END; * @ex_rslt Creates three external tables in ODS schema: * - C2D_A_UC_DISSEM_METADATA_LOADS_INBOX * - C2D_A_UC_DISSEM_METADATA_LOADS_ODS * - C2D_A_UC_DISSEM_METADATA_LOADS_ARCHIVE + * Preserves existing grants if pRestoreGrants = TRUE **/ PROCEDURE CREATE_EXTERNAL_TABLES_SET ( pSourceFileConfigKey IN NUMBER, - pRecreate IN BOOLEAN DEFAULT FALSE + pRecreate IN BOOLEAN DEFAULT FALSE, + pRestoreGrants IN BOOLEAN DEFAULT TRUE ); /** @@ -628,22 +634,27 @@ AS * @desc Creates external table sets for multiple configurations based on filter criteria. * Processes only INPUT type files from A_SOURCE_FILE_CONFIG. Creates 3 tables per configuration * (INBOX, ODS, ARCHIVE). Continues processing even if individual sets fail. + * If pRestoreGrants is TRUE, saves and restores table grants during recreate operations. * @param pSourceKey - Filter by A_SOURCE_KEY (NULL = all sources) * @param pSourceFileId - Filter by SOURCE_FILE_ID (NULL = all file types) * @param pTableId - Filter by TABLE_ID (NULL = all tables) * @param pRecreate - If TRUE, drops and recreates existing tables; if FALSE, skips if tables exist - * @example -- Create all external tables for C2D source + * @param pRestoreGrants - If TRUE, saves grants before DROP and restores after CREATE (only when pRecreate=TRUE) + * Uses DBA_TAB_PRIVS - requires SELECT ANY DICTIONARY or SELECT ON DBA_TAB_PRIVS privilege + * @example -- Create all external tables for C2D source with grant preservation * BEGIN * FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH( * pSourceKey => 'C2D', - * pRecreate => FALSE + * pRecreate => TRUE, + * pRestoreGrants => TRUE * ); * END; * - * -- Recreate all external tables for all sources + * -- Recreate all external tables without grant preservation * BEGIN * FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH( - * pRecreate => TRUE + * pRecreate => TRUE, + * pRestoreGrants => FALSE * ); * END; * @ex_rslt Returns summary: Total: 10, Processed: 9, Failed: 1 @@ -652,7 +663,8 @@ AS pSourceKey IN VARCHAR2 DEFAULT NULL, pSourceFileId IN VARCHAR2 DEFAULT NULL, pTableId IN VARCHAR2 DEFAULT NULL, - pRecreate IN BOOLEAN DEFAULT FALSE + pRecreate IN BOOLEAN DEFAULT FALSE, + pRestoreGrants IN BOOLEAN DEFAULT TRUE ); --------------------------------------------------------------------------------------------------------------------------- diff --git a/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER_ODS.pkb b/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER_ODS.pkb index ceb9360..58a83d6 100644 --- a/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER_ODS.pkb +++ b/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER_ODS.pkb @@ -63,20 +63,24 @@ AS */ PROCEDURE CREATE_EXTERNAL_TABLES_SET ( pSourceFileConfigKey IN NUMBER, - pRecreate IN BOOLEAN DEFAULT FALSE + pRecreate IN BOOLEAN DEFAULT FALSE, + pRestoreGrants IN BOOLEAN DEFAULT TRUE ) IS vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE; vRecreateStr VARCHAR2(10); + vRestoreGrantsStr VARCHAR2(10); BEGIN -- Convert BOOLEAN to VARCHAR2 for logging vRecreateStr := CASE WHEN pRecreate THEN 'TRUE' ELSE 'FALSE' END; + vRestoreGrantsStr := CASE WHEN pRestoreGrants THEN 'TRUE' ELSE 'FALSE' END; -- Log the start of the procedure vParameters := CT_MRDS.ENV_MANAGER.FORMAT_PARAMETERS( SYS.ODCIVARCHAR2LIST( 'pSourceFileConfigKey => ' || pSourceFileConfigKey, - 'pRecreate => ' || vRecreateStr + 'pRecreate => ' || vRecreateStr, + 'pRestoreGrants => ' || vRestoreGrantsStr ) ); @@ -87,7 +91,8 @@ AS -- and ODS wrapper simply delegates execution with DEFINER rights CT_MRDS.FILE_MANAGER.CREATE_EXTERNAL_TABLES_SET( pSourceFileConfigKey => pSourceFileConfigKey, - pRecreate => pRecreate + pRecreate => pRecreate, + pRestoreGrants => pRestoreGrants ); CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_SET', 'INFO', vParameters); @@ -111,14 +116,17 @@ AS pSourceKey IN VARCHAR2 DEFAULT NULL, pSourceFileId IN VARCHAR2 DEFAULT NULL, pTableId IN VARCHAR2 DEFAULT NULL, - pRecreate IN BOOLEAN DEFAULT FALSE + pRecreate IN BOOLEAN DEFAULT FALSE, + pRestoreGrants IN BOOLEAN DEFAULT TRUE ) IS vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE; vRecreateStr VARCHAR2(10); + vRestoreGrantsStr VARCHAR2(10); BEGIN -- Convert BOOLEAN to VARCHAR2 for logging vRecreateStr := CASE WHEN pRecreate THEN 'TRUE' ELSE 'FALSE' END; + vRestoreGrantsStr := CASE WHEN pRestoreGrants THEN 'TRUE' ELSE 'FALSE' END; -- Log the start of the procedure vParameters := CT_MRDS.ENV_MANAGER.FORMAT_PARAMETERS( @@ -126,7 +134,8 @@ AS 'pSourceKey => ''' || NVL(pSourceKey, 'NULL') || '''', 'pSourceFileId => ''' || NVL(pSourceFileId, 'NULL') || '''', 'pTableId => ''' || NVL(pTableId, 'NULL') || '''', - 'pRecreate => ' || vRecreateStr + 'pRecreate => ' || vRecreateStr, + 'pRestoreGrants => ' || vRestoreGrantsStr ) ); @@ -139,7 +148,8 @@ AS pSourceKey => pSourceKey, pSourceFileId => pSourceFileId, pTableId => pTableId, - pRecreate => pRecreate + pRecreate => pRecreate, + pRestoreGrants => pRestoreGrants ); CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_BATCH', 'INFO', vParameters); diff --git a/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER_ODS.pkg b/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER_ODS.pkg index 8f82cc3..d5d0c72 100644 --- a/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER_ODS.pkg +++ b/MARS_Packages/REL03/MARS-1057/new_version/FILE_MANAGER_ODS.pkg @@ -16,12 +16,13 @@ AS */ -- Package Version Information (Semantic Versioning: MAJOR.MINOR.PATCH) - PACKAGE_VERSION CONSTANT VARCHAR2(10) := '2.2.0'; - PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2025-11-27 15:00:00'; + PACKAGE_VERSION CONSTANT VARCHAR2(10) := '2.3.0'; + PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2026-02-18 13:30:00'; PACKAGE_AUTHOR CONSTANT VARCHAR2(100) := 'Grzegorz Michalski'; -- Version History (Latest changes first) VERSION_HISTORY CONSTANT VARCHAR2(4000) := + '2.3.0 (2026-02-18): MARS-1057 - Added pRestoreGrants parameter support for grant preservation during table recreate' || CHR(13)||CHR(10) || '2.2.0 (2025-11-27): MARS-1057 - Added CREATE_EXTERNAL_TABLES_SET and CREATE_EXTERNAL_TABLES_BATCH wrappers for batch external table creation' || CHR(13)||CHR(10) || '2.1.0 (2025-11-24): MARS-1049 - Added pEncoding parameter support for CSV character set specification' || CHR(13)||CHR(10) || '2.0.0 (2025-10-22): Added package versioning system using centralized ENV_MANAGER functions' || CHR(13)||CHR(10) || @@ -67,20 +68,26 @@ AS * from A_SOURCE_FILE_CONFIG table. Automatically generates table names and paths following * official path patterns. Wrapper for CT_MRDS.FILE_MANAGER.CREATE_EXTERNAL_TABLES_SET * with DEFINER rights to ensure objects are created in ODS schema. + * If pRestoreGrants is TRUE, saves and restores table grants during recreate operation. * @param pSourceFileConfigKey - Primary key from A_SOURCE_FILE_CONFIG table * @param pRecreate - If TRUE, drops existing tables before creating new ones; if FALSE, fails if tables exist + * @param pRestoreGrants - If TRUE, saves grants before DROP and restores after CREATE (only when pRecreate=TRUE) + * Uses DBA_TAB_PRIVS - requires SELECT ANY DICTIONARY or SELECT ON DBA_TAB_PRIVS privilege * @example EXEC ODS.FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_SET( * pSourceFileConfigKey => 123, - * pRecreate => FALSE + * pRecreate => TRUE, + * pRestoreGrants => TRUE * ); * @ex_rslt Creates three external tables in ODS schema: * - C2D_A_UC_DISSEM_METADATA_LOADS_INBOX * - C2D_A_UC_DISSEM_METADATA_LOADS_ODS * - C2D_A_UC_DISSEM_METADATA_LOADS_ARCHIVE + * Preserves existing grants if pRestoreGrants = TRUE */ PROCEDURE CREATE_EXTERNAL_TABLES_SET ( pSourceFileConfigKey IN NUMBER, - pRecreate IN BOOLEAN DEFAULT FALSE + pRecreate IN BOOLEAN DEFAULT FALSE, + pRestoreGrants IN BOOLEAN DEFAULT TRUE ); /** @@ -89,19 +96,24 @@ AS * Processes only INPUT type files from A_SOURCE_FILE_CONFIG. Creates 3 tables per configuration * (INBOX, ODS, ARCHIVE). Wrapper for CT_MRDS.FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH * with DEFINER rights to ensure objects are created in ODS schema. + * If pRestoreGrants is TRUE, saves and restores table grants during recreate operations. * @param pSourceKey - Filter by A_SOURCE_KEY (NULL = all sources) * @param pSourceFileId - Filter by SOURCE_FILE_ID (NULL = all file types) * @param pTableId - Filter by TABLE_ID (NULL = all tables) * @param pRecreate - If TRUE, drops and recreates existing tables; if FALSE, skips if tables exist - * @example -- Create all external tables for C2D source + * @param pRestoreGrants - If TRUE, saves grants before DROP and restores after CREATE (only when pRecreate=TRUE) + * Uses DBA_TAB_PRIVS - requires SELECT ANY DICTIONARY or SELECT ON DBA_TAB_PRIVS privilege + * @example -- Create all external tables for C2D source with grant preservation * EXEC ODS.FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_BATCH( * pSourceKey => 'C2D', - * pRecreate => FALSE + * pRecreate => TRUE, + * pRestoreGrants => TRUE * ); * - * -- Recreate all external tables for all sources + * -- Recreate all external tables without grant preservation * EXEC ODS.FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_BATCH( - * pRecreate => TRUE + * pRecreate => TRUE, + * pRestoreGrants => FALSE * ); * @ex_rslt Returns summary: Total: 10, Processed: 9, Failed: 1 */ @@ -109,7 +121,8 @@ AS pSourceKey IN VARCHAR2 DEFAULT NULL, pSourceFileId IN VARCHAR2 DEFAULT NULL, pTableId IN VARCHAR2 DEFAULT NULL, - pRecreate IN BOOLEAN DEFAULT FALSE + pRecreate IN BOOLEAN DEFAULT FALSE, + pRestoreGrants IN BOOLEAN DEFAULT TRUE ); ---------------------------------------------------------------------------------------------------------------------------