Compare commits
39 Commits
3848a9471b
...
866b886c70
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
866b886c70 | ||
|
|
cafa30f8f3 | ||
|
|
a0f4146a24 | ||
|
|
2b116c0256 | ||
|
|
204616252a | ||
|
|
8ce07c3360 | ||
|
|
64dc830a2b | ||
|
|
057a4e7ce3 | ||
|
|
a9a51f19be | ||
|
|
fc6304c60b | ||
|
|
b6f6446232 | ||
|
|
1327410880 | ||
|
|
f4e9fb9cb2 | ||
|
|
26aba08759 | ||
|
|
b96becd8ef | ||
|
|
b1bb24e487 | ||
|
|
86535048fc | ||
|
|
9ffad718fe | ||
|
|
d443c4f07d | ||
|
|
cdd9dff32d | ||
|
|
70909ba8c4 | ||
|
|
88325f0b8c | ||
|
|
dc8031262c | ||
|
|
fc95b12c9e | ||
|
|
23b9962128 | ||
|
|
802c102f29 | ||
|
|
fa1f179be9 | ||
|
|
5e9233649e | ||
|
|
974f6eca25 | ||
|
|
c4f5ba48bc | ||
|
|
e6ab189dc9 | ||
|
|
e93140e962 | ||
|
|
f42777f480 | ||
|
|
19925603fa | ||
|
|
569c647b6c | ||
|
|
8a162ce9bf | ||
|
|
c508e1e4e2 | ||
|
|
d6fd0b3dbd | ||
|
|
32c7a5dcee |
@@ -4,13 +4,12 @@
|
||||
# Confluence documentation (generated, not source)
|
||||
confluence/
|
||||
|
||||
patches/
|
||||
# Log files from SPOOL operations
|
||||
log/
|
||||
*.log
|
||||
|
||||
# Test directories and files
|
||||
test/
|
||||
*_test.sql
|
||||
|
||||
# Mock data scripts (development only)
|
||||
mock_data/
|
||||
|
||||
@@ -10,22 +10,36 @@ PROMPT ========================================
|
||||
-- Add new columns
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG ADD (
|
||||
ARCHIVAL_STRATEGY VARCHAR2(30) DEFAULT 'THRESHOLD_BASED' NOT NULL,
|
||||
MINIMUM_AGE_MONTHS NUMBER(3) DEFAULT NULL
|
||||
MINIMUM_AGE_MONTHS NUMBER(3) DEFAULT NULL,
|
||||
ARCHIVE_ENABLED CHAR(1) DEFAULT 'N' NOT NULL,
|
||||
KEEP_IN_TRASH CHAR(1) DEFAULT 'Y' NOT NULL
|
||||
);
|
||||
|
||||
-- Add check constraint for valid strategies
|
||||
-- Add check constraints
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG ADD CONSTRAINT
|
||||
CHK_ARCHIVAL_STRATEGY CHECK (
|
||||
ARCHIVAL_STRATEGY IN ('THRESHOLD_BASED', 'CURRENT_MONTH_ONLY', 'MINIMUM_AGE_MONTHS', 'HYBRID')
|
||||
ARCHIVAL_STRATEGY IN ('THRESHOLD_BASED', 'MINIMUM_AGE_MONTHS', 'HYBRID')
|
||||
);
|
||||
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG ADD CONSTRAINT
|
||||
CHK_ARCHIVE_ENABLED CHECK (ARCHIVE_ENABLED IN ('Y', 'N'));
|
||||
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG ADD CONSTRAINT
|
||||
CHK_KEEP_IN_TRASH CHECK (KEEP_IN_TRASH IN ('Y', 'N'));
|
||||
|
||||
-- Add comments
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.ARCHIVAL_STRATEGY IS
|
||||
'Archival strategy: THRESHOLD_BASED (days), CURRENT_MONTH_ONLY (exclude current month), MINIMUM_AGE_MONTHS (minimum age), HYBRID (combination)';
|
||||
'Archival strategy: THRESHOLD_BASED (days), MINIMUM_AGE_MONTHS (0=current month, N=retain N months), HYBRID (combination)';
|
||||
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.MINIMUM_AGE_MONTHS IS
|
||||
'Minimum age in months for archival (used with MINIMUM_AGE_MONTHS or HYBRID strategies)';
|
||||
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.ARCHIVE_ENABLED IS
|
||||
'Y=Enable archiving, N=Skip archiving. Controls if table participates in archival process. Added in MARS-828 v3.3.0';
|
||||
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.KEEP_IN_TRASH IS
|
||||
'Y=Keep files in TRASH after archiving, N=Delete immediately. Controls TRASH retention policy. Added in MARS-828 v3.3.0';
|
||||
|
||||
-- Verify columns added
|
||||
SELECT
|
||||
column_name,
|
||||
@@ -36,7 +50,7 @@ SELECT
|
||||
FROM all_tab_columns
|
||||
WHERE owner = 'CT_MRDS'
|
||||
AND table_name = 'A_SOURCE_FILE_CONFIG'
|
||||
AND column_name IN ('ARCHIVAL_STRATEGY', 'MINIMUM_AGE_MONTHS')
|
||||
AND column_name IN ('ARCHIVAL_STRATEGY', 'MINIMUM_AGE_MONTHS', 'ARCHIVE_ENABLED', 'KEEP_IN_TRASH')
|
||||
ORDER BY column_id;
|
||||
|
||||
PROMPT ========================================
|
||||
|
||||
@@ -1,14 +1,29 @@
|
||||
-- ===================================================================
|
||||
-- MARS-828: Install FILE_ARCHIVER Package Specification v3.0.0
|
||||
-- ===================================================================
|
||||
-- Purpose: Deploy updated package specification with version 3.0.0
|
||||
--=============================================================================================================================
|
||||
-- MARS-828: Install CT_MRDS.FILE_ARCHIVER Package Specification v3.3.0
|
||||
--=============================================================================================================================
|
||||
-- Purpose: Deploy FILE_ARCHIVER Package Specification with FN_ function names
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2026-01-27
|
||||
-- ===================================================================
|
||||
-- Date: 2026-02-11
|
||||
-- Related: MARS-828 Archival Strategy Implementation
|
||||
--=============================================================================================================================
|
||||
|
||||
SET SERVEROUTPUT ON
|
||||
|
||||
PROMPT ========================================================================
|
||||
PROMPT Installing CT_MRDS.FILE_ARCHIVER Package Specification v3.3.0
|
||||
PROMPT ========================================================================
|
||||
|
||||
@@new_version/FILE_ARCHIVER.pkg
|
||||
|
||||
-- Verify package compilation (check specific schema when installing as ADMIN)
|
||||
SELECT OBJECT_NAME, OBJECT_TYPE, STATUS
|
||||
FROM ALL_OBJECTS
|
||||
WHERE OWNER = 'CT_MRDS'
|
||||
AND OBJECT_NAME = 'FILE_ARCHIVER'
|
||||
AND OBJECT_TYPE = 'PACKAGE';
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT FILE_ARCHIVER Specification v3.0.0 ready for installation
|
||||
PROMPT ========================================
|
||||
PROMPT SUCCESS: FILE_ARCHIVER Package Specification v3.3.0 installed
|
||||
|
||||
--=============================================================================================================================
|
||||
-- End of Script
|
||||
--=============================================================================================================================
|
||||
|
||||
@@ -1,14 +1,38 @@
|
||||
-- ===================================================================
|
||||
-- MARS-828: Install FILE_ARCHIVER Package Body v3.0.0
|
||||
-- ===================================================================
|
||||
-- Purpose: Deploy updated package body with GET_ARCHIVAL_WHERE_CLAUSE function
|
||||
--=============================================================================================================================
|
||||
-- MARS-828: Install CT_MRDS.FILE_ARCHIVER Package Body v3.3.0
|
||||
--=============================================================================================================================
|
||||
-- Purpose: Deploy FILE_ARCHIVER Package Body with config-based archival and FN_ function names
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2026-01-27
|
||||
-- Changes:
|
||||
-- - Added GET_ARCHIVAL_WHERE_CLAUSE private function
|
||||
-- - Updated ARCHIVE_TABLE_DATA to use strategy-based filtering
|
||||
-- - Updated GATHER_TABLE_STAT to use strategy-based statistics
|
||||
-- ===================================================================
|
||||
-- Date: 2026-02-11
|
||||
-- Related: MARS-828 Archival Strategy Implementation
|
||||
--=============================================================================================================================
|
||||
|
||||
SET SERVEROUTPUT ON
|
||||
|
||||
PROMPT ========================================================================
|
||||
PROMPT Installing CT_MRDS.FILE_ARCHIVER Package Body v3.3.0
|
||||
PROMPT ========================================================================
|
||||
|
||||
@@new_version/FILE_ARCHIVER.pkb
|
||||
|
||||
-- Verify package compilation (check specific schema when installing as ADMIN)
|
||||
SELECT OBJECT_NAME, OBJECT_TYPE, STATUS
|
||||
FROM ALL_OBJECTS
|
||||
WHERE OWNER = 'CT_MRDS'
|
||||
AND OBJECT_NAME = 'FILE_ARCHIVER'
|
||||
AND OBJECT_TYPE IN ('PACKAGE', 'PACKAGE BODY')
|
||||
ORDER BY OBJECT_TYPE;
|
||||
|
||||
-- Check for any compilation errors
|
||||
SELECT 'COMPILATION ERRORS FOUND' AS WARNING
|
||||
FROM ALL_ERRORS
|
||||
WHERE OWNER = 'CT_MRDS'
|
||||
AND NAME = 'FILE_ARCHIVER'
|
||||
AND TYPE = 'PACKAGE BODY'
|
||||
AND ROWNUM = 1;
|
||||
|
||||
PROMPT SUCCESS: FILE_ARCHIVER Package Body v3.3.0 installed
|
||||
|
||||
--=============================================================================================================================
|
||||
-- End of Script
|
||||
--=============================================================================================================================
|
||||
|
||||
@@ -81,6 +81,8 @@ SELECT CT_MRDS.FILE_ARCHIVER.GET_VERSION() as package_version FROM DUAL;
|
||||
-- 7. Test trigger validation
|
||||
PROMPT
|
||||
PROMPT 7. Testing trigger validation (should fail)...
|
||||
WHENEVER SQLERROR CONTINUE
|
||||
SET SERVEROUTPUT ON
|
||||
DECLARE
|
||||
vTestPassed BOOLEAN := FALSE;
|
||||
BEGIN
|
||||
@@ -107,14 +109,16 @@ EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
IF SQLCODE = -20999 THEN
|
||||
DBMS_OUTPUT.PUT_LINE('SUCCESS: Trigger validation working correctly');
|
||||
DBMS_OUTPUT.PUT_LINE('Expected error: ' || SQLERRM);
|
||||
DBMS_OUTPUT.PUT_LINE('Trigger correctly rejected MINIMUM_AGE_MONTHS strategy without required value');
|
||||
vTestPassed := TRUE;
|
||||
ELSE
|
||||
DBMS_OUTPUT.PUT_LINE('ERROR: Unexpected error: ' || SQLERRM);
|
||||
DBMS_OUTPUT.PUT_LINE('ERROR: Unexpected error occurred during trigger validation');
|
||||
DBMS_OUTPUT.PUT_LINE('Error code: ' || SQLCODE);
|
||||
END IF;
|
||||
ROLLBACK;
|
||||
END;
|
||||
/
|
||||
WHENEVER SQLERROR EXIT FAILURE
|
||||
|
||||
PROMPT
|
||||
PROMPT ========================================
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
-- =====================================================================
|
||||
-- Script: 06_MARS_828_configure_release01_tables.sql
|
||||
-- MARS Issue: MARS-828
|
||||
-- Purpose: Configure COMPLETE archival parameters for Release 01 tables
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2026-02-05
|
||||
--
|
||||
-- Description:
|
||||
-- Configures ALL archival parameters for 25 tables:
|
||||
-- - ARCHIVAL_STRATEGY and MINIMUM_AGE_MONTHS
|
||||
-- - Archival triggers (FILES/ROWS/BYTES thresholds)
|
||||
-- - Statistics expiration (HOURS_TO_EXPIRE_STATISTICS)
|
||||
--
|
||||
-- Configuration by group:
|
||||
-- - 19 LM tables: MINIMUM_AGE_MONTHS=0 (current month only), 10 files OR 100K rows OR 1GB, 24h stats
|
||||
-- - 2 CSDB DEBT: MINIMUM_AGE_MONTHS=6, 5 files OR 50K rows OR 512MB, 48h stats
|
||||
-- - 4 CSDB ratings: MINIMUM_AGE_MONTHS=0 (current month only), 10 files OR 20K rows OR 256MB, 72h stats
|
||||
--
|
||||
-- Dependencies:
|
||||
-- - A_SOURCE_FILE_CONFIG table with all archival columns
|
||||
-- - TRG_BI_A_SRC_FILE_CFG_ARCH_VAL trigger
|
||||
-- =====================================================================
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT MARS-828: Enhanced Configuration - Complete Archival Parameters
|
||||
PROMPT =====================================================================
|
||||
PROMPT
|
||||
PROMPT This script configures COMPLETE archival parameters for 25 tables
|
||||
PROMPT
|
||||
PROMPT LM Tables (19):
|
||||
PROMPT - Strategy: MINIMUM_AGE_MONTHS = 0 (current month only)
|
||||
PROMPT - Triggers: 10 files OR 100,000 rows OR 1 GB
|
||||
PROMPT - Stats Expiration: 24 hours
|
||||
PROMPT
|
||||
PROMPT CSDB DEBT Tables (2):
|
||||
PROMPT - Strategy: MINIMUM_AGE_MONTHS = 6
|
||||
PROMPT - Triggers: 5 files OR 50,000 rows OR 512 MB
|
||||
PROMPT - Stats Expiration: 48 hours
|
||||
PROMPT
|
||||
PROMPT CSDB Rating/Description Tables (4):
|
||||
PROMPT - Strategy: MINIMUM_AGE_MONTHS = 0 (current month only)
|
||||
PROMPT - Triggers: 10 files OR 20,000 rows OR 256 MB
|
||||
PROMPT - Stats Expiration: 72 hours
|
||||
PROMPT
|
||||
PROMPT Current timestamp:
|
||||
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') AS CURRENT_TIME FROM DUAL;
|
||||
PROMPT
|
||||
PROMPT =====================================================================
|
||||
PROMPT SECTION 1: LM Tables Configuration (MINIMUM_AGE_MONTHS = 0)
|
||||
PROMPT =====================================================================
|
||||
PROMPT Thresholds: 10 files OR 100K rows OR 1GB
|
||||
PROMPT Stats expire: 24 hours
|
||||
PROMPT =====================================================================
|
||||
|
||||
-- Update all 19 LM tables in a single statement
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = 0, -- 0 = current month only
|
||||
ODS_SCHEMA_NAME = 'ODS',
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD = 10,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD = 100000,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD = 1073741824, -- 1 GB
|
||||
HOURS_TO_EXPIRE_STATISTICS = 24,
|
||||
ARCHIVE_ENABLED = 'Y', -- Enable archival for all LM tables
|
||||
KEEP_IN_TRASH = 'N' -- Delete files immediately after archival (no TRASH retention)
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND A_SOURCE_KEY = 'LM'
|
||||
AND TABLE_ID IN (
|
||||
'LM_STANDING_FACILITIES',
|
||||
'LM_STANDING_FACILITIES_HEADER',
|
||||
'LM_TTS_HEADER',
|
||||
'LM_TTS_ITEM',
|
||||
'LM_ADHOC_ADJUSTMENTS_HEADER',
|
||||
'LM_ADHOC_ADJUSTMENTS_ITEM',
|
||||
'LM_ADHOC_ADJUSTMENTS_ITEM_HEADER',
|
||||
'LM_BALANCESHEET_HEADER',
|
||||
'LM_BALANCESHEET_ITEM',
|
||||
'LM_CSM_ADJUSTMENTS_HEADER',
|
||||
'LM_CSM_ADJUSTMENTS_ITEM',
|
||||
'LM_CSM_ADJUSTMENTS_ITEM_HEADER',
|
||||
'LM_CURRENT_ACCOUNTS_HEADER',
|
||||
'LM_CURRENT_ACCOUNTS_ITEM',
|
||||
'LM_FORECAST_HEADER',
|
||||
'LM_FORECAST_ITEM',
|
||||
'LM_QRE_ADJUSTMENTS_HEADER',
|
||||
'LM_QRE_ADJUSTMENTS_ITEM',
|
||||
'LM_QRE_ADJUSTMENTS_ITEM_HEADER'
|
||||
);
|
||||
|
||||
PROMPT
|
||||
PROMPT LM tables configuration completed
|
||||
PROMPT
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT SECTION 2: CSDB DEBT Tables (MINIMUM_AGE_MONTHS = 6)
|
||||
PROMPT =====================================================================
|
||||
PROMPT Thresholds: 5 files OR 50K rows OR 512MB
|
||||
PROMPT Stats expire: 48 hours
|
||||
PROMPT =====================================================================
|
||||
|
||||
-- Update CSDB DEBT tables (6-month retention)
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = 6,
|
||||
ODS_SCHEMA_NAME = 'ODS',
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD = 5,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD = 50000,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD = 536870912, -- 512 MB
|
||||
HOURS_TO_EXPIRE_STATISTICS = 48,
|
||||
ARCHIVE_ENABLED = 'Y', -- Enable archival for CSDB DEBT tables
|
||||
KEEP_IN_TRASH = 'N' -- Delete files immediately after archival (no TRASH retention)
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND A_SOURCE_KEY = 'CSDB'
|
||||
AND TABLE_ID IN ('CSDB_DEBT', 'CSDB_DEBT_DAILY');
|
||||
|
||||
PROMPT
|
||||
PROMPT CSDB DEBT tables configuration completed
|
||||
PROMPT
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT SECTION 3: CSDB Rating/Description Tables (MINIMUM_AGE_MONTHS = 0)
|
||||
PROMPT =====================================================================
|
||||
PROMPT Thresholds: 10 files OR 20K rows OR 256MB
|
||||
PROMPT Stats expire: 72 hours
|
||||
PROMPT =====================================================================
|
||||
|
||||
-- Update CSDB rating/description tables
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = 0, -- 0 = current month only
|
||||
ODS_SCHEMA_NAME = 'ODS',
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD = 10,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD = 20000,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD = 268435456, -- 256 MB
|
||||
HOURS_TO_EXPIRE_STATISTICS = 72,
|
||||
ARCHIVE_ENABLED = 'Y', -- Enable archival for CSDB rating/description tables
|
||||
KEEP_IN_TRASH = 'N' -- Delete files immediately after archival (no TRASH retention)
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND A_SOURCE_KEY = 'CSDB'
|
||||
AND TABLE_ID IN (
|
||||
'CSDB_INSTR_RAT_FULL',
|
||||
'CSDB_INSTR_DESC_FULL',
|
||||
'CSDB_ISSUER_RAT_FULL',
|
||||
'CSDB_ISSUER_DESC_FULL'
|
||||
);
|
||||
|
||||
PROMPT
|
||||
PROMPT CSDB rating/description tables configuration completed
|
||||
PROMPT
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT Committing configuration changes...
|
||||
PROMPT =====================================================================
|
||||
|
||||
COMMIT;
|
||||
|
||||
PROMPT
|
||||
PROMPT Configuration committed successfully.
|
||||
PROMPT
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT VERIFICATION: Complete Archival Configuration
|
||||
PROMPT =====================================================================
|
||||
|
||||
PROMPT
|
||||
PROMPT LM Tables (MINIMUM_AGE_MONTHS = 0):
|
||||
PROMPT
|
||||
|
||||
SELECT
|
||||
TABLE_ID,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS,
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD AS FILE_THR,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD AS ROW_THR,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD AS BYTE_THR,
|
||||
HOURS_TO_EXPIRE_STATISTICS AS STATS_HRS,
|
||||
ARCHIVE_ENABLED,
|
||||
KEEP_IN_TRASH,
|
||||
CASE
|
||||
WHEN ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS'
|
||||
AND MINIMUM_AGE_MONTHS = 0
|
||||
AND FILES_COUNT_OVER_ARCHIVE_THRESHOLD = 10
|
||||
AND ROWS_COUNT_OVER_ARCHIVE_THRESHOLD = 100000
|
||||
AND BYTES_SUM_OVER_ARCHIVE_THRESHOLD = 1073741824
|
||||
AND HOURS_TO_EXPIRE_STATISTICS = 24
|
||||
AND ARCHIVE_ENABLED = 'Y'
|
||||
AND KEEP_IN_TRASH = 'N'
|
||||
THEN 'OK'
|
||||
ELSE 'ERROR'
|
||||
END AS STATUS
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE A_SOURCE_KEY = 'LM'
|
||||
AND SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND TABLE_ID LIKE 'LM_%'
|
||||
ORDER BY TABLE_ID;
|
||||
|
||||
PROMPT
|
||||
PROMPT CSDB DEBT Tables (MINIMUM_AGE_MONTHS = 6):
|
||||
PROMPT
|
||||
|
||||
SELECT
|
||||
TABLE_ID,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS,
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD AS FILE_THR,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD AS ROW_THR,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD AS BYTE_THR,
|
||||
HOURS_TO_EXPIRE_STATISTICS AS STATS_HRS,
|
||||
ARCHIVE_ENABLED,
|
||||
KEEP_IN_TRASH,
|
||||
CASE
|
||||
WHEN ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS'
|
||||
AND MINIMUM_AGE_MONTHS = 6
|
||||
AND FILES_COUNT_OVER_ARCHIVE_THRESHOLD = 5
|
||||
AND ROWS_COUNT_OVER_ARCHIVE_THRESHOLD = 50000
|
||||
AND BYTES_SUM_OVER_ARCHIVE_THRESHOLD = 536870912
|
||||
AND HOURS_TO_EXPIRE_STATISTICS = 48
|
||||
AND ARCHIVE_ENABLED = 'Y'
|
||||
AND KEEP_IN_TRASH = 'N'
|
||||
THEN 'OK'
|
||||
ELSE 'ERROR'
|
||||
END AS STATUS
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE A_SOURCE_KEY = 'CSDB'
|
||||
AND SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND TABLE_ID IN ('CSDB_DEBT', 'CSDB_DEBT_DAILY')
|
||||
ORDER BY TABLE_ID;
|
||||
|
||||
PROMPT
|
||||
PROMPT CSDB Rating/Description Tables (MINIMUM_AGE_MONTHS = 0):
|
||||
PROMPT
|
||||
|
||||
SELECT
|
||||
TABLE_ID,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS,
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD AS FILE_THR,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD AS ROW_THR,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD AS BYTE_THR,
|
||||
HOURS_TO_EXPIRE_STATISTICS AS STATS_HRS,
|
||||
ARCHIVE_ENABLED,
|
||||
KEEP_IN_TRASH,
|
||||
CASE
|
||||
WHEN ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS'
|
||||
AND MINIMUM_AGE_MONTHS = 0
|
||||
AND FILES_COUNT_OVER_ARCHIVE_THRESHOLD = 10
|
||||
AND ROWS_COUNT_OVER_ARCHIVE_THRESHOLD = 20000
|
||||
AND BYTES_SUM_OVER_ARCHIVE_THRESHOLD = 268435456
|
||||
AND HOURS_TO_EXPIRE_STATISTICS = 72
|
||||
AND ARCHIVE_ENABLED = 'Y'
|
||||
AND KEEP_IN_TRASH = 'N'
|
||||
THEN 'OK'
|
||||
ELSE 'ERROR'
|
||||
END AS STATUS
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE A_SOURCE_KEY = 'CSDB'
|
||||
AND SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND TABLE_ID IN ('CSDB_INSTR_RAT_FULL', 'CSDB_INSTR_DESC_FULL', 'CSDB_ISSUER_RAT_FULL', 'CSDB_ISSUER_DESC_FULL')
|
||||
ORDER BY TABLE_ID;
|
||||
|
||||
PROMPT
|
||||
PROMPT =====================================================================
|
||||
PROMPT Summary: Total Configured Tables with Full Parameters
|
||||
PROMPT =====================================================================
|
||||
|
||||
SELECT
|
||||
COUNT(*) AS TOTAL_CONFIGURED,
|
||||
SUM(CASE WHEN MINIMUM_AGE_MONTHS = 0 THEN 1 ELSE 0 END) AS CURRENT_MONTH_ONLY,
|
||||
SUM(CASE WHEN MINIMUM_AGE_MONTHS > 0 THEN 1 ELSE 0 END) AS MULTI_MONTH_RETENTION,
|
||||
SUM(CASE WHEN FILES_COUNT_OVER_ARCHIVE_THRESHOLD IS NOT NULL THEN 1 ELSE 0 END) AS WITH_FILE_THRESHOLD,
|
||||
SUM(CASE WHEN ROWS_COUNT_OVER_ARCHIVE_THRESHOLD IS NOT NULL THEN 1 ELSE 0 END) AS WITH_ROWS_THRESHOLD,
|
||||
SUM(CASE WHEN BYTES_SUM_OVER_ARCHIVE_THRESHOLD IS NOT NULL THEN 1 ELSE 0 END) AS WITH_BYTES_THRESHOLD,
|
||||
SUM(CASE WHEN HOURS_TO_EXPIRE_STATISTICS IS NOT NULL THEN 1 ELSE 0 END) AS WITH_STATS_EXPIRY,
|
||||
SUM(CASE WHEN ARCHIVE_ENABLED = 'Y' THEN 1 ELSE 0 END) AS ARCHIVAL_ENABLED,
|
||||
SUM(CASE WHEN KEEP_IN_TRASH = 'N' THEN 1 ELSE 0 END) AS IMMEDIATE_DELETE
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND ((A_SOURCE_KEY = 'LM' AND TABLE_ID LIKE 'LM_%')
|
||||
OR (A_SOURCE_KEY = 'CSDB' AND TABLE_ID IN (
|
||||
'CSDB_DEBT', 'CSDB_DEBT_DAILY',
|
||||
'CSDB_INSTR_RAT_FULL', 'CSDB_INSTR_DESC_FULL',
|
||||
'CSDB_ISSUER_RAT_FULL', 'CSDB_ISSUER_DESC_FULL'
|
||||
)));
|
||||
|
||||
PROMPT
|
||||
PROMPT Expected:
|
||||
PROMPT - TOTAL_CONFIGURED = 25
|
||||
PROMPT - WITH_FILE_THRESHOLD = 25
|
||||
PROMPT - WITH_ROWS_THRESHOLD = 25
|
||||
PROMPT - WITH_BYTES_THRESHOLD = 25
|
||||
PROMPT - WITH_STATS_EXPIRY = 25
|
||||
PROMPT - ARCHIVAL_ENABLED = 25 (all tables enabled for archival)
|
||||
PROMPT - IMMEDIATE_DELETE = 25 (all tables delete files immediately, no TRASH retention)
|
||||
PROMPT
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT Parameter Configuration Summary by Group
|
||||
PROMPT =====================================================================
|
||||
|
||||
SELECT
|
||||
CASE
|
||||
WHEN A_SOURCE_KEY = 'LM' THEN 'LM Tables'
|
||||
WHEN TABLE_ID LIKE 'CSDB_DEBT%' THEN 'CSDB DEBT'
|
||||
ELSE 'CSDB Ratings'
|
||||
END AS GROUP_NAME,
|
||||
COUNT(*) AS TABLE_COUNT,
|
||||
MAX(ARCHIVAL_STRATEGY) AS STRATEGY,
|
||||
MAX(MINIMUM_AGE_MONTHS) AS MIN_AGE,
|
||||
MAX(FILES_COUNT_OVER_ARCHIVE_THRESHOLD) AS FILES_THRESHOLD,
|
||||
MAX(ROWS_COUNT_OVER_ARCHIVE_THRESHOLD) AS ROWS_THRESHOLD,
|
||||
ROUND(MAX(BYTES_SUM_OVER_ARCHIVE_THRESHOLD)/1048576, 0) || ' MB' AS BYTES_THRESHOLD,
|
||||
MAX(HOURS_TO_EXPIRE_STATISTICS) AS STATS_HOURS
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND ((A_SOURCE_KEY = 'LM' AND TABLE_ID LIKE 'LM_%')
|
||||
OR (A_SOURCE_KEY = 'CSDB' AND TABLE_ID IN (
|
||||
'CSDB_DEBT', 'CSDB_DEBT_DAILY',
|
||||
'CSDB_INSTR_RAT_FULL', 'CSDB_INSTR_DESC_FULL',
|
||||
'CSDB_ISSUER_RAT_FULL', 'CSDB_ISSUER_DESC_FULL'
|
||||
)))
|
||||
GROUP BY
|
||||
CASE
|
||||
WHEN A_SOURCE_KEY = 'LM' THEN 'LM Tables'
|
||||
WHEN TABLE_ID LIKE 'CSDB_DEBT%' THEN 'CSDB DEBT'
|
||||
ELSE 'CSDB Ratings'
|
||||
END
|
||||
ORDER BY GROUP_NAME;
|
||||
|
||||
PROMPT
|
||||
PROMPT =====================================================================
|
||||
PROMPT Configuration Complete
|
||||
PROMPT =====================================================================
|
||||
PROMPT
|
||||
PROMPT Next Steps:
|
||||
PROMPT 1. Review verification results above
|
||||
PROMPT 2. All 25 tables should show STATUS = 'OK'
|
||||
PROMPT 3. Verify parameter configuration summary matches expectations
|
||||
PROMPT 4. Monitor archival process with new thresholds
|
||||
PROMPT
|
||||
PROMPT Archival Trigger Logic (OR condition):
|
||||
PROMPT - Archival starts when ANY threshold is exceeded
|
||||
PROMPT - Example: 10 files OR 100K rows OR 1GB triggers archival
|
||||
PROMPT
|
||||
PROMPT Statistics Refresh:
|
||||
PROMPT - LM: Every 24 hours (daily updates for frequent changes)
|
||||
PROMPT - CSDB DEBT: Every 48 hours (bi-daily for larger datasets)
|
||||
PROMPT - CSDB Ratings: Every 72 hours (every 3 days for stable data)
|
||||
PROMPT
|
||||
PROMPT Log file: 06_MARS_828_configure_release01_tables.log
|
||||
PROMPT =====================================================================
|
||||
@@ -0,0 +1,46 @@
|
||||
-- MARS-828: Add TRASH retention statuses to A_SOURCE_FILE_RECEIVED
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2026-02-09
|
||||
-- Description: Adds ARCHIVED_AND_TRASHED and ARCHIVED_AND_PURGED statuses to support TRASH retention feature
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT MARS-828: Adding TRASH retention statuses
|
||||
PROMPT ========================================
|
||||
|
||||
-- Drop old constraint
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_RECEIVED DROP CONSTRAINT A_SOURCE_FILE_RECEIVED_CHK;
|
||||
|
||||
-- Add new constraint with TRASH retention statuses
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_RECEIVED ADD CONSTRAINT A_SOURCE_FILE_RECEIVED_CHK
|
||||
CHECK (PROCESSING_STATUS IN (
|
||||
'RECEIVED',
|
||||
'VALIDATED',
|
||||
'VALIDATION_FAILED',
|
||||
'READY_FOR_INGESTION',
|
||||
'INGESTED',
|
||||
'ARCHIVED', -- Legacy status (backward compatibility)
|
||||
'ARCHIVED_AND_TRASHED', -- Files archived to Parquet and kept in TRASH folder (DATA bucket subfolder)
|
||||
'ARCHIVED_AND_PURGED' -- Files archived to Parquet and deleted from TRASH folder
|
||||
));
|
||||
|
||||
-- Add comment
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_RECEIVED.PROCESSING_STATUS IS
|
||||
'File processing status: RECEIVED → VALIDATED → READY_FOR_INGESTION → INGESTED → ARCHIVED_AND_TRASHED → ARCHIVED_AND_PURGED (optional)';
|
||||
|
||||
-- Verify constraint
|
||||
SELECT constraint_name, constraint_type, search_condition
|
||||
FROM user_constraints
|
||||
WHERE table_name = 'A_SOURCE_FILE_RECEIVED'
|
||||
AND constraint_name = 'A_SOURCE_FILE_RECEIVED_CHK';
|
||||
|
||||
-- Show current status distribution
|
||||
SELECT PROCESSING_STATUS, COUNT(*) as FILE_COUNT
|
||||
FROM CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
GROUP BY PROCESSING_STATUS
|
||||
ORDER BY PROCESSING_STATUS;
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT TRASH retention statuses added successfully
|
||||
PROMPT Status flow: INGESTED → ARCHIVED_AND_TRASHED → ARCHIVED_AND_PURGED (optional)
|
||||
PROMPT Legacy ARCHIVED status maintained for backward compatibility
|
||||
PROMPT ========================================
|
||||
@@ -0,0 +1,23 @@
|
||||
-- MARS-828: Grant EXECUTE privilege on T_FILENAME to MRDS_LOADER
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2026-02-17
|
||||
-- Description: Grants EXECUTE privilege on CT_MRDS.T_FILENAME type to MRDS_LOADER user for file processing operations
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT MARS-828: Granting EXECUTE on T_FILENAME
|
||||
PROMPT ========================================
|
||||
|
||||
-- Grant EXECUTE privilege
|
||||
GRANT EXECUTE ON CT_MRDS.T_FILENAME TO MRDS_LOADER;
|
||||
|
||||
PROMPT EXECUTE privilege on CT_MRDS.T_FILENAME granted to MRDS_LOADER
|
||||
|
||||
-- Verify grant
|
||||
SELECT GRANTEE, PRIVILEGE, GRANTABLE
|
||||
FROM USER_TAB_PRIVS
|
||||
WHERE TABLE_NAME = 'T_FILENAME'
|
||||
AND GRANTEE = 'MRDS_LOADER';
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT T_FILENAME privilege grant completed
|
||||
PROMPT ========================================
|
||||
@@ -0,0 +1,78 @@
|
||||
-- MARS-828 ROLLBACK: Remove TRASH retention statuses from A_SOURCE_FILE_RECEIVED
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2026-02-09
|
||||
-- Description: Rollback TRASH retention statuses to original constraint
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT MARS-828 ROLLBACK: Removing TRASH retention statuses
|
||||
PROMPT ========================================
|
||||
|
||||
-- Check if any files have new statuses
|
||||
DECLARE
|
||||
vTrashCount NUMBER;
|
||||
vPurgedCount NUMBER;
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO vTrashCount
|
||||
FROM CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
WHERE PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED';
|
||||
|
||||
SELECT COUNT(*) INTO vPurgedCount
|
||||
FROM CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
WHERE PROCESSING_STATUS = 'ARCHIVED_AND_PURGED';
|
||||
|
||||
DBMS_OUTPUT.PUT_LINE('Files with ARCHIVED_AND_TRASHED status: ' || vTrashCount);
|
||||
DBMS_OUTPUT.PUT_LINE('Files with ARCHIVED_AND_PURGED status: ' || vPurgedCount);
|
||||
|
||||
IF vTrashCount > 0 OR vPurgedCount > 0 THEN
|
||||
DBMS_OUTPUT.PUT_LINE('');
|
||||
DBMS_OUTPUT.PUT_LINE('WARNING: Files exist with new statuses!');
|
||||
DBMS_OUTPUT.PUT_LINE('Migrating statuses to ARCHIVED before rollback...');
|
||||
|
||||
-- Migrate new statuses back to ARCHIVED
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
SET PROCESSING_STATUS = 'ARCHIVED'
|
||||
WHERE PROCESSING_STATUS IN ('ARCHIVED_AND_TRASHED', 'ARCHIVED_AND_PURGED');
|
||||
|
||||
COMMIT;
|
||||
DBMS_OUTPUT.PUT_LINE('Migrated ' || SQL%ROWCOUNT || ' records to ARCHIVED status');
|
||||
ELSE
|
||||
DBMS_OUTPUT.PUT_LINE('No files with new statuses - safe to rollback');
|
||||
END IF;
|
||||
END;
|
||||
/
|
||||
|
||||
-- Drop new constraint
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_RECEIVED DROP CONSTRAINT A_SOURCE_FILE_RECEIVED_CHK;
|
||||
|
||||
-- Restore original constraint
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_RECEIVED ADD CONSTRAINT A_SOURCE_FILE_RECEIVED_CHK
|
||||
CHECK (PROCESSING_STATUS IN (
|
||||
'RECEIVED',
|
||||
'VALIDATED',
|
||||
'VALIDATION_FAILED',
|
||||
'READY_FOR_INGESTION',
|
||||
'INGESTED',
|
||||
'ARCHIVED'
|
||||
));
|
||||
|
||||
-- Remove comment
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_RECEIVED.PROCESSING_STATUS IS
|
||||
'File processing status: RECEIVED → VALIDATED → READY_FOR_INGESTION → INGESTED → ARCHIVED';
|
||||
|
||||
-- Verify constraint restored
|
||||
SELECT constraint_name, constraint_type, search_condition
|
||||
FROM user_constraints
|
||||
WHERE table_name = 'A_SOURCE_FILE_RECEIVED'
|
||||
AND constraint_name = 'A_SOURCE_FILE_RECEIVED_CHK';
|
||||
|
||||
-- Show current status distribution
|
||||
SELECT PROCESSING_STATUS, COUNT(*) as FILE_COUNT
|
||||
FROM CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
GROUP BY PROCESSING_STATUS
|
||||
ORDER BY PROCESSING_STATUS;
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT TRASH retention statuses rollback completed
|
||||
PROMPT Original constraint restored
|
||||
PROMPT All ARCHIVED_AND_TRASHED/ARCHIVED_AND_PURGED migrated to ARCHIVED
|
||||
PROMPT ========================================
|
||||
@@ -1,20 +1,28 @@
|
||||
-- MARS-828: Rollback archival strategy columns
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2026-01-27
|
||||
-- Description: Remove ARCHIVAL_STRATEGY and MINIMUM_AGE_MONTHS columns
|
||||
-- Description: Remove ARCHIVAL_STRATEGY, MINIMUM_AGE_MONTHS, ARCHIVE_ENABLED, and KEEP_IN_TRASH columns
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT MARS-828: Removing archival strategy columns
|
||||
PROMPT MARS-828: Removing archival strategy and config columns
|
||||
PROMPT ========================================
|
||||
|
||||
-- Drop check constraint first
|
||||
-- Drop check constraints first
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
DROP CONSTRAINT CHK_ARCHIVAL_STRATEGY;
|
||||
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
DROP CONSTRAINT CHK_ARCHIVE_ENABLED;
|
||||
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
DROP CONSTRAINT CHK_KEEP_IN_TRASH;
|
||||
|
||||
-- Drop columns
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG DROP (
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS
|
||||
MINIMUM_AGE_MONTHS,
|
||||
ARCHIVE_ENABLED,
|
||||
KEEP_IN_TRASH
|
||||
);
|
||||
|
||||
-- Verify columns dropped
|
||||
@@ -23,8 +31,8 @@ SELECT
|
||||
FROM all_tab_columns
|
||||
WHERE owner = 'CT_MRDS'
|
||||
AND table_name = 'A_SOURCE_FILE_CONFIG'
|
||||
AND column_name IN ('ARCHIVAL_STRATEGY', 'MINIMUM_AGE_MONTHS');
|
||||
AND column_name IN ('ARCHIVAL_STRATEGY', 'MINIMUM_AGE_MONTHS', 'ARCHIVE_ENABLED', 'KEEP_IN_TRASH');
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT Archival strategy columns removed successfully
|
||||
PROMPT Archival strategy and config columns removed successfully
|
||||
PROMPT ========================================
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
-- MARS-828 ROLLBACK: Revoke EXECUTE privilege on T_FILENAME from MRDS_LOADER
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2026-02-17
|
||||
-- Description: Revokes EXECUTE privilege on CT_MRDS.T_FILENAME type from MRDS_LOADER user
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT MARS-828: Revoking EXECUTE on T_FILENAME
|
||||
PROMPT ========================================
|
||||
|
||||
-- Revoke EXECUTE privilege
|
||||
REVOKE EXECUTE ON CT_MRDS.T_FILENAME FROM MRDS_LOADER;
|
||||
|
||||
PROMPT EXECUTE privilege on CT_MRDS.T_FILENAME revoked from MRDS_LOADER
|
||||
|
||||
-- Verify revocation
|
||||
SELECT GRANTEE, PRIVILEGE, GRANTABLE
|
||||
FROM USER_TAB_PRIVS
|
||||
WHERE TABLE_NAME = 'T_FILENAME'
|
||||
AND GRANTEE = 'MRDS_LOADER';
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT T_FILENAME privilege revocation completed
|
||||
PROMPT ========================================
|
||||
@@ -0,0 +1,274 @@
|
||||
-- =====================================================================
|
||||
-- Script: 96_MARS_828_rollback_release01_configuration.sql
|
||||
-- MARS Issue: MARS-828
|
||||
-- Purpose: ROLLBACK archival configuration for Release 01 tables
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2026-02-05
|
||||
--
|
||||
-- Description:
|
||||
-- Rolls back archival configuration for 25 tables by setting all
|
||||
-- archival parameters back to NULL (unconfigured state):
|
||||
-- - ARCHIVAL_STRATEGY
|
||||
-- - MINIMUM_AGE_MONTHS
|
||||
-- - FILES_COUNT_OVER_ARCHIVE_THRESHOLD
|
||||
-- - ROWS_COUNT_OVER_ARCHIVE_THRESHOLD
|
||||
-- - BYTES_SUM_OVER_ARCHIVE_THRESHOLD
|
||||
-- - HOURS_TO_EXPIRE_STATISTICS
|
||||
--
|
||||
-- This script reverts changes made by:
|
||||
-- - 06_MARS_828_configure_release01_tables.sql
|
||||
--
|
||||
-- Dependencies:
|
||||
-- - A_SOURCE_FILE_CONFIG table with archival columns
|
||||
-- =====================================================================
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT MARS-828: ROLLBACK - Remove Archival Configuration
|
||||
PROMPT =====================================================================
|
||||
PROMPT
|
||||
PROMPT This script will REMOVE archival configuration from 25 tables
|
||||
PROMPT
|
||||
PROMPT WARNING: This will reset ALL archival parameters to NULL
|
||||
PROMPT
|
||||
PROMPT Tables affected:
|
||||
PROMPT - 19 LM tables
|
||||
PROMPT - 2 CSDB DEBT tables
|
||||
PROMPT - 4 CSDB rating/description tables
|
||||
PROMPT
|
||||
PROMPT Current timestamp:
|
||||
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') AS CURRENT_TIME FROM DUAL;
|
||||
PROMPT
|
||||
PROMPT =====================================================================
|
||||
PROMPT SECTION 1: Rollback LM Tables Configuration
|
||||
PROMPT =====================================================================
|
||||
|
||||
-- Rollback all 19 LM tables in a single statement
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = NULL,
|
||||
MINIMUM_AGE_MONTHS = NULL,
|
||||
ODS_SCHEMA_NAME = NULL,
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD = NULL,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD = NULL,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD = NULL,
|
||||
HOURS_TO_EXPIRE_STATISTICS = NULL
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND A_SOURCE_KEY = 'LM'
|
||||
AND TABLE_ID IN (
|
||||
'LM_STANDING_FACILITIES',
|
||||
'LM_STANDING_FACILITIES_HEADER',
|
||||
'LM_TTS_HEADER',
|
||||
'LM_TTS_ITEM',
|
||||
'LM_ADHOC_ADJUSTMENTS_HEADER',
|
||||
'LM_ADHOC_ADJUSTMENTS_ITEM',
|
||||
'LM_ADHOC_ADJUSTMENTS_ITEM_HEADER',
|
||||
'LM_BALANCESHEET_HEADER',
|
||||
'LM_BALANCESHEET_ITEM',
|
||||
'LM_CSM_ADJUSTMENTS_HEADER',
|
||||
'LM_CSM_ADJUSTMENTS_ITEM',
|
||||
'LM_CSM_ADJUSTMENTS_ITEM_HEADER',
|
||||
'LM_CURRENT_ACCOUNTS_HEADER',
|
||||
'LM_CURRENT_ACCOUNTS_ITEM',
|
||||
'LM_FORECAST_HEADER',
|
||||
'LM_FORECAST_ITEM',
|
||||
'LM_QRE_ADJUSTMENTS_HEADER',
|
||||
'LM_QRE_ADJUSTMENTS_ITEM',
|
||||
'LM_QRE_ADJUSTMENTS_ITEM_HEADER'
|
||||
);
|
||||
|
||||
PROMPT
|
||||
PROMPT LM tables rollback completed
|
||||
PROMPT
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT SECTION 2: Rollback CSDB DEBT Tables Configuration
|
||||
PROMPT =====================================================================
|
||||
|
||||
-- Rollback CSDB DEBT tables
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = NULL,
|
||||
MINIMUM_AGE_MONTHS = NULL,
|
||||
ODS_SCHEMA_NAME = NULL,
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD = NULL,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD = NULL,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD = NULL,
|
||||
HOURS_TO_EXPIRE_STATISTICS = NULL
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND A_SOURCE_KEY = 'CSDB'
|
||||
AND TABLE_ID IN ('CSDB_DEBT', 'CSDB_DEBT_DAILY');
|
||||
|
||||
PROMPT
|
||||
PROMPT CSDB DEBT tables rollback completed
|
||||
PROMPT
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT SECTION 3: Rollback CSDB Rating/Description Tables Configuration
|
||||
PROMPT =====================================================================
|
||||
|
||||
-- Rollback CSDB rating/description tables
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = NULL,
|
||||
MINIMUM_AGE_MONTHS = NULL,
|
||||
ODS_SCHEMA_NAME = NULL,
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD = NULL,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD = NULL,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD = NULL,
|
||||
HOURS_TO_EXPIRE_STATISTICS = NULL
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND A_SOURCE_KEY = 'CSDB'
|
||||
AND TABLE_ID IN (
|
||||
'CSDB_INSTR_RAT_FULL',
|
||||
'CSDB_INSTR_DESC_FULL',
|
||||
'CSDB_ISSUER_RAT_FULL',
|
||||
'CSDB_ISSUER_DESC_FULL'
|
||||
);
|
||||
|
||||
PROMPT
|
||||
PROMPT CSDB rating/description tables rollback completed
|
||||
PROMPT
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT Committing rollback changes...
|
||||
PROMPT =====================================================================
|
||||
|
||||
COMMIT;
|
||||
|
||||
PROMPT
|
||||
PROMPT Rollback committed successfully.
|
||||
PROMPT
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT VERIFICATION: Archival Configuration Removed
|
||||
PROMPT =====================================================================
|
||||
|
||||
PROMPT
|
||||
PROMPT LM Tables (should all be NULL):
|
||||
PROMPT
|
||||
|
||||
SELECT
|
||||
TABLE_ID,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS,
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD AS FILE_THR,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD AS ROW_THR,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD AS BYTE_THR,
|
||||
HOURS_TO_EXPIRE_STATISTICS AS STATS_HRS,
|
||||
CASE
|
||||
WHEN ARCHIVAL_STRATEGY IS NULL
|
||||
AND MINIMUM_AGE_MONTHS IS NULL
|
||||
AND FILES_COUNT_OVER_ARCHIVE_THRESHOLD IS NULL
|
||||
AND ROWS_COUNT_OVER_ARCHIVE_THRESHOLD IS NULL
|
||||
AND BYTES_SUM_OVER_ARCHIVE_THRESHOLD IS NULL
|
||||
AND HOURS_TO_EXPIRE_STATISTICS IS NULL
|
||||
THEN 'OK'
|
||||
ELSE 'ERROR - Still configured'
|
||||
END AS STATUS
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE A_SOURCE_KEY = 'LM'
|
||||
AND SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND TABLE_ID LIKE 'LM_%'
|
||||
ORDER BY TABLE_ID;
|
||||
|
||||
PROMPT
|
||||
PROMPT CSDB DEBT Tables (should all be NULL):
|
||||
PROMPT
|
||||
|
||||
SELECT
|
||||
TABLE_ID,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS,
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD AS FILE_THR,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD AS ROW_THR,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD AS BYTE_THR,
|
||||
HOURS_TO_EXPIRE_STATISTICS AS STATS_HRS,
|
||||
CASE
|
||||
WHEN ARCHIVAL_STRATEGY IS NULL
|
||||
AND MINIMUM_AGE_MONTHS IS NULL
|
||||
AND FILES_COUNT_OVER_ARCHIVE_THRESHOLD IS NULL
|
||||
AND ROWS_COUNT_OVER_ARCHIVE_THRESHOLD IS NULL
|
||||
AND BYTES_SUM_OVER_ARCHIVE_THRESHOLD IS NULL
|
||||
AND HOURS_TO_EXPIRE_STATISTICS IS NULL
|
||||
THEN 'OK'
|
||||
ELSE 'ERROR - Still configured'
|
||||
END AS STATUS
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE A_SOURCE_KEY = 'CSDB'
|
||||
AND SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND TABLE_ID IN ('CSDB_DEBT', 'CSDB_DEBT_DAILY')
|
||||
ORDER BY TABLE_ID;
|
||||
|
||||
PROMPT
|
||||
PROMPT CSDB Rating/Description Tables (should all be NULL):
|
||||
PROMPT
|
||||
|
||||
SELECT
|
||||
TABLE_ID,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS,
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD AS FILE_THR,
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD AS ROW_THR,
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD AS BYTE_THR,
|
||||
HOURS_TO_EXPIRE_STATISTICS AS STATS_HRS,
|
||||
CASE
|
||||
WHEN ARCHIVAL_STRATEGY IS NULL
|
||||
AND MINIMUM_AGE_MONTHS IS NULL
|
||||
AND FILES_COUNT_OVER_ARCHIVE_THRESHOLD IS NULL
|
||||
AND ROWS_COUNT_OVER_ARCHIVE_THRESHOLD IS NULL
|
||||
AND BYTES_SUM_OVER_ARCHIVE_THRESHOLD IS NULL
|
||||
AND HOURS_TO_EXPIRE_STATISTICS IS NULL
|
||||
THEN 'OK'
|
||||
ELSE 'ERROR - Still configured'
|
||||
END AS STATUS
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE A_SOURCE_KEY = 'CSDB'
|
||||
AND SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND TABLE_ID IN ('CSDB_INSTR_RAT_FULL', 'CSDB_INSTR_DESC_FULL', 'CSDB_ISSUER_RAT_FULL', 'CSDB_ISSUER_DESC_FULL')
|
||||
ORDER BY TABLE_ID;
|
||||
|
||||
PROMPT
|
||||
PROMPT =====================================================================
|
||||
PROMPT Summary: Total Tables with Rollback Applied
|
||||
PROMPT =====================================================================
|
||||
|
||||
SELECT
|
||||
COUNT(*) AS TOTAL_TABLES,
|
||||
SUM(CASE WHEN ARCHIVAL_STRATEGY IS NULL THEN 1 ELSE 0 END) AS STRATEGY_NULL,
|
||||
SUM(CASE WHEN MINIMUM_AGE_MONTHS IS NULL THEN 1 ELSE 0 END) AS MIN_AGE_NULL,
|
||||
SUM(CASE WHEN FILES_COUNT_OVER_ARCHIVE_THRESHOLD IS NULL THEN 1 ELSE 0 END) AS FILE_THR_NULL,
|
||||
SUM(CASE WHEN ROWS_COUNT_OVER_ARCHIVE_THRESHOLD IS NULL THEN 1 ELSE 0 END) AS ROWS_THR_NULL,
|
||||
SUM(CASE WHEN BYTES_SUM_OVER_ARCHIVE_THRESHOLD IS NULL THEN 1 ELSE 0 END) AS BYTES_THR_NULL,
|
||||
SUM(CASE WHEN HOURS_TO_EXPIRE_STATISTICS IS NULL THEN 1 ELSE 0 END) AS STATS_NULL
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND ((A_SOURCE_KEY = 'LM' AND TABLE_ID LIKE 'LM_%')
|
||||
OR (A_SOURCE_KEY = 'CSDB' AND TABLE_ID IN (
|
||||
'CSDB_DEBT', 'CSDB_DEBT_DAILY',
|
||||
'CSDB_INSTR_RAT_FULL', 'CSDB_INSTR_DESC_FULL',
|
||||
'CSDB_ISSUER_RAT_FULL', 'CSDB_ISSUER_DESC_FULL'
|
||||
)));
|
||||
|
||||
PROMPT
|
||||
PROMPT Expected: All counts should be 25 (all parameters NULL for all tables)
|
||||
PROMPT - TOTAL_TABLES = 25
|
||||
PROMPT - STRATEGY_NULL = 25
|
||||
PROMPT - MIN_AGE_NULL = 25
|
||||
PROMPT - FILE_THR_NULL = 25
|
||||
PROMPT - ROWS_THR_NULL = 25
|
||||
PROMPT - BYTES_THR_NULL = 25
|
||||
PROMPT - STATS_NULL = 25
|
||||
PROMPT
|
||||
|
||||
PROMPT =====================================================================
|
||||
PROMPT Rollback Complete
|
||||
PROMPT =====================================================================
|
||||
PROMPT
|
||||
PROMPT Next Steps:
|
||||
PROMPT 1. Review verification results above
|
||||
PROMPT 2. All 25 tables should show STATUS = 'OK'
|
||||
PROMPT 3. All archival parameters should be NULL
|
||||
PROMPT 4. Tables are now in unconfigured state (no archival strategy)
|
||||
PROMPT
|
||||
PROMPT To restore configuration, re-run:
|
||||
PROMPT @06_MARS_828_configure_release01_tables.sql
|
||||
PROMPT
|
||||
PROMPT Log file: 96_MARS_828_rollback_release01_configuration.log
|
||||
PROMPT =====================================================================
|
||||
@@ -1,269 +0,0 @@
|
||||
# MARS-828: Enhanced Archival Strategies
|
||||
|
||||
## Overview
|
||||
|
||||
Implementation of flexible archival strategies for FILE_ARCHIVER package to support business requirements for different data retention policies across source systems.
|
||||
|
||||
### Background
|
||||
|
||||
**Issue**: Current FILE_ARCHIVER v2.0.0 uses fixed threshold-based archival (DAYS_FOR_ARCHIVE_THRESHOLD) which cannot accommodate:
|
||||
1. **LM/TOP sources**: Archive all data except current month
|
||||
2. **CSDB sources**: Archive only data older than 6 months
|
||||
|
||||
**Root Cause**: Hardcoded WHERE clause in ARCHIVE_TABLE_DATA procedure:
|
||||
```sql
|
||||
WHERE extract(day from (systimestamp - workflow_start)) > DAYS_FOR_ARCHIVE_THRESHOLD
|
||||
```
|
||||
|
||||
**Solution**: Introduce ARCHIVAL_STRATEGY configuration column with four strategies:
|
||||
- `THRESHOLD_BASED` - Days-based threshold (backward compatible)
|
||||
- `CURRENT_MONTH_ONLY` - Keep only current month data
|
||||
- `MINIMUM_AGE_MONTHS` - Archive data older than X months
|
||||
- `HYBRID` - Combination of current month and minimum age
|
||||
|
||||
## Changes Made
|
||||
|
||||
### Database Schema Changes
|
||||
**Table**: CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
|
||||
**Before**:
|
||||
```sql
|
||||
-- Only threshold-based configuration available
|
||||
DAYS_FOR_ARCHIVE_THRESHOLD NUMBER DEFAULT 30
|
||||
```
|
||||
|
||||
**After**:
|
||||
```sql
|
||||
-- Flexible strategy-based configuration
|
||||
ARCHIVAL_STRATEGY VARCHAR2(30) DEFAULT 'THRESHOLD_BASED' NOT NULL,
|
||||
MINIMUM_AGE_MONTHS NUMBER(3),
|
||||
DAYS_FOR_ARCHIVE_THRESHOLD NUMBER DEFAULT 30,
|
||||
CONSTRAINT CHK_ARCHIVAL_STRATEGY CHECK (ARCHIVAL_STRATEGY IN ('THRESHOLD_BASED', 'CURRENT_MONTH_ONLY', 'MINIMUM_AGE_MONTHS', 'HYBRID'))
|
||||
```
|
||||
|
||||
**New Trigger**: TRG_BI_ARCHIVAL_STRATEGY_VAL
|
||||
- Validates MINIMUM_AGE_MONTHS required for strategies that need it
|
||||
- Ensures data integrity before insert/update
|
||||
|
||||
### Package Changes
|
||||
**Package**: CT_MRDS.FILE_ARCHIVER
|
||||
|
||||
**Version**: 2.0.0 → 3.0.0 (MAJOR - breaking changes to internal logic)
|
||||
|
||||
**Specification Changes**:
|
||||
- Updated PACKAGE_VERSION: '2.0.0' → '3.0.0'
|
||||
- Updated VERSION_HISTORY with MARS-828 entry
|
||||
- Updated PACKAGE_BUILD_DATE to deployment date
|
||||
|
||||
**Body Changes**:
|
||||
1. **New Function**: GET_ARCHIVAL_WHERE_CLAUSE(pSourceFileConfig) - Returns strategy-specific WHERE clause
|
||||
2. **Updated**: ARCHIVE_TABLE_DATA - Uses GET_ARCHIVAL_WHERE_CLAUSE for flexible filtering
|
||||
3. **Updated**: GATHER_TABLE_STAT - Uses GET_ARCHIVAL_WHERE_CLAUSE for statistics calculation
|
||||
|
||||
**File Structure**:
|
||||
- **rollback/** - Backup of FILE_ARCHIVER v2.0.0 (for rollback)
|
||||
- **new_version/** - Updated FILE_ARCHIVER v3.0.0 (with strategy support)
|
||||
|
||||
## Archival Strategies
|
||||
|
||||
| Strategy | WHERE Clause Logic | Configuration Required | Use Case |
|
||||
|----------|-------------------|----------------------|----------|
|
||||
| `THRESHOLD_BASED` | `extract(day from (systimestamp - workflow_start)) > DAYS_FOR_ARCHIVE_THRESHOLD` | DAYS_FOR_ARCHIVE_THRESHOLD | Legacy compatibility |
|
||||
| `CURRENT_MONTH_ONLY` | `TRUNC(workflow_start, 'MM') < TRUNC(SYSDATE, 'MM')` | None | General sources (LM, TOP) |
|
||||
| `MINIMUM_AGE_MONTHS` | `workflow_start < ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -X)` | MINIMUM_AGE_MONTHS | CSDB (6 months retention) |
|
||||
| `HYBRID` | Both CURRENT_MONTH_ONLY AND MINIMUM_AGE_MONTHS | MINIMUM_AGE_MONTHS | Advanced scenarios |
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
```sql
|
||||
-- LM/TOP sources: Archive everything except current month
|
||||
UPDATE A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'CURRENT_MONTH_ONLY',
|
||||
MINIMUM_AGE_MONTHS = NULL
|
||||
WHERE A_SOURCE_KEY IN ('LM', 'TOP');
|
||||
|
||||
-- CSDB: Archive only data older than 6 months
|
||||
UPDATE A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = 6
|
||||
WHERE A_SOURCE_KEY = 'CSDB'
|
||||
AND TABLE_ID IN ('DEBT', 'DEBT_DAILY');
|
||||
|
||||
-- Legacy sources: Keep existing threshold behavior
|
||||
UPDATE A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'THRESHOLD_BASED',
|
||||
DAYS_FOR_ARCHIVE_THRESHOLD = 30
|
||||
WHERE A_SOURCE_KEY = 'C2D';
|
||||
|
||||
-- Advanced hybrid: Current month + 3 months minimum
|
||||
UPDATE A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'HYBRID',
|
||||
MINIMUM_AGE_MONTHS = 3
|
||||
WHERE A_SOURCE_KEY = 'SPECIAL';
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
### Prerequisites
|
||||
- **User**: ADMIN with full privileges
|
||||
- **Database**: Oracle 23ai
|
||||
- **ENV_MANAGER**: v3.x or higher
|
||||
- **FILE_MANAGER**: v3.x or higher
|
||||
- **FILE_ARCHIVER**: v2.0.0 (will upgrade to v3.0.0)
|
||||
- **Table**: A_SOURCE_FILE_CONFIG must exist
|
||||
|
||||
### Installation Steps
|
||||
|
||||
**Option 1: Master Script (Recommended)**
|
||||
```powershell
|
||||
# Navigate to MARS-828 directory
|
||||
cd .\MARS_Packages\REL01_ADDITIONS\MARS-828
|
||||
|
||||
# Execute installation (requires ADMIN user)
|
||||
sql "ADMIN/Cloudpass#34@ggmichalski_high" "@install_mars828.sql"
|
||||
|
||||
# Log file created: log/INSTALL_MARS_828_<PDB>_<timestamp>.log
|
||||
```
|
||||
|
||||
**Installation Workflow**:
|
||||
1. **Add Columns** - ARCHIVAL_STRATEGY, MINIMUM_AGE_MONTHS to A_SOURCE_FILE_CONFIG
|
||||
2. **Create Trigger** - Validation trigger TRG_BI_ARCHIVAL_STRATEGY_VAL
|
||||
3. **Deploy Package Spec** - FILE_ARCHIVER v3.0.0 specification
|
||||
4. **Deploy Package Body** - FILE_ARCHIVER v3.0.0 body with GET_ARCHIVAL_WHERE_CLAUSE
|
||||
5. **Verify Installation** - Check package compilation and structure
|
||||
6. **Track Version** - Record v3.0.0 in ENV_MANAGER
|
||||
7. **Verify Packages** - Check for untracked changes using ENV_MANAGER hash verification
|
||||
|
||||
**Option 2: Using Get-Content**
|
||||
```powershell
|
||||
Get-Content "MARS_Packages\REL01_ADDITIONS\MARS-828\install_mars828.sql" | sql "ADMIN/Cloudpass#34@ggmichalski_high"
|
||||
```
|
||||
|
||||
### Verification
|
||||
```sql
|
||||
-- Check package compilation status
|
||||
SELECT object_name, object_type, status
|
||||
FROM all_objects
|
||||
WHERE owner = 'CT_MRDS'
|
||||
AND object_name = 'FILE_ARCHIVER'
|
||||
AND object_type IN ('PACKAGE', 'PACKAGE BODY');
|
||||
|
||||
-- Verify package version
|
||||
SELECT CT_MRDS.FILE_ARCHIVER.GET_VERSION() FROM DUAL;
|
||||
-- Expected: 3.0.0
|
||||
|
||||
-- Check new columns exist
|
||||
SELECT column_name, data_type, data_default
|
||||
FROM all_tab_columns
|
||||
WHERE owner = 'CT_MRDS'
|
||||
AND table_name = 'A_SOURCE_FILE_CONFIG'
|
||||
AND column_name IN ('ARCHIVAL_STRATEGY', 'MINIMUM_AGE_MONTHS');
|
||||
|
||||
-- Test strategy configuration
|
||||
SELECT A_SOURCE_KEY, TABLE_ID, ARCHIVAL_STRATEGY, MINIMUM_AGE_MONTHS
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
ORDER BY A_SOURCE_KEY, TABLE_ID;
|
||||
```
|
||||
|
||||
### Rollback
|
||||
```powershell
|
||||
# Execute rollback script (requires ADMIN user)
|
||||
cd .\MARS_Packages\REL01_ADDITIONS\MARS-828
|
||||
sql "ADMIN/Cloudpass#34@ggmichalski_high" "@rollback_mars828.sql"
|
||||
|
||||
# Log file created: log/ROLLBACK_MARS_828_<PDB>_<timestamp>.log
|
||||
```
|
||||
|
||||
**Rollback Workflow**:
|
||||
1. **Restore Package Body** - FILE_ARCHIVER v2.0.0 body
|
||||
2. **Restore Package Spec** - FILE_ARCHIVER v2.0.0 specification
|
||||
3. **Drop Trigger** - Remove TRG_BI_ARCHIVAL_STRATEGY_VAL
|
||||
4. **Drop Columns** - Remove ARCHIVAL_STRATEGY, MINIMUM_AGE_MONTHS
|
||||
5. **Track Rollback** - Record v2.0.0 restoration in ENV_MANAGER
|
||||
6. **Verify Packages** - Check package hash consistency
|
||||
|
||||
## Testing
|
||||
|
||||
**Test Scripts**: Located in `test/` folder
|
||||
|
||||
**Main Test Script**: test/test_archival_strategies.sql
|
||||
|
||||
```sql
|
||||
-- Test 1: CURRENT_MONTH_ONLY strategy
|
||||
-- Expected: Archives data from previous months only
|
||||
SELECT COUNT(*) FROM table WHERE TRUNC(workflow_start, 'MM') < TRUNC(SYSDATE, 'MM');
|
||||
|
||||
-- Test 2: MINIMUM_AGE_MONTHS strategy (6 months)
|
||||
-- Expected: Archives data older than 6 months
|
||||
SELECT COUNT(*) FROM table WHERE workflow_start < ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -6);
|
||||
|
||||
-- Test 3: HYBRID strategy
|
||||
-- Expected: Archives data from previous months AND older than X months
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Required Packages
|
||||
- **CT_MRDS.ENV_MANAGER** v3.x - Error handling, logging, version tracking
|
||||
- **CT_MRDS.FILE_MANAGER** v3.x - Bucket URI resolution
|
||||
- **MRDS_LOADER.cloud_wrapper** - DBMS_CLOUD operations
|
||||
|
||||
### Database Objects
|
||||
- **Table**: CT_MRDS.A_SOURCE_FILE_CONFIG - Configuration storage
|
||||
- **Table**: CT_ODS.A_LOAD_HISTORY - Workflow tracking
|
||||
- **Credential**: DEF_CRED_ARN - OCI bucket access
|
||||
|
||||
## Files Included
|
||||
|
||||
1. **README.md** - This documentation file
|
||||
2. **.gitignore** - Git exclusions (confluence/, log/, test/, mock_data/)
|
||||
3. **install_mars828.sql** - Master installation script with SPOOL logging (7 steps)
|
||||
4. **rollback_mars828.sql** - Master rollback script (6 steps)
|
||||
5. **01_MARS_828_install_add_archival_strategy_columns.sql** - ALTER TABLE DDL
|
||||
6. **02_MARS_828_install_archival_strategy_trigger.sql** - CREATE TRIGGER DDL
|
||||
7. **03_MARS_828_install_CT_MRDS_FILE_ARCHIVER_SPEC.sql** - Deploy package specification v3.0.0
|
||||
8. **04_MARS_828_install_CT_MRDS_FILE_ARCHIVER_BODY.sql** - Deploy package body v3.0.0
|
||||
9. **05_MARS_828_verify_installation.sql** - Verification queries
|
||||
10. **91_MARS_828_rollback_FILE_ARCHIVER_SPEC.sql** - Restore package specification v2.0.0
|
||||
11. **92_MARS_828_rollback_FILE_ARCHIVER_BODY.sql** - Restore package body v2.0.0
|
||||
12. **93_MARS_828_rollback_trigger.sql** - DROP TRIGGER
|
||||
13. **94_MARS_828_rollback_columns.sql** - ALTER TABLE DROP COLUMN
|
||||
14. **track_package_versions.sql** - Universal version tracking script (Standard)
|
||||
15. **verify_packages_version.sql** - Universal package verification script (Standard)
|
||||
16. **test/** - Test scripts and validation scenarios
|
||||
17. **rollback/** - Backup of FILE_ARCHIVER v2.0.0 (for rollback)
|
||||
18. **new_version/** - Updated FILE_ARCHIVER v3.0.0 (deployment source)
|
||||
|
||||
## Impact Analysis
|
||||
|
||||
### Backward Compatibility
|
||||
✅ **FULLY BACKWARD COMPATIBLE**: Default ARCHIVAL_STRATEGY = 'THRESHOLD_BASED' maintains existing behavior for all sources without configuration changes.
|
||||
|
||||
### Affected Procedures
|
||||
1. **ARCHIVE_TABLE_DATA** - Uses GET_ARCHIVAL_WHERE_CLAUSE for WHERE clause generation
|
||||
2. **GATHER_TABLE_STAT** - Uses GET_ARCHIVAL_WHERE_CLAUSE for statistics calculation
|
||||
|
||||
### Configuration Migration
|
||||
No automatic migration required. New columns have sensible defaults:
|
||||
- ARCHIVAL_STRATEGY = 'THRESHOLD_BASED' (maintains current behavior)
|
||||
- MINIMUM_AGE_MONTHS = NULL (not required for THRESHOLD_BASED)
|
||||
|
||||
## Version History
|
||||
- **v3.0.0** (2026-01-27): Added flexible archival strategies (CURRENT_MONTH_ONLY, MINIMUM_AGE_MONTHS, HYBRID) via ARCHIVAL_STRATEGY configuration
|
||||
- **v2.0.0** (2025-10-01): Initial FILE_ARCHIVER package with threshold-based archival
|
||||
|
||||
## Related JIRA Issues
|
||||
- **MARS-828**: Enhanced Archival Strategies implementation
|
||||
|
||||
## Author
|
||||
Created by: Grzegorz Michalski
|
||||
Date: 2026-01-27
|
||||
Schema: CT_MRDS
|
||||
Package: FILE_ARCHIVER
|
||||
|
||||
|
||||
Grzegorz Michalski
|
||||
|
||||
## Date
|
||||
|
||||
2026-01-27
|
||||
@@ -1,6 +1,7 @@
|
||||
-- ============================================================================
|
||||
-- MARS-828 Master Installation Script
|
||||
-- ============================================================================
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Purpose: Deploy enhanced archival strategies for FILE_ARCHIVER package
|
||||
-- Target Schema: CT_MRDS
|
||||
-- Estimated Time: 2-3 minutes
|
||||
@@ -35,9 +36,9 @@ PROMPT =========================================================================
|
||||
PROMPT MARS-828 Installation Starting
|
||||
PROMPT ============================================================================
|
||||
PROMPT Package: CT_MRDS.FILE_ARCHIVER
|
||||
PROMPT Change: Enhanced archival strategies (CURRENT_MONTH_ONLY, MINIMUM_AGE_MONTHS, HYBRID)
|
||||
PROMPT Purpose: Flexible archival policies per data source
|
||||
PROMPT Steps: 7 (DDL, Trigger, Packages, Verify, Track, Verify)
|
||||
PROMPT Change: Enhanced archival strategies (MINIMUM_AGE_MONTHS, HYBRID) + TRASH retention + Selective archiving
|
||||
PROMPT Purpose: Flexible archival policies per data source with file retention and config-based control
|
||||
PROMPT Steps: 10 (DDL, Trigger, Statuses, Grants, Package v3.3.0, Verify, Track, Configure)
|
||||
PROMPT Timestamp:
|
||||
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') AS install_start FROM DUAL;
|
||||
PROMPT ============================================================================
|
||||
@@ -54,40 +55,56 @@ END;
|
||||
WHENEVER SQLERROR CONTINUE
|
||||
|
||||
-- Installation steps
|
||||
PROMPT7: Adding archival strategy columns to A_SOURCE_FILE_CONFIG
|
||||
PROMPT ===================================================================
|
||||
PROMPT
|
||||
PROMPT Step 1/9: Adding archival strategy and config columns to A_SOURCE_FILE_CONFIG
|
||||
PROMPT =============================================================================
|
||||
@@01_MARS_828_install_add_archival_strategy_columns.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 2/7: Creating validation trigger
|
||||
PROMPT Step 2/9: Creating validation trigger
|
||||
PROMPT ======================================
|
||||
@@02_MARS_828_install_archival_strategy_trigger.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 3/7: Deploying FILE_ARCHIVER Package Specification v3.0.0
|
||||
PROMPT ===============================================================
|
||||
PROMPT Step 3/10: Adding TRASH retention statuses to A_SOURCE_FILE_RECEIVED
|
||||
PROMPT =====================================================================
|
||||
@@07_MARS_828_install_add_trash_retention_statuses.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 4/10: Granting privileges on T_FILENAME to MRDS_LOADER
|
||||
PROMPT ============================================================
|
||||
@@08_MARS_828_install_grant_t_filename.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 5/10: Deploying FILE_ARCHIVER Package Specification v3.3.0
|
||||
PROMPT ================================================================
|
||||
@@03_MARS_828_install_CT_MRDS_FILE_ARCHIVER_SPEC.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 4/7: Deploying FILE_ARCHIVER Package Body v3.0.0
|
||||
PROMPT Step 6/10: Deploying FILE_ARCHIVER Package Body v3.3.0
|
||||
PROMPT ======================================================
|
||||
@@04_MARS_828_install_CT_MRDS_FILE_ARCHIVER_BODY.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 5/7: Verifying installation
|
||||
PROMPT Step 7/10: Verifying installation
|
||||
PROMPT =================================
|
||||
@@05_MARS_828_verify_installation.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 6/7: Tracking package versions
|
||||
PROMPT Step 8/10: Tracking package versions
|
||||
PROMPT ====================================
|
||||
@@track_package_versions.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 7/7: Verifying tracked packages
|
||||
PROMPT Step 9/10: Verifying tracked packages
|
||||
PROMPT =====================================
|
||||
@@verify_packages_version.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 10/10: Configuring Release 01 tables archival strategies
|
||||
PROMPT ============================================================
|
||||
@@06_MARS_828_configure_release01_tables.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT ============================================================================
|
||||
PROMPT MARS-828 Installation Completed
|
||||
@@ -97,16 +114,21 @@ SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') AS install_end FROM DUAL;
|
||||
PROMPT
|
||||
PROMPT Installation Summary:
|
||||
PROMPT - Package: CT_MRDS.FILE_ARCHIVER
|
||||
PROMPT - Version: 2.0.0 -> 3.0.0 (MAJOR)
|
||||
PROMPT - New Strategies: CURRENT_MONTH_ONLY, MINIMUM_AGE_MONTHS, HYBRID
|
||||
PROMPT - Backward Compatible: THRESHOLD_BASED (default)
|
||||
PROMPT - Version: 3.3.0 (includes selective archiving and config-based TRASH policy)
|
||||
PROMPT - Strategies: THRESHOLD_BASED (default), MINIMUM_AGE_MONTHS (0=current month), HYBRID
|
||||
PROMPT - Selective Archiving: ARCHIVE_ENABLED column (Y=archive, N=skip)
|
||||
PROMPT - TRASH Policy: KEEP_IN_TRASH column (Y=keep files, N=delete immediately)
|
||||
PROMPT * Default: ARCHIVE_ENABLED='Y', KEEP_IN_TRASH='N' (archiving enabled, immediate deletion)
|
||||
PROMPT * TRASH is a subfolder in DATA bucket (e.g., TRASH/LM/TABLE_NAME)
|
||||
PROMPT * No more pKeepInTrash parameter - policy from config only
|
||||
PROMPT - New Procedure: ARCHIVE_ALL_FOR_SOURCE(pSourceKey) for batch processing
|
||||
PROMPT - TRASH Management: RESTORE_FILE_FROM_TRASH, PURGE_TRASH_FOLDER (3-level granularity)
|
||||
PROMPT - New Statuses: ARCHIVED_AND_TRASHED, ARCHIVED_AND_PURGED
|
||||
PROMPT - Backward Compatible: Yes (default THRESHOLD_BASED, existing behavior preserved)
|
||||
PROMPT - Configured Tables: 25 Release 01 tables (19 LM + 6 CSDB)
|
||||
PROMPT - Includes All Fixes from v3.0.0 through v3.2.1
|
||||
PROMPT
|
||||
PROMPT Next Steps:
|
||||
PROMPT 1. Configure archival strategies per source:
|
||||
PROMPT UPDATE A_SOURCE_FILE_CONFIG SET ARCHIVAL_STRATEGY = 'CURRENT_MONTH_ONLY' WHERE A_SOURCE_KEY = 'LM';
|
||||
PROMPT UPDATE A_SOURCE_FILE_CONFIG SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS', MINIMUM_AGE_MONTHS = 6 WHERE A_SOURCE_KEY = 'CSDB';
|
||||
PROMPT 2. Test strategies using test_archival_strategies.sql
|
||||
PROMPT 3. Monitor first archival run
|
||||
PROMPT Note: Incremental patches available in patches/ directory
|
||||
PROMPT
|
||||
PROMPT Log file: &_filename
|
||||
PROMPT ============================================================================
|
||||
|
||||
@@ -1,310 +0,0 @@
|
||||
|
||||
============================================================================
|
||||
MARS-828 Installation Starting (AUTO MODE)
|
||||
============================================================================
|
||||
|
||||
INSTALL_START
|
||||
______________________
|
||||
2026-01-28 06:49:11
|
||||
|
||||
1 row selected.
|
||||
|
||||
============================================================================
|
||||
|
||||
Step 1/7: Adding archival strategy columns
|
||||
===================================================================
|
||||
========================================
|
||||
MARS-828: Adding archival strategy columns
|
||||
========================================
|
||||
|
||||
Error starting at line : 11 File @ C:\_git\_local_rep\working_dir_02\MARS_Packages\REL01_ADDITIONS\MARS-828\01_MARS_828_install_add_archival_strategy_columns.sql
|
||||
In command -
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG ADD (
|
||||
ARCHIVAL_STRATEGY VARCHAR2(30) DEFAULT 'THRESHOLD_BASED' NOT NULL,
|
||||
MINIMUM_AGE_MONTHS NUMBER(3) DEFAULT NULL
|
||||
)
|
||||
Error report -
|
||||
ORA-01430: column being added already exists in table
|
||||
|
||||
https://docs.oracle.com/error-help/db/ora-01430/
|
||||
01430. 00000 - "column being added already exists in table"
|
||||
*Cause: An ALTER TABLE ADD statement specified the name of a
|
||||
column that was already in the table. All column names must be
|
||||
unique within a table.
|
||||
*Action: Specify a unique name for the new column, then
|
||||
re-execute the statement.
|
||||
|
||||
Error starting at line : 17 File @ C:\_git\_local_rep\working_dir_02\MARS_Packages\REL01_ADDITIONS\MARS-828\01_MARS_828_install_add_archival_strategy_columns.sql
|
||||
In command -
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG ADD CONSTRAINT
|
||||
CHK_ARCHIVAL_STRATEGY CHECK (
|
||||
ARCHIVAL_STRATEGY IN ('THRESHOLD_BASED', 'CURRENT_MONTH_ONLY', 'MINIMUM_AGE_MONTHS', 'HYBRID')
|
||||
)
|
||||
Error report -
|
||||
ORA-02264: name already used by an existing constraint
|
||||
|
||||
https://docs.oracle.com/error-help/db/ora-02264/
|
||||
02264. 00000 - "name already used by an existing constraint"
|
||||
*Cause: The specified constraint name has to be unique.
|
||||
*Action: Specify a unique constraint name for the constraint.
|
||||
|
||||
Comment created.
|
||||
|
||||
|
||||
Comment created.
|
||||
|
||||
|
||||
COLUMN_NAME DATA_TYPE DATA_LENGTH NULLABLE DATA_DEFAULT
|
||||
_____________________ ____________ ______________ ___________ _____________________
|
||||
ARCHIVAL_STRATEGY VARCHAR2 30 N 'THRESHOLD_BASED'
|
||||
MINIMUM_AGE_MONTHS NUMBER 22 Y NULL
|
||||
|
||||
2 rows selected.
|
||||
|
||||
========================================
|
||||
Archival strategy columns added successfully
|
||||
========================================
|
||||
|
||||
Step 2/7: Creating validation trigger
|
||||
======================================
|
||||
========================================
|
||||
MARS-828: Creating archival strategy validation trigger
|
||||
========================================
|
||||
|
||||
Trigger CT_MRDS.TRG_BI_A_SRC_FILE_CFG_ARCH_VAL compiled
|
||||
|
||||
|
||||
TRIGGER_NAME STATUS TRIGGER_TYPE TRIGGERING_EVENT
|
||||
_________________________________ __________ __________________ ___________________
|
||||
TRG_BI_A_SRC_FILE_CFG_ARCH_VAL ENABLED BEFORE EACH ROW INSERT OR UPDATE
|
||||
|
||||
1 row selected.
|
||||
|
||||
========================================
|
||||
Archival strategy validation trigger created successfully
|
||||
========================================
|
||||
|
||||
Step 3/7: Deploying FILE_ARCHIVER Spec v3.0.0
|
||||
===============================================================
|
||||
|
||||
Package CT_MRDS.FILE_ARCHIVER compiled
|
||||
|
||||
========================================
|
||||
FILE_ARCHIVER Specification v3.0.0 ready for installation
|
||||
========================================
|
||||
|
||||
Step 4/7: Deploying FILE_ARCHIVER Body v3.0.0
|
||||
======================================================
|
||||
|
||||
Package Body CT_MRDS.FILE_ARCHIVER compiled
|
||||
|
||||
LINE/COL ERROR
|
||||
--------- -------------------------------------------------------------
|
||||
36/10 PLS-00103: Encountered the symbol "\" when expecting one of the following: ( begin case declare else end exit for goto if loop mod null pragma raise return select update when while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge json_object The symbol "case was inserted before "\" to continue.
|
||||
49/8 PLS-00103: Encountered the symbol "GET_ARCHIVAL_WHERE_CLAUSE" when expecting one of the following: case
|
||||
67/9 PLS-00103: Encountered the symbol "JOIN" when expecting one of the following: , ; for group having intersect minus order start union where connect
|
||||
Errors: check compiler log
|
||||
|
||||
Step 5/7: Verifying installation
|
||||
=================================
|
||||
========================================
|
||||
MARS-828: Verification Script
|
||||
========================================
|
||||
|
||||
1. Verifying A_SOURCE_FILE_CONFIG columns...
|
||||
|
||||
COLUMN_NAME DATA_TYPE NULLABLE DATA_DEFAULT
|
||||
_____________________ ____________ ___________ _____________________
|
||||
ARCHIVAL_STRATEGY VARCHAR2 N 'THRESHOLD_BASED'
|
||||
MINIMUM_AGE_MONTHS NUMBER Y NULL
|
||||
|
||||
2 rows selected.
|
||||
|
||||
|
||||
2. Verifying check constraint...
|
||||
|
||||
CONSTRAINT_NAME CONSTRAINT_TYPE SEARCH_CONDITION
|
||||
________________________ __________________ _________________________________________________________________________________________________
|
||||
CHK_ARCHIVAL_STRATEGY C ARCHIVAL_STRATEGY IN ('THRESHOLD_BASED', 'CURRENT_MONTH_ONLY', 'MINIMUM_AGE_MONTHS', 'HYBRID')
|
||||
|
||||
1 row selected.
|
||||
|
||||
|
||||
3. Verifying validation trigger...
|
||||
|
||||
TRIGGER_NAME STATUS TRIGGER_TYPE
|
||||
_________________________________ __________ __________________
|
||||
TRG_BI_A_SRC_FILE_CFG_ARCH_VAL ENABLED BEFORE EACH ROW
|
||||
|
||||
1 row selected.
|
||||
|
||||
|
||||
4. Checking FILE_ARCHIVER package status...
|
||||
|
||||
OBJECT_NAME OBJECT_TYPE STATUS LAST_DDL_TIME
|
||||
________________ _______________ __________ ______________________
|
||||
FILE_ARCHIVER PACKAGE VALID 2026-01-28 06:49:14
|
||||
FILE_ARCHIVER PACKAGE BODY INVALID 2026-01-28 06:49:15
|
||||
|
||||
2 rows selected.
|
||||
|
||||
|
||||
5. Checking for compilation errors...
|
||||
|
||||
NAME TYPE LINE POSITION TEXT
|
||||
________________ _______________ _______ ___________ _____________________________________________________________________________
|
||||
FILE_ARCHIVER PACKAGE BODY 36 10 PLS-00103: Encountered the symbol "\" when expecting one of the following:
|
||||
|
||||
( begin case declare else end exit for goto if loop mod null
|
||||
pragma raise return select update when while with
|
||||
<an identifier> <a double-quoted delimited-identifier>
|
||||
<a bind variable> << continue close current delete fetch lock
|
||||
insert open rollback savepoint set sql execute commit forall
|
||||
merge pipe purge json_object
|
||||
The symbol "case was inserted before "\" to continue.
|
||||
|
||||
FILE_ARCHIVER PACKAGE BODY 49 8 PLS-00103: Encountered the symbol "GET_ARCHIVAL_WHERE_CLAUSE" when expecting one of the following:
|
||||
|
||||
case
|
||||
|
||||
FILE_ARCHIVER PACKAGE BODY 67 9 PLS-00103: Encountered the symbol "JOIN" when expecting one of the following:
|
||||
|
||||
, ; for group having intersect minus order start union where
|
||||
connect
|
||||
|
||||
|
||||
3 rows selected.
|
||||
|
||||
|
||||
6. Verifying FILE_ARCHIVER version...
|
||||
|
||||
Error starting at line : 79 File @ C:\_git\_local_rep\working_dir_02\MARS_Packages\REL01_ADDITIONS\MARS-828\05_MARS_828_verify_installation.sql
|
||||
In command -
|
||||
SELECT CT_MRDS.FILE_ARCHIVER.GET_VERSION() as package_version FROM DUAL
|
||||
Error at Command Line : 79 Column : 68 File @ C:\_git\_local_rep\working_dir_02\MARS_Packages\REL01_ADDITIONS\MARS-828\05_MARS_828_verify_installation.sql
|
||||
Error report -
|
||||
SQL Error: ORA-04063: package body "CT_MRDS.FILE_ARCHIVER" has errors
|
||||
|
||||
https://docs.oracle.com/error-help/db/ora-04063/04063. 00000 - "%s has errors"
|
||||
*Cause: Attempt to execute a stored procedure or use a view that has
|
||||
errors. For stored procedures, the problem could be syntax errors
|
||||
or references to other, non-existent procedures. For views,
|
||||
the problem could be a reference in the view's defining query to
|
||||
a non-existent table.
|
||||
Can also be a table which has references to non-existent or
|
||||
inaccessible types.
|
||||
*Action: Fix the errors and/or create referenced objects as necessary.
|
||||
|
||||
More Details :
|
||||
https://docs.oracle.com/error-help/db/ora-04063/
|
||||
|
||||
7. Testing trigger validation (should fail)...
|
||||
SUCCESS: Trigger validation working correctly
|
||||
Expected error: ORA-20999: MINIMUM_AGE_MONTHS is required for MINIMUM_AGE_MONTHS strategy
|
||||
ORA-06512: at "CT_MRDS.TRG_BI_A_SRC_FILE_CFG_ARCH_VAL", line 26
|
||||
ORA-06512: at "CT_MRDS.TRG_BI_A_SRC_FILE_CFG_ARCH_VAL", line 8
|
||||
ORA-04088: error during execution of trigger 'CT_MRDS.TRG_BI_A_SRC_FILE_CFG_ARCH_VAL'
|
||||
|
||||
|
||||
PL/SQL procedure successfully completed.
|
||||
|
||||
|
||||
========================================
|
||||
MARS-828: Verification Complete
|
||||
========================================
|
||||
|
||||
Step 6/7: Tracking package versions
|
||||
====================================
|
||||
========================================
|
||||
Package Version Tracking
|
||||
========================================
|
||||
|
||||
Summary:
|
||||
--------
|
||||
Packages tracked: 0/1
|
||||
========================================
|
||||
|
||||
|
||||
PL/SQL procedure successfully completed.
|
||||
|
||||
|
||||
Step 7/7: Verifying tracked packages
|
||||
=====================================
|
||||
|
||||
========================================
|
||||
Package Version Verification
|
||||
========================================
|
||||
|
||||
|
||||
PACKAGE_OWNER PACKAGE_NAME VERSION STATUS
|
||||
________________ ___________________ __________ _______________________________________________________
|
||||
CT_MRDS DATA_EXPORTER 2.5.0 OK: Package CT_MRDS.DATA_EXPORTER has not changed.
|
||||
Last Tracked: 2026-01-26 17:15:41
|
||||
Version: 2.5.0
|
||||
CT_MRDS ENV_MANAGER 3.2.0 OK: Package CT_MRDS.ENV_MANAGER has not changed.
|
||||
Last Tracked: 2026-01-26 17:15:41
|
||||
Version: 3.2.0
|
||||
CT_MRDS FILE_ARCHIVER 2.0.0 WARNING: Package CT_MRDS.FILE_ARCHIVER has changed!
|
||||
========================================
|
||||
Last Tracked Version: 2.0.0
|
||||
Last Tracked Date: 2025-11-25 16:00:36
|
||||
|
||||
SPECIFICATION Changed:
|
||||
Current Hash: 71a835e531971ca7...
|
||||
Last Hash: 836641155e237fc5...
|
||||
|
||||
BODY Changed:
|
||||
Current Hash: 6f87dff6b0394529...
|
||||
Last Hash: 9bf9b3c0e059493c...
|
||||
|
||||
RECOMMENDATION:
|
||||
1. Update PACKAGE_VERSION constant
|
||||
2. Update PACKAGE_BUILD_DATE constant
|
||||
3. Add entry to VERSION_HISTORY
|
||||
4. Call TRACK_PACKAGE_VERSION to update tracking
|
||||
CT_MRDS FILE_MANAGER 3.4.0 OK: Package CT_MRDS.FILE_MANAGER has not changed.
|
||||
Last Tracked: 2026-01-26 11:42:32
|
||||
Version: 3.4.0
|
||||
CT_MRDS WORKFLOW_MANAGER 1.7.1 OK: Package CT_MRDS.WORKFLOW_MANAGER has not changed.
|
||||
Last Tracked: 2025-11-25 16:00:36
|
||||
Version: 1.7.1
|
||||
ODS FILE_MANAGER_ODS 2.1.0 WARNING: Package ODS.FILE_MANAGER_ODS has changed!
|
||||
========================================
|
||||
Last Tracked Version: 2.1.0
|
||||
Last Tracked Date: 2025-11-26 08:58:57
|
||||
|
||||
BODY Changed:
|
||||
Current Hash: 1d167a53256c10dd...
|
||||
Last Hash: NULL...
|
||||
|
||||
RECOMMENDATION:
|
||||
1. Update PACKAGE_VERSION constant
|
||||
2. Update PACKAGE_BUILD_DATE constant
|
||||
3. Add entry to VERSION_HISTORY
|
||||
4. Call TRACK_PACKAGE_VERSION to update tracking
|
||||
EnvironmentID set to: dev
|
||||
|
||||
|
||||
========================================
|
||||
Verification Complete
|
||||
========================================
|
||||
|
||||
Legend:
|
||||
OK - Package has not changed since last tracking
|
||||
WARNING - Package code changed without version update
|
||||
|
||||
For detailed hash information, use:
|
||||
SELECT ENV_MANAGER.GET_PACKAGE_HASH_INFO('OWNER', 'PACKAGE') FROM DUAL
|
||||
========================================
|
||||
|
||||
============================================================================
|
||||
MARS-828 Installation Completed
|
||||
============================================================================
|
||||
|
||||
INSTALL_END
|
||||
______________________
|
||||
2026-01-28 06:49:23
|
||||
|
||||
1 row selected.
|
||||
|
||||
============================================================================
|
||||
@@ -1,194 +0,0 @@
|
||||
|
||||
============================================================================
|
||||
MARS-828 Rollback Starting (AUTO MODE - No Confirmation)
|
||||
============================================================================
|
||||
|
||||
ROLLBACK_START
|
||||
______________________
|
||||
2026-01-29 19:52:30
|
||||
|
||||
Elapsed: 00:00:00.065
|
||||
============================================================================
|
||||
|
||||
Step 1/6: Restoring FILE_ARCHIVER Package Specification v2.0.0
|
||||
===============================================================
|
||||
|
||||
Package CT_MRDS.FILE_ARCHIVER compiled
|
||||
|
||||
Elapsed: 00:00:00.110
|
||||
|
||||
Step 2/6: Restoring FILE_ARCHIVER Package Body v2.0.0
|
||||
======================================================
|
||||
|
||||
Package Body CT_MRDS.FILE_ARCHIVER compiled
|
||||
|
||||
Elapsed: 00:00:00.133
|
||||
|
||||
Step 3/6: Dropping validation trigger
|
||||
======================================
|
||||
========================================
|
||||
MARS-828: Dropping archival strategy validation trigger
|
||||
========================================
|
||||
|
||||
Error starting at line : 10 File @ C:\_git\_local_rep\working_dir_02\MARS_Packages\REL01_ADDITIONS\MARS-828\93_MARS_828_rollback_trigger.sql
|
||||
In command -
|
||||
DROP TRIGGER CT_MRDS.TRG_BI_A_SRC_FILE_CFG_ARCH_VAL
|
||||
Error report -
|
||||
ORA-04080: trigger 'TRG_BI_A_SRC_FILE_CFG_ARCH_VAL' does not exist
|
||||
|
||||
https://docs.oracle.com/error-help/db/ora-04080/
|
||||
04080. 00000 - "trigger '%s' does not exist"
|
||||
*Cause: The TRIGGER name is invalid.
|
||||
*Action: Check the trigger name.
|
||||
Elapsed: 00:00:00.135
|
||||
|
||||
TRIGGER_COUNT
|
||||
________________
|
||||
0
|
||||
|
||||
Elapsed: 00:00:00.070
|
||||
========================================
|
||||
Validation trigger dropped successfully
|
||||
========================================
|
||||
|
||||
Step 4/6: Dropping archival strategy columns
|
||||
=============================================
|
||||
========================================
|
||||
MARS-828: Removing archival strategy columns
|
||||
========================================
|
||||
|
||||
Error starting at line : 11 File @ C:\_git\_local_rep\working_dir_02\MARS_Packages\REL01_ADDITIONS\MARS-828\94_MARS_828_rollback_columns.sql
|
||||
In command -
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
DROP CONSTRAINT CHK_ARCHIVAL_STRATEGY
|
||||
Error report -
|
||||
ORA-02443: Cannot drop constraint - nonexistent constraint
|
||||
|
||||
https://docs.oracle.com/error-help/db/ora-02443/
|
||||
02443. 00000 - "Cannot drop constraint - nonexistent constraint"
|
||||
*Cause: alter table drop constraint <constraint_name>
|
||||
*Action: make sure you supply correct constraint name.
|
||||
Elapsed: 00:00:00.118
|
||||
|
||||
Error starting at line : 15 File @ C:\_git\_local_rep\working_dir_02\MARS_Packages\REL01_ADDITIONS\MARS-828\94_MARS_828_rollback_columns.sql
|
||||
In command -
|
||||
ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG DROP (
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS
|
||||
)
|
||||
Error report -
|
||||
ORA-00904: "MINIMUM_AGE_MONTHS": invalid identifier
|
||||
|
||||
https://docs.oracle.com/error-help/db/ora-00904/
|
||||
00904. 00000 - "%s: invalid identifier"
|
||||
*Cause: The identifier or column name entered was invalid.
|
||||
*Action: Ensure the following
|
||||
Elapsed: 00:00:00.113
|
||||
|
||||
no rows selected
|
||||
Elapsed: 00:00:00.066
|
||||
========================================
|
||||
Archival strategy columns removed successfully
|
||||
========================================
|
||||
|
||||
Step 5/6: Tracking rollback version
|
||||
====================================
|
||||
========================================
|
||||
Package Version Tracking
|
||||
========================================
|
||||
EnvironmentID set to: dev
|
||||
[2026-01-29 19:52:34] [INFO] ENV_MANAGER.TRACK_PACKAGE_VERSION: Start TRACK_PACKAGE_VERSION
|
||||
[2026-01-29 19:52:34] [INFO] ENV_MANAGER.TRACK_PACKAGE_VERSION: End TRACK_PACKAGE_VERSION - Record inserted
|
||||
|
||||
Summary:
|
||||
--------
|
||||
Packages tracked: 1/1
|
||||
|
||||
Tracked Packages:
|
||||
CT_MRDS.FILE_ARCHIVER v2.0.0
|
||||
========================================
|
||||
|
||||
|
||||
PL/SQL procedure successfully completed.
|
||||
|
||||
Elapsed: 00:00:00.232
|
||||
|
||||
Step 6/6: Verifying tracked packages
|
||||
=====================================
|
||||
|
||||
========================================
|
||||
Package Version Verification
|
||||
========================================
|
||||
|
||||
|
||||
PACKAGE_OWNER PACKAGE_NAME VERSION STATUS
|
||||
________________ ___________________ __________ ______________________________________________________
|
||||
CT_MRDS DATA_EXPORTER 2.6.3 OK: Package CT_MRDS.DATA_EXPORTER has not changed.
|
||||
Last Tracked: 2026-01-28 19:18:36
|
||||
Version: 2.6.3
|
||||
CT_MRDS ENV_MANAGER 3.2.0 OK: Package CT_MRDS.ENV_MANAGER has not changed.
|
||||
Last Tracked: 2026-01-28 19:18:36
|
||||
Version: 3.2.0
|
||||
CT_MRDS FILE_ARCHIVER 2.0.0 OK: Package CT_MRDS.FILE_ARCHIVER has not changed.
|
||||
Last Tracked: 2026-01-29 19:52:34
|
||||
Version: 2.0.0
|
||||
CT_MRDS FILE_MANAGER 3.4.0 OK: Package CT_MRDS.FILE_MANAGER has not changed.
|
||||
Last Tracked: 2026-01-26 11:42:32
|
||||
Version: 3.4.0
|
||||
CT_MRDS WORKFLOW_MANAGER 1.7.1 OK: Package CT_MRDS.WORKFLOW_MANAGER has not changed.
|
||||
Last Tracked: 2025-11-25 16:00:36
|
||||
Version: 1.7.1
|
||||
ODS FILE_MANAGER_ODS 2.1.0 WARNING: Package ODS.FILE_MANAGER_ODS has changed!
|
||||
========================================
|
||||
Last Tracked Version: 2.1.0
|
||||
Last Tracked Date: 2025-11-26 08:58:57
|
||||
|
||||
BODY Changed:
|
||||
Current Hash: 1d167a53256c10dd...
|
||||
Last Hash: NULL...
|
||||
|
||||
RECOMMENDATION:
|
||||
1. Update PACKAGE_VERSION constant
|
||||
2. Update PACKAGE_BUILD_DATE constant
|
||||
3. Add entry to VERSION_HISTORY
|
||||
4. Call TRACK_PACKAGE_VERSION to update tracking
|
||||
Elapsed: 00:00:00.388
|
||||
|
||||
========================================
|
||||
Verification Complete
|
||||
========================================
|
||||
|
||||
Legend:
|
||||
OK - Package has not changed since last tracking
|
||||
WARNING - Package code changed without version update
|
||||
|
||||
For detailed hash information, use:
|
||||
SELECT ENV_MANAGER.GET_PACKAGE_HASH_INFO('OWNER', 'PACKAGE') FROM DUAL
|
||||
========================================
|
||||
|
||||
Verification: Package Compilation Status
|
||||
=========================================
|
||||
|
||||
OBJECT_NAME OBJECT_TYPE STATUS LAST_DDL_TIME
|
||||
________________ _______________ _________ ________________
|
||||
FILE_ARCHIVER PACKAGE VALID 29-JAN-26
|
||||
FILE_ARCHIVER PACKAGE BODY VALID 29-JAN-26
|
||||
|
||||
2 rows selected.
|
||||
|
||||
Elapsed: 00:00:00.100
|
||||
|
||||
============================================================================
|
||||
MARS-828 Rollback Completed
|
||||
============================================================================
|
||||
|
||||
ROLLBACK_END
|
||||
______________________
|
||||
2026-01-29 19:52:36
|
||||
|
||||
1 row selected.
|
||||
|
||||
Elapsed: 00:00:00.058
|
||||
|
||||
Log file: ../log/ROLLBACK_MARS_828_AUTO_G45C5E88148E17E_GGMICHALSKI_20260129_195230.log
|
||||
============================================================================
|
||||
@@ -1,197 +0,0 @@
|
||||
|
||||
============================================================================
|
||||
MARS-828 Rollback Starting
|
||||
============================================================================
|
||||
WARNING: This will restore FILE_ARCHIVER to v2.0.0
|
||||
|
||||
CRITICAL IMPACT:
|
||||
1. All archival strategies revert to THRESHOLD_BASED
|
||||
2. ARCHIVAL_STRATEGY and MINIMUM_AGE_MONTHS columns will be dropped
|
||||
3. Validation trigger will be removed
|
||||
4. Reconfigure archival thresholds after rollback
|
||||
|
||||
Timestamp:
|
||||
|
||||
ROLLBACK_START
|
||||
______________________
|
||||
2026-01-29 19:52:12
|
||||
|
||||
Elapsed: 00:00:00.068
|
||||
============================================================================
|
||||
Type YES to continue with rollback, or Ctrl+C to abort: YES
|
||||
old:BEGIN
|
||||
IF '&continue' IS NULL OR TRIM('&continue') IS NULL OR UPPER(TRIM('&continue')) != 'YES' THEN
|
||||
RAISE_APPLICATION_ERROR(-20001, 'Rollback aborted by user');
|
||||
END IF;
|
||||
END;
|
||||
|
||||
new:BEGIN
|
||||
IF 'YES' IS NULL OR TRIM('YES') IS NULL OR UPPER(TRIM('YES')) != 'YES' THEN
|
||||
RAISE_APPLICATION_ERROR(-20001, 'Rollback aborted by user');
|
||||
END IF;
|
||||
END;
|
||||
|
||||
PL/SQL procedure successfully completed.
|
||||
|
||||
Elapsed: 00:00:00.096
|
||||
|
||||
Step 1/6: Restoring FILE_ARCHIVER Package Specification v2.0.0
|
||||
===============================================================
|
||||
|
||||
Package CT_MRDS.FILE_ARCHIVER compiled
|
||||
|
||||
Elapsed: 00:00:00.382
|
||||
|
||||
Step 2/6: Restoring FILE_ARCHIVER Package Body v2.0.0
|
||||
======================================================
|
||||
|
||||
Package Body CT_MRDS.FILE_ARCHIVER compiled
|
||||
|
||||
Elapsed: 00:00:00.288
|
||||
|
||||
Step 3/6: Dropping validation trigger
|
||||
======================================
|
||||
========================================
|
||||
MARS-828: Dropping archival strategy validation trigger
|
||||
========================================
|
||||
|
||||
Trigger CT_MRDS.TRG_BI_A_SRC_FILE_CFG_ARCH_VAL dropped.
|
||||
|
||||
Elapsed: 00:00:00.193
|
||||
|
||||
TRIGGER_COUNT
|
||||
________________
|
||||
0
|
||||
|
||||
Elapsed: 00:00:00.335
|
||||
========================================
|
||||
Validation trigger dropped successfully
|
||||
========================================
|
||||
|
||||
Step 4/6: Dropping archival strategy columns
|
||||
=============================================
|
||||
========================================
|
||||
MARS-828: Removing archival strategy columns
|
||||
========================================
|
||||
|
||||
Table CT_MRDS.A_SOURCE_FILE_CONFIG altered.
|
||||
|
||||
Elapsed: 00:00:00.131
|
||||
|
||||
Table CT_MRDS.A_SOURCE_FILE_CONFIG altered.
|
||||
|
||||
Elapsed: 00:00:00.206
|
||||
|
||||
no rows selected
|
||||
Elapsed: 00:00:00.341
|
||||
========================================
|
||||
Archival strategy columns removed successfully
|
||||
========================================
|
||||
|
||||
Step 5/6: Tracking rollback version
|
||||
====================================
|
||||
========================================
|
||||
Package Version Tracking
|
||||
========================================
|
||||
EnvironmentID set to: dev
|
||||
[2026-01-29 19:52:16] [INFO] ENV_MANAGER.TRACK_PACKAGE_VERSION: Start TRACK_PACKAGE_VERSION
|
||||
[2026-01-29 19:52:17] [INFO] ENV_MANAGER.TRACK_PACKAGE_VERSION: End TRACK_PACKAGE_VERSION - Record inserted
|
||||
|
||||
Summary:
|
||||
--------
|
||||
Packages tracked: 1/1
|
||||
|
||||
Tracked Packages:
|
||||
CT_MRDS.FILE_ARCHIVER v2.0.0
|
||||
========================================
|
||||
|
||||
|
||||
PL/SQL procedure successfully completed.
|
||||
|
||||
Elapsed: 00:00:01.230
|
||||
|
||||
Step 6/6: Verifying tracked packages
|
||||
=====================================
|
||||
|
||||
========================================
|
||||
Package Version Verification
|
||||
========================================
|
||||
|
||||
|
||||
PACKAGE_OWNER PACKAGE_NAME VERSION STATUS
|
||||
________________ ___________________ __________ ______________________________________________________
|
||||
CT_MRDS DATA_EXPORTER 2.6.3 OK: Package CT_MRDS.DATA_EXPORTER has not changed.
|
||||
Last Tracked: 2026-01-28 19:18:36
|
||||
Version: 2.6.3
|
||||
CT_MRDS ENV_MANAGER 3.2.0 OK: Package CT_MRDS.ENV_MANAGER has not changed.
|
||||
Last Tracked: 2026-01-28 19:18:36
|
||||
Version: 3.2.0
|
||||
CT_MRDS FILE_ARCHIVER 2.0.0 OK: Package CT_MRDS.FILE_ARCHIVER has not changed.
|
||||
Last Tracked: 2026-01-29 19:52:17
|
||||
Version: 2.0.0
|
||||
CT_MRDS FILE_MANAGER 3.4.0 OK: Package CT_MRDS.FILE_MANAGER has not changed.
|
||||
Last Tracked: 2026-01-26 11:42:32
|
||||
Version: 3.4.0
|
||||
CT_MRDS WORKFLOW_MANAGER 1.7.1 OK: Package CT_MRDS.WORKFLOW_MANAGER has not changed.
|
||||
Last Tracked: 2025-11-25 16:00:36
|
||||
Version: 1.7.1
|
||||
ODS FILE_MANAGER_ODS 2.1.0 WARNING: Package ODS.FILE_MANAGER_ODS has changed!
|
||||
========================================
|
||||
Last Tracked Version: 2.1.0
|
||||
Last Tracked Date: 2025-11-26 08:58:57
|
||||
|
||||
BODY Changed:
|
||||
Current Hash: 1d167a53256c10dd...
|
||||
Last Hash: NULL...
|
||||
|
||||
RECOMMENDATION:
|
||||
1. Update PACKAGE_VERSION constant
|
||||
2. Update PACKAGE_BUILD_DATE constant
|
||||
3. Add entry to VERSION_HISTORY
|
||||
4. Call TRACK_PACKAGE_VERSION to update tracking
|
||||
Elapsed: 00:00:00.448
|
||||
|
||||
========================================
|
||||
Verification Complete
|
||||
========================================
|
||||
|
||||
Legend:
|
||||
OK - Package has not changed since last tracking
|
||||
WARNING - Package code changed without version update
|
||||
|
||||
For detailed hash information, use:
|
||||
SELECT ENV_MANAGER.GET_PACKAGE_HASH_INFO('OWNER', 'PACKAGE') FROM DUAL
|
||||
========================================
|
||||
|
||||
Verification: Package Compilation Status
|
||||
=========================================
|
||||
|
||||
OBJECT_NAME OBJECT_TYPE STATUS LAST_DDL_TIME
|
||||
________________ _______________ _________ ________________
|
||||
FILE_ARCHIVER PACKAGE VALID 29-JAN-26
|
||||
FILE_ARCHIVER PACKAGE BODY VALID 29-JAN-26
|
||||
|
||||
2 rows selected.
|
||||
|
||||
Elapsed: 00:00:00.202
|
||||
|
||||
============================================================================
|
||||
MARS-828 Rollback Completed
|
||||
============================================================================
|
||||
Completion Time:
|
||||
|
||||
ROLLBACK_END
|
||||
______________________
|
||||
2026-01-29 19:52:20
|
||||
|
||||
1 row selected.
|
||||
|
||||
Elapsed: 00:00:00.061
|
||||
|
||||
Rollback Summary:
|
||||
- Package: CT_MRDS.FILE_ARCHIVER
|
||||
- Restored Version: 2.0.0 (THRESHOLD_BASED archival only)
|
||||
- Removed Features: CURRENT_MONTH_ONLY, MINIMUM_AGE_MONTHS, HYBRID strategies
|
||||
|
||||
Log file: log/ROLLBACK_MARS_828_G45C5E88148E17E_GGMICHALSKI_20260129_195211.log
|
||||
============================================================================
|
||||
@@ -0,0 +1,56 @@
|
||||
-- ====================================================================
|
||||
-- A_SOURCE_FILE_CONFIG Table
|
||||
-- ====================================================================
|
||||
-- Purpose: Store source file configuration and processing rules
|
||||
-- MARS-1049: Added ENCODING column for CSV character set support
|
||||
-- MARS-828: Added ARCHIVAL_STRATEGY and MINIMUM_AGE_MONTHS for archival automation
|
||||
-- ====================================================================
|
||||
|
||||
CREATE TABLE CT_MRDS.A_SOURCE_FILE_CONFIG (
|
||||
A_SOURCE_FILE_CONFIG_KEY NUMBER(38,0) NOT NULL ENABLE,
|
||||
A_SOURCE_KEY VARCHAR2(30) NOT NULL ENABLE,
|
||||
SOURCE_FILE_TYPE VARCHAR2(200), -- Can be 'INPUT' or 'CONTAINER' or 'LOAD_CONFIG'
|
||||
SOURCE_FILE_ID VARCHAR2(200),
|
||||
SOURCE_FILE_DESC VARCHAR2(2000),
|
||||
SOURCE_FILE_NAME_PATTERN VARCHAR2(200),
|
||||
TABLE_ID VARCHAR2(200),
|
||||
TEMPLATE_TABLE_NAME VARCHAR2(200),
|
||||
CONTAINER_FILE_KEY NUMBER(38,0),
|
||||
DAYS_FOR_ARCHIVE_THRESHOLD NUMBER(4,0),
|
||||
FILES_COUNT_OVER_ARCHIVE_THRESHOLD NUMBER(38,0),
|
||||
BYTES_SUM_OVER_ARCHIVE_THRESHOLD NUMBER(38,0),
|
||||
ODS_SCHEMA_NAME VARCHAR2(100),
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD NUMBER(38,0),
|
||||
HOURS_TO_EXPIRE_STATISTICS NUMBER(38,3),
|
||||
ARCHIVAL_STRATEGY VARCHAR2(50),
|
||||
MINIMUM_AGE_MONTHS NUMBER(3,0),
|
||||
ENCODING VARCHAR2(50) DEFAULT 'UTF8',
|
||||
ARCHIVE_ENABLED CHAR(1) DEFAULT 'N' NOT NULL,
|
||||
KEEP_IN_TRASH CHAR(1) DEFAULT 'N' NOT NULL,
|
||||
CONSTRAINT A_SOURCE_FILE_CONFIG_PK PRIMARY KEY (A_SOURCE_FILE_CONFIG_KEY),
|
||||
CONSTRAINT CHK_ARCHIVE_ENABLED CHECK (ARCHIVE_ENABLED IN ('Y', 'N')),
|
||||
CONSTRAINT CHK_KEEP_IN_TRASH CHECK (KEEP_IN_TRASH IN ('Y', 'N')),
|
||||
CONSTRAINT SOURCE_FILE_TYPE_CHK CHECK (SOURCE_FILE_TYPE IN ('INPUT', 'CONTAINER', 'LOAD_CONFIG')),
|
||||
CONSTRAINT ASFC_A_SOURCE_KEY_FK FOREIGN KEY(A_SOURCE_KEY) REFERENCES CT_MRDS.A_SOURCE(A_SOURCE_KEY),
|
||||
CONSTRAINT ASFC_CONTAINER_FILE_KEY_FK FOREIGN KEY(CONTAINER_FILE_KEY) REFERENCES CT_MRDS.A_SOURCE_FILE_CONFIG(A_SOURCE_FILE_CONFIG_KEY),
|
||||
CONSTRAINT A_SOURCE_FILE_CONFIG_UQ1 UNIQUE(SOURCE_FILE_TYPE, SOURCE_FILE_ID, TABLE_ID)
|
||||
) TABLESPACE "DATA";
|
||||
|
||||
-- Primary key index (from production export)
|
||||
CREATE UNIQUE INDEX "CT_MRDS"."A_SOURCE_FILE_CONFIG_PK"
|
||||
ON "CT_MRDS"."A_SOURCE_FILE_CONFIG" ("A_SOURCE_FILE_CONFIG_KEY")
|
||||
TABLESPACE "DATA";
|
||||
|
||||
-- Unique constraint index (from production export)
|
||||
CREATE UNIQUE INDEX "CT_MRDS"."A_SOURCE_FILE_CONFIG_UQ1"
|
||||
ON "CT_MRDS"."A_SOURCE_FILE_CONFIG" ("SOURCE_FILE_TYPE", "SOURCE_FILE_ID", "TABLE_ID")
|
||||
TABLESPACE "DATA";
|
||||
|
||||
-- Column comments
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.ARCHIVAL_STRATEGY IS 'Archival strategy: THRESHOLD_BASED, CURRENT_MONTH_ONLY, MINIMUM_AGE_MONTHS, HYBRID. Added in MARS-828';
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.MINIMUM_AGE_MONTHS IS 'Minimum age in months before archival (required for MINIMUM_AGE_MONTHS strategy). Added in MARS-828';
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.ENCODING IS 'Oracle character set name for CSV files (e.g., UTF8, WE8MSWIN1252, EE8ISO8859P2). Added in MARS-1049';
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.ARCHIVE_ENABLED IS 'Y=Enable archiving, N=Skip archiving. Controls if table participates in archival process. Added in MARS-828 v3.3.0';
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.KEEP_IN_TRASH IS 'Y=Keep files in TRASH after archiving, N=Delete immediately. Controls TRASH retention policy. Added in MARS-828 v3.3.0';
|
||||
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON CT_MRDS.A_SOURCE_FILE_CONFIG TO MRDS_LOADER_ROLE;
|
||||
@@ -0,0 +1,29 @@
|
||||
-- ====================================================================
|
||||
-- A_SOURCE_FILE_RECEIVED Table
|
||||
-- ====================================================================
|
||||
-- Purpose: Track received files and their processing status
|
||||
-- ====================================================================
|
||||
|
||||
CREATE TABLE CT_MRDS.A_SOURCE_FILE_RECEIVED (
|
||||
A_SOURCE_FILE_RECEIVED_KEY NUMBER(38,0) NOT NULL ENABLE,
|
||||
A_SOURCE_FILE_CONFIG_KEY NUMBER(38,0) NOT NULL ENABLE,
|
||||
SOURCE_FILE_NAME VARCHAR2(1000) NOT NULL,
|
||||
CHECKSUM VARCHAR2(128),
|
||||
CREATED TIMESTAMP(6) WITH TIME ZONE,
|
||||
BYTES NUMBER,
|
||||
RECEPTION_DATE DATE NOT NULL,
|
||||
PROCESSING_STATUS VARCHAR2(200),
|
||||
EXTERNAL_TABLE_NAME VARCHAR2(200),
|
||||
PARTITION_YEAR VARCHAR2(4),
|
||||
PARTITION_MONTH VARCHAR2(2),
|
||||
ARCH_FILE_NAME VARCHAR2(1000),
|
||||
CONSTRAINT A_SOURCE_FILE_RECEIVED_PK PRIMARY KEY (A_SOURCE_FILE_RECEIVED_KEY),
|
||||
CONSTRAINT ASFR_A_SOURCE_FILE_CONFIG_KEY_FK FOREIGN KEY(A_SOURCE_FILE_CONFIG_KEY) REFERENCES CT_MRDS.A_SOURCE_FILE_CONFIG(A_SOURCE_FILE_CONFIG_KEY),
|
||||
CONSTRAINT A_SOURCE_FILE_RECEIVED_CHK CHECK (PROCESSING_STATUS IN ('RECEIVED', 'VALIDATED', 'READY_FOR_INGESTION', 'INGESTED', 'ARCHIVED', 'ARCHIVED_AND_TRASHED', 'ARCHIVED_AND_PURGED'))
|
||||
) TABLESPACE "DATA";
|
||||
|
||||
-- Unique index for file identification (workaround for TIMESTAMP WITH TIMEZONE constraint limitation)
|
||||
CREATE UNIQUE INDEX CT_MRDS.A_SOURCE_FILE_RECEIVED_UK1
|
||||
ON CT_MRDS.A_SOURCE_FILE_RECEIVED(CHECKSUM, CREATED, BYTES);
|
||||
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON CT_MRDS.A_SOURCE_FILE_RECEIVED TO MRDS_LOADER_ROLE;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,39 +17,56 @@ AS
|
||||
**/
|
||||
|
||||
-- Package Version Information (Semantic Versioning: MAJOR.MINOR.PATCH)
|
||||
PACKAGE_VERSION CONSTANT VARCHAR2(10) := '3.1.0';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2026-01-29 21:00:00';
|
||||
PACKAGE_VERSION CONSTANT VARCHAR2(10) := '3.3.0';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2026-02-11 12:00:00';
|
||||
PACKAGE_AUTHOR CONSTANT VARCHAR2(100) := 'Grzegorz Michalski';
|
||||
|
||||
-- Version History (Latest changes first)
|
||||
VERSION_HISTORY CONSTANT VARCHAR2(4000) :=
|
||||
'3.3.0 (2026-02-11): Added ARCHIVE_ENABLED and KEEP_IN_TRASH columns to A_SOURCE_FILE_CONFIG for selective archiving and config-based TRASH policy. Removed pKeepInTrash parameter (now from config). Added ARCHIVE_ALL batch procedure with 3-level granularity (config/source/all). Added GATHER_TABLE_STAT_ALL batch statistics procedure with 3-level granularity. Added RESTORE_FILE_FROM_TRASH and PURGE_TRASH_FOLDER with 3-level granularity' || CHR(13)||CHR(10) ||
|
||||
'3.2.1 (2026-02-10): Fixed status update - ARCHIVED → ARCHIVED_AND_TRASHED when moving files to TRASH folder (critical bug fix)' || CHR(13)||CHR(10) ||
|
||||
'3.2.0 (2026-02-06): Added pKeepInTrash parameter (DEFAULT TRUE) to ARCHIVE_TABLE_DATA for TRASH folder retention control - files kept in TRASH subfolder (DATA bucket) by default for safety and compliance' || CHR(13)||CHR(10) ||
|
||||
'3.1.2 (2026-02-06): Fixed missing PARTITION_YEAR/PARTITION_MONTH assignments in UPDATE statement and export query circular dependency (now filters by workflow_start instead of partition fields)' || CHR(13)||CHR(10) ||
|
||||
'3.1.1 (2026-02-06): Fixed ORA-01422 error when DBMS_CLOUD.EXPORT_DATA creates multiple parquet files (parallel execution). Now stores archive directory prefix instead of individual filenames' || CHR(13)||CHR(10) ||
|
||||
'3.1.0 (2026-01-29): Added function overloads for ARCHIVE_TABLE_DATA and GATHER_TABLE_STAT returning SQLCODE for Python library integration' || CHR(13)||CHR(10) ||
|
||||
'3.0.0 (2026-01-27): MARS-828 - Added flexible archival strategies (CURRENT_MONTH_ONLY, MINIMUM_AGE_MONTHS, HYBRID) via ARCHIVAL_STRATEGY configuration' || CHR(13)||CHR(10) ||
|
||||
'3.0.0 (2026-01-27): MARS-828 - Added flexible archival strategies (MINIMUM_AGE_MONTHS with 0=current month, HYBRID) via ARCHIVAL_STRATEGY configuration' || CHR(13)||CHR(10) ||
|
||||
'2.0.0 (2025-10-22): Added package versioning system using centralized ENV_MANAGER functions' || CHR(13)||CHR(10) ||
|
||||
'1.5.0 (2025-10-18): Enhanced ARCHIVE_TABLE_DATA with Hive-style partitioning support' || CHR(13)||CHR(10) ||
|
||||
'1.0.0 (2025-09-15): Initial release with table archival and statistics gathering';
|
||||
|
||||
cgBL CONSTANT VARCHAR2(2) := ENV_MANAGER.cgBL;
|
||||
|
||||
/**
|
||||
* @name GET_TABLE_STAT
|
||||
* @desc Private function to retrieve table statistics for archival processing.
|
||||
* Returns A_TABLE_STAT record with table metadata and row counts.
|
||||
* @param pSourceFileConfigKey - Configuration key for source file
|
||||
* @return CT_MRDS.A_TABLE_STAT%ROWTYPE - Table statistics record
|
||||
* @private Internal function for archival operations
|
||||
**/
|
||||
FUNCTION GET_TABLE_STAT(pSourceFileConfigKey IN NUMBER) RETURN CT_MRDS.A_TABLE_STAT%ROWTYPE;
|
||||
|
||||
/**
|
||||
* @name ARCHIVE_TABLE_DATA
|
||||
* @desc Wrapper procedure for DBMS_CLOUD.EXPORT_DATA.
|
||||
* Exports data from table specified by pSourceFileConfigKey(A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY) into PARQUET file on OCI infrustructure.
|
||||
* Each YEAR_MONTH pair goes to seperate file (implicit partitioning).
|
||||
* TRASH policy is controlled by A_SOURCE_FILE_CONFIG.KEEP_IN_TRASH column ('Y'=keep in TRASH, 'N'=delete immediately).
|
||||
**/
|
||||
PROCEDURE ARCHIVE_TABLE_DATA (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
);
|
||||
|
||||
/**
|
||||
* @name ARCHIVE_TABLE_DATA
|
||||
* @desc Function overload for ARCHIVE_TABLE_DATA procedure.
|
||||
* @name FN_ARCHIVE_TABLE_DATA
|
||||
* @desc Function wrapper for ARCHIVE_TABLE_DATA procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main ARCHIVE_TABLE_DATA procedure and captures execution result.
|
||||
* @example SELECT FILE_ARCHIVER.ARCHIVE_TABLE_DATA(pSourceFileConfigKey => 123) FROM DUAL;
|
||||
* TRASH policy is controlled by A_SOURCE_FILE_CONFIG.KEEP_IN_TRASH column ('Y'=keep in TRASH, 'N'=delete immediately).
|
||||
* @example SELECT FILE_ARCHIVER.FN_ARCHIVE_TABLE_DATA(pSourceFileConfigKey => 123) FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION ARCHIVE_TABLE_DATA (
|
||||
FUNCTION FN_ARCHIVE_TABLE_DATA (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
@@ -65,17 +82,163 @@ AS
|
||||
);
|
||||
|
||||
/**
|
||||
* @name GATHER_TABLE_STAT
|
||||
* @desc Function overload for GATHER_TABLE_STAT procedure.
|
||||
* @name FN_GATHER_TABLE_STAT
|
||||
* @desc Function wrapper for GATHER_TABLE_STAT procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main GATHER_TABLE_STAT procedure and captures execution result.
|
||||
* @example SELECT FILE_ARCHIVER.GATHER_TABLE_STAT(pSourceFileConfigKey => 123) FROM DUAL;
|
||||
* @example SELECT FILE_ARCHIVER.FN_GATHER_TABLE_STAT(pSourceFileConfigKey => 123) FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION GATHER_TABLE_STAT (
|
||||
FUNCTION FN_GATHER_TABLE_STAT (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
/**
|
||||
* @name GATHER_TABLE_STAT_ALL
|
||||
* @desc Multi-level batch statistics gathering procedure with three granularity levels.
|
||||
* Processes configurations based on ARCHIVE_ENABLED setting (when pOnlyEnabled=TRUE).
|
||||
* Gathers statistics for external tables and inserts data into A_TABLE_STAT and A_TABLE_STAT_HIST.
|
||||
* @param pSourceFileConfigKey - (LEVEL 1) Gather stats for specific configuration key (highest priority)
|
||||
* @param pSourceKey - (LEVEL 2) Gather stats for all tables in source system (e.g., 'LM', 'C2D') (medium priority)
|
||||
* @param pGatherAll - (LEVEL 3) When TRUE, gather stats for ALL tables across all sources (lowest priority)
|
||||
* @param pOnlyEnabled - When TRUE (default), only process tables with ARCHIVE_ENABLED='Y'
|
||||
* @example -- Level 1: CALL FILE_ARCHIVER.GATHER_TABLE_STAT_ALL(pSourceFileConfigKey => 123);
|
||||
* @example -- Level 2: CALL FILE_ARCHIVER.GATHER_TABLE_STAT_ALL(pSourceKey => 'LM');
|
||||
* @example -- Level 3: CALL FILE_ARCHIVER.GATHER_TABLE_STAT_ALL(pGatherAll => TRUE);
|
||||
* @example -- All tables regardless of ARCHIVE_ENABLED: CALL FILE_ARCHIVER.GATHER_TABLE_STAT_ALL(pGatherAll => TRUE, pOnlyEnabled => FALSE);
|
||||
**/
|
||||
PROCEDURE GATHER_TABLE_STAT_ALL (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pSourceKey IN CT_MRDS.A_SOURCE.A_SOURCE_KEY%TYPE DEFAULT NULL,
|
||||
pGatherAll IN BOOLEAN DEFAULT FALSE,
|
||||
pOnlyEnabled IN BOOLEAN DEFAULT TRUE
|
||||
);
|
||||
|
||||
/**
|
||||
* @name FN_GATHER_TABLE_STAT_ALL
|
||||
* @desc Function wrapper for GATHER_TABLE_STAT_ALL procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main GATHER_TABLE_STAT_ALL procedure and captures execution result.
|
||||
* @param pSourceFileConfigKey - (LEVEL 1) Gather stats for specific configuration key (highest priority)
|
||||
* @param pSourceKey - (LEVEL 2) Gather stats for all tables in source system (medium priority)
|
||||
* @param pGatherAll - (LEVEL 3) When TRUE, gather stats for ALL tables across all sources (lowest priority)
|
||||
* @param pOnlyEnabled - When TRUE (default), only process tables with ARCHIVE_ENABLED='Y'
|
||||
* @example SELECT FILE_ARCHIVER.FN_GATHER_TABLE_STAT_ALL(pSourceKey => 'LM') FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION FN_GATHER_TABLE_STAT_ALL (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pSourceKey IN CT_MRDS.A_SOURCE.A_SOURCE_KEY%TYPE DEFAULT NULL,
|
||||
pGatherAll IN BOOLEAN DEFAULT FALSE,
|
||||
pOnlyEnabled IN BOOLEAN DEFAULT TRUE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
/**
|
||||
* @name ARCHIVE_ALL
|
||||
* @desc Multi-level batch archival procedure with three granularity levels.
|
||||
* Only processes configurations where ARCHIVE_ENABLED='Y'.
|
||||
* TRASH policy for each table is controlled by individual KEEP_IN_TRASH column.
|
||||
* @param pSourceFileConfigKey - (LEVEL 1) Archive specific configuration key (highest priority)
|
||||
* @param pSourceKey - (LEVEL 2) Archive all enabled tables for source system (e.g., 'LM', 'C2D') (medium priority)
|
||||
* @param pArchiveAll - (LEVEL 3) When TRUE, archive ALL enabled tables across all sources (lowest priority)
|
||||
* @example -- Level 1: CALL FILE_ARCHIVER.ARCHIVE_ALL(pSourceFileConfigKey => 123);
|
||||
* @example -- Level 2: CALL FILE_ARCHIVER.ARCHIVE_ALL(pSourceKey => 'LM');
|
||||
* @example -- Level 3: CALL FILE_ARCHIVER.ARCHIVE_ALL(pArchiveAll => TRUE);
|
||||
**/
|
||||
PROCEDURE ARCHIVE_ALL (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pSourceKey IN CT_MRDS.A_SOURCE.A_SOURCE_KEY%TYPE DEFAULT NULL,
|
||||
pArchiveAll IN BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
|
||||
/**
|
||||
* @name FN_ARCHIVE_ALL
|
||||
* @desc Function wrapper for ARCHIVE_ALL procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main ARCHIVE_ALL procedure and captures execution result.
|
||||
* @param pSourceFileConfigKey - (LEVEL 1) Archive specific configuration key (highest priority)
|
||||
* @param pSourceKey - (LEVEL 2) Archive all enabled tables for source system (medium priority)
|
||||
* @param pArchiveAll - (LEVEL 3) When TRUE, archive ALL enabled tables across all sources (lowest priority)
|
||||
* @example SELECT FILE_ARCHIVER.FN_ARCHIVE_ALL(pSourceKey => 'LM') FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION FN_ARCHIVE_ALL (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pSourceKey IN CT_MRDS.A_SOURCE.A_SOURCE_KEY%TYPE DEFAULT NULL,
|
||||
pArchiveAll IN BOOLEAN DEFAULT FALSE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
/**
|
||||
* @name RESTORE_FILE_FROM_TRASH
|
||||
* @desc Restores files from TRASH folder back to ODS at three different granularity levels.
|
||||
* Moves files from TRASH subfolder back to ODS subfolder in DATA bucket.
|
||||
* Updates status from ARCHIVED_AND_TRASHED to INGESTED and clears archival metadata.
|
||||
* @param pSourceFileReceivedKey - (LEVEL 3) Specific file to restore by A_SOURCE_FILE_RECEIVED_KEY (highest priority)
|
||||
* @param pSourceFileConfigKey - (LEVEL 2) Restore all files for specific configuration key (medium priority)
|
||||
* @param pRestoreAll - (LEVEL 1) When TRUE, restore ALL files with ARCHIVED_AND_TRASHED status (lowest priority)
|
||||
* @example -- Restore single file: CALL FILE_ARCHIVER.RESTORE_FILE_FROM_TRASH(pSourceFileReceivedKey => 12345);
|
||||
* @example -- Restore all files for config: CALL FILE_ARCHIVER.RESTORE_FILE_FROM_TRASH(pSourceFileConfigKey => 341);
|
||||
* @example -- Restore all TRASH globally: CALL FILE_ARCHIVER.RESTORE_FILE_FROM_TRASH(pRestoreAll => TRUE);
|
||||
**/
|
||||
PROCEDURE RESTORE_FILE_FROM_TRASH (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pRestoreAll IN BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
|
||||
/**
|
||||
* @name RESTORE_FILE_FROM_TRASH
|
||||
* @desc Function overload for RESTORE_FILE_FROM_TRASH procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main RESTORE_FILE_FROM_TRASH procedure and captures execution result.
|
||||
* @param pSourceFileReceivedKey - (LEVEL 3) Specific file to restore by A_SOURCE_FILE_RECEIVED_KEY (highest priority)
|
||||
* @param pSourceFileConfigKey - (LEVEL 2) Restore all files for specific configuration key (medium priority)
|
||||
* @param pRestoreAll - (LEVEL 1) When TRUE, restore ALL files with ARCHIVED_AND_TRASHED status (lowest priority)
|
||||
* @example SELECT FILE_ARCHIVER.RESTORE_FILE_FROM_TRASH(pSourceFileReceivedKey => 12345) FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION RESTORE_FILE_FROM_TRASH (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pRestoreAll IN BOOLEAN DEFAULT FALSE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
/**
|
||||
* @name PURGE_TRASH_FOLDER
|
||||
* @desc Deletes files from TRASH folder at three different granularity levels.
|
||||
* Updates status from ARCHIVED_AND_TRASHED to ARCHIVED_AND_PURGED for all affected files.
|
||||
* WARNING: This operation is irreversible - files are permanently deleted from TRASH.
|
||||
* @param pSourceFileReceivedKey - (LEVEL 3) Specific file to delete by A_SOURCE_FILE_RECEIVED_KEY (highest priority)
|
||||
* @param pSourceFileConfigKey - (LEVEL 2) Delete all files for specific configuration key (medium priority)
|
||||
* @param pPurgeAll - (LEVEL 1) When TRUE, delete ALL files with ARCHIVED_AND_TRASHED status (lowest priority)
|
||||
* @example -- Delete single file: CALL FILE_ARCHIVER.PURGE_TRASH_FOLDER(pSourceFileReceivedKey => 12345);
|
||||
* @example -- Delete all files for config: CALL FILE_ARCHIVER.PURGE_TRASH_FOLDER(pSourceFileConfigKey => 341);
|
||||
* @example -- Delete all TRASH globally: CALL FILE_ARCHIVER.PURGE_TRASH_FOLDER(pPurgeAll => TRUE);
|
||||
**/
|
||||
PROCEDURE PURGE_TRASH_FOLDER (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pPurgeAll IN BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
|
||||
/**
|
||||
* @name PURGE_TRASH_FOLDER
|
||||
* @desc Function overload for PURGE_TRASH_FOLDER procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main PURGE_TRASH_FOLDER procedure and captures execution result.
|
||||
* WARNING: This operation is irreversible - files are permanently deleted from TRASH.
|
||||
* @param pSourceFileReceivedKey - (LEVEL 3) Specific file to delete by A_SOURCE_FILE_RECEIVED_KEY (highest priority)
|
||||
* @param pSourceFileConfigKey - (LEVEL 2) Delete all files for specific configuration key (medium priority)
|
||||
* @param pPurgeAll - (LEVEL 1) When TRUE, delete ALL files with ARCHIVED_AND_TRASHED status (lowest priority)
|
||||
* @example SELECT FILE_ARCHIVER.PURGE_TRASH_FOLDER(pSourceFileReceivedKey => 12345) FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION PURGE_TRASH_FOLDER (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pPurgeAll IN BOOLEAN DEFAULT FALSE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
-- PACKAGE VERSION MANAGEMENT FUNCTIONS
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -20,10 +20,10 @@ BEGIN
|
||||
RAISE_APPLICATION_ERROR(-20999, vErrorMsg);
|
||||
END IF;
|
||||
|
||||
-- Validate MINIMUM_AGE_MONTHS is positive
|
||||
-- Validate MINIMUM_AGE_MONTHS is non-negative (0 = current month only)
|
||||
IF :NEW.MINIMUM_AGE_MONTHS IS NOT NULL
|
||||
AND :NEW.MINIMUM_AGE_MONTHS < 1 THEN
|
||||
RAISE_APPLICATION_ERROR(-20998, 'MINIMUM_AGE_MONTHS must be greater than 0');
|
||||
AND :NEW.MINIMUM_AGE_MONTHS < 0 THEN
|
||||
RAISE_APPLICATION_ERROR(-20998, 'MINIMUM_AGE_MONTHS must be greater than or equal to 0');
|
||||
END IF;
|
||||
|
||||
-- Warn if MINIMUM_AGE_MONTHS set but strategy doesn't use it
|
||||
|
||||
@@ -29,13 +29,15 @@ PROMPT
|
||||
PROMPT ============================================================================
|
||||
PROMPT MARS-828 Rollback Starting
|
||||
PROMPT ============================================================================
|
||||
PROMPT WARNING: This will restore FILE_ARCHIVER to v2.0.0
|
||||
PROMPT This will restore FILE_ARCHIVER to v2.0.0
|
||||
PROMPT
|
||||
PROMPT CRITICAL IMPACT:
|
||||
PROMPT 1. All archival strategies revert to THRESHOLD_BASED
|
||||
PROMPT 2. ARCHIVAL_STRATEGY and MINIMUM_AGE_MONTHS columns will be dropped
|
||||
PROMPT 3. Validation trigger will be removed
|
||||
PROMPT 4. Reconfigure archival thresholds after rollback
|
||||
PROMPT Rollback steps:
|
||||
PROMPT 1. Rollback TRASH retention statuses
|
||||
PROMPT 2. Revoke T_FILENAME privileges
|
||||
PROMPT 3. Remove validation trigger
|
||||
PROMPT 4. Drop all configuration columns (ARCHIVAL_STRATEGY, MINIMUM_AGE_MONTHS, ARCHIVE_ENABLED, KEEP_IN_TRASH)
|
||||
PROMPT 5. Restore FILE_ARCHIVER package to v2.0.0
|
||||
PROMPT 6. Revert all archival strategies to THRESHOLD_BASED
|
||||
PROMPT
|
||||
PROMPT Timestamp:
|
||||
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') AS rollback_start FROM DUAL;
|
||||
@@ -54,32 +56,37 @@ WHENEVER SQLERROR CONTINUE
|
||||
|
||||
-- Rollback steps (in reverse order)
|
||||
PROMPT
|
||||
PROMPT Step 1/6: Restoring FILE_ARCHIVER Package Specification v2.0.0
|
||||
PROMPT ===============================================================
|
||||
@@91_MARS_828_rollback_FILE_ARCHIVER_SPEC.sql
|
||||
PROMPT Step 1/7: Rolling back TRASH retention statuses
|
||||
PROMPT ================================================
|
||||
@@90_MARS_828_rollback_trash_retention_statuses.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 2/6: Restoring FILE_ARCHIVER Package Body v2.0.0
|
||||
PROMPT ======================================================
|
||||
@@92_MARS_828_rollback_FILE_ARCHIVER_BODY.sql
|
||||
PROMPT Step 2/7: Revoking T_FILENAME privileges from MRDS_LOADER
|
||||
PROMPT ==========================================================
|
||||
@@95_MARS_828_rollback_grant_t_filename.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 3/6: Dropping validation trigger
|
||||
PROMPT Step 3/7: Dropping validation trigger
|
||||
PROMPT ======================================
|
||||
@@93_MARS_828_rollback_trigger.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 4/6: Dropping archival strategy columns
|
||||
PROMPT =============================================
|
||||
PROMPT Step 4/7: Dropping all archival configuration columns
|
||||
PROMPT ======================================================
|
||||
@@94_MARS_828_rollback_columns.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 5/6: Tracking rollback version
|
||||
PROMPT ====================================
|
||||
@@track_package_versions.sql
|
||||
PROMPT Step 5/7: Restoring FILE_ARCHIVER Package Specification v2.0.0
|
||||
PROMPT ===============================================================
|
||||
@@91_MARS_828_rollback_FILE_ARCHIVER_SPEC.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 6/6: Verifying tracked packages
|
||||
PROMPT Step 6/7: Restoring FILE_ARCHIVER Package Body v2.0.0
|
||||
PROMPT ======================================================
|
||||
@@92_MARS_828_rollback_FILE_ARCHIVER_BODY.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT Step 7/7: Verifying tracked packages
|
||||
PROMPT =====================================
|
||||
@@verify_packages_version.sql
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ AS
|
||||
BEGIN
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED r
|
||||
SET PROCESSING_STATUS = 'ARCHIVED'
|
||||
,ARCH_FILE_NAME = vUri||vFilename
|
||||
,ARCH_PATH = vUri||vFilename
|
||||
WHERE r.a_source_file_config_key= pSourceFileConfigKey
|
||||
AND r.source_file_name = f.filename
|
||||
AND r.processing_status = 'INGESTED'
|
||||
@@ -244,7 +244,7 @@ AS
|
||||
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED r
|
||||
SET PROCESSING_STATUS = 'INGESTED'
|
||||
,ARCH_FILE_NAME = NULL
|
||||
,ARCH_PATH = NULL
|
||||
WHERE r.a_source_file_config_key = pSourceFileConfigKey
|
||||
AND r.source_file_name = f.filename
|
||||
;
|
||||
|
||||
@@ -231,7 +231,7 @@ AS
|
||||
BEGIN
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED r
|
||||
SET PROCESSING_STATUS = 'ARCHIVED'
|
||||
,ARCH_FILE_NAME = vUri||vFilename
|
||||
,ARCH_PATH = vUri||vFilename
|
||||
WHERE r.a_source_file_config_key= pSourceFileConfigKey
|
||||
AND r.source_file_name = f.filename
|
||||
AND r.processing_status = 'INGESTED'
|
||||
@@ -294,7 +294,7 @@ AS
|
||||
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED r
|
||||
SET PROCESSING_STATUS = 'INGESTED'
|
||||
,ARCH_FILE_NAME = NULL
|
||||
,ARCH_PATH = NULL
|
||||
WHERE r.a_source_file_config_key = pSourceFileConfigKey
|
||||
AND r.source_file_name = f.filename
|
||||
;
|
||||
|
||||
@@ -0,0 +1,998 @@
|
||||
create or replace PACKAGE BODY CT_MRDS.FILE_ARCHIVER
|
||||
AS
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
-- PRIVATE FUNCTION: GET_ARCHIVAL_WHERE_CLAUSE
|
||||
----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @name GET_ARCHIVAL_WHERE_CLAUSE
|
||||
* @desc Private function that generates WHERE clause based on ARCHIVAL_STRATEGY configuration.
|
||||
* Supports three strategies: THRESHOLD_BASED, MINIMUM_AGE_MONTHS, HYBRID.
|
||||
* @param pSourceFileConfig - Source file configuration record with ARCHIVAL_STRATEGY
|
||||
* @return VARCHAR2 - WHERE clause for filtering archival candidates
|
||||
**/
|
||||
FUNCTION GET_ARCHIVAL_WHERE_CLAUSE(
|
||||
pSourceFileConfig IN CT_MRDS.A_SOURCE_FILE_CONFIG%ROWTYPE
|
||||
) RETURN VARCHAR2
|
||||
IS
|
||||
vWhereClause VARCHAR2(4000);
|
||||
cgBL CONSTANT VARCHAR2(2) := CHR(13)||CHR(10);
|
||||
BEGIN
|
||||
CASE pSourceFileConfig.ARCHIVAL_STRATEGY
|
||||
-- Legacy threshold-based strategy (backward compatible)
|
||||
WHEN 'THRESHOLD_BASED' THEN
|
||||
vWhereClause := 'extract(day from (systimestamp - workflow_start)) > ' || pSourceFileConfig.DAYS_FOR_ARCHIVE_THRESHOLD;
|
||||
|
||||
-- Archive data older than X months (0 = current month only)
|
||||
WHEN 'MINIMUM_AGE_MONTHS' THEN
|
||||
IF pSourceFileConfig.MINIMUM_AGE_MONTHS IS NULL THEN
|
||||
RAISE_APPLICATION_ERROR(-20001, 'MINIMUM_AGE_MONTHS must be configured for MINIMUM_AGE_MONTHS strategy');
|
||||
END IF;
|
||||
vWhereClause := 'workflow_start < ADD_MONTHS(TRUNC(SYSDATE, ''MM''), -' || pSourceFileConfig.MINIMUM_AGE_MONTHS || ')';
|
||||
|
||||
-- Hybrid: Current month exclusion AND minimum age requirement
|
||||
WHEN 'HYBRID' THEN
|
||||
IF pSourceFileConfig.MINIMUM_AGE_MONTHS IS NULL THEN
|
||||
RAISE_APPLICATION_ERROR(-20001, 'MINIMUM_AGE_MONTHS must be configured for HYBRID strategy');
|
||||
END IF;
|
||||
vWhereClause := 'TRUNC(workflow_start, ''MM'') < TRUNC(SYSDATE, ''MM'') ' ||
|
||||
'AND workflow_start < ADD_MONTHS(TRUNC(SYSDATE, ''MM''), -' || pSourceFileConfig.MINIMUM_AGE_MONTHS || ')';
|
||||
|
||||
ELSE
|
||||
RAISE_APPLICATION_ERROR(-20002, 'Invalid ARCHIVAL_STRATEGY: ' || pSourceFileConfig.ARCHIVAL_STRATEGY);
|
||||
END CASE;
|
||||
|
||||
RETURN vWhereClause;
|
||||
END GET_ARCHIVAL_WHERE_CLAUSE;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION GET_TABLE_STAT(pSourceFileConfigKey IN NUMBER)
|
||||
RETURN CT_MRDS.A_TABLE_STAT%ROWTYPE
|
||||
IS
|
||||
vTableStat CT_MRDS.A_TABLE_STAT%ROWTYPE;
|
||||
vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE;
|
||||
vCount PLS_INTEGER;
|
||||
vSourceFileType CT_MRDS.A_SOURCE_FILE_CONFIG.SOURCE_FILE_TYPE%TYPE;
|
||||
|
||||
BEGIN
|
||||
vParameters := CT_MRDS.ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST('pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey),NULL)));
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Start','DEBUG', vParameters);
|
||||
SELECT count(*) , min(SOURCE_FILE_TYPE)
|
||||
INTO vCount, vSourceFileType
|
||||
FROM CT_MRDS.A_TABLE_STAT s
|
||||
JOIN CT_MRDS.A_SOURCE_FILE_CONFIG c
|
||||
ON s.A_SOURCE_FILE_CONFIG_KEY = c.A_SOURCE_FILE_CONFIG_KEY
|
||||
WHERE s.A_SOURCE_FILE_CONFIG_KEY = pSourceFileConfigKey;
|
||||
|
||||
IF vCount=0 and vSourceFileType='INPUT' THEN
|
||||
GATHER_TABLE_STAT(pSourceFileConfigKey);
|
||||
END IF;
|
||||
|
||||
BEGIN
|
||||
SELECT *
|
||||
INTO vTableStat
|
||||
FROM CT_MRDS.A_TABLE_STAT
|
||||
WHERE A_SOURCE_FILE_CONFIG_KEY = pSourceFileConfigKey;
|
||||
-- EXCEPTION
|
||||
-- WHEN NO_DATA_FOUND THEN
|
||||
--
|
||||
END;
|
||||
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End','DEBUG',vParameters);
|
||||
RETURN vTableStat;
|
||||
|
||||
END GET_TABLE_STAT;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
PROCEDURE ARCHIVE_TABLE_DATA (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE,
|
||||
pKeepInTrash IN BOOLEAN DEFAULT TRUE
|
||||
)
|
||||
IS
|
||||
vSourceFileConfig CT_MRDS.A_SOURCE_FILE_CONFIG%ROWTYPE;
|
||||
vTableStat CT_MRDS.A_TABLE_STAT%ROWTYPE;
|
||||
vQuery VARCHAR2(4000);
|
||||
vTableName VARCHAR2(200);
|
||||
vUri VARCHAR2(1000);
|
||||
vfiles T_FILENAMES;
|
||||
vFilename VARCHAR2(300);
|
||||
vOperationId NUMBER := -1;
|
||||
vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE;
|
||||
vArchivalTriggeredBy VARCHAR2(60); -- Possible values: FILES_COUNT, ROWS_COUNT, BYTES_SUM
|
||||
vUserLoadOperations USER_LOAD_OPERATIONS%ROWTYPE;
|
||||
vProcessControlStatus VARCHAR2(60) := 'OK';
|
||||
|
||||
BEGIN
|
||||
vParameters := CT_MRDS.ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST(
|
||||
'pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey), 'NULL'),
|
||||
'pKeepInTrash => '||CASE WHEN pKeepInTrash THEN 'TRUE' ELSE 'FALSE' END
|
||||
));
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Start','INFO', vParameters);
|
||||
|
||||
vSourceFileConfig := CT_MRDS.FILE_MANAGER.GET_SOURCE_FILE_CONFIG(pSourceFileConfigKey => pSourceFileConfigKey);
|
||||
vTableStat := GET_TABLE_STAT(pSourceFileConfigKey => pSourceFileConfigKey);
|
||||
|
||||
if vSourceFileConfig.SOURCE_FILE_TYPE <> 'INPUT' then
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.MSG_NOT_INPUT_SOURCE_FILE_TYPE, 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_NOT_INPUT_SOURCE_FILE_TYPE, CT_MRDS.ENV_MANAGER.MSG_NOT_INPUT_SOURCE_FILE_TYPE);
|
||||
end if;
|
||||
|
||||
if vTableStat.created < sysdate-(vSourceFileConfig.HOURS_TO_EXPIRE_STATISTICS/24) then
|
||||
GATHER_TABLE_STAT(pSourceFileConfigKey => pSourceFileConfigKey);
|
||||
vTableStat := GET_TABLE_STAT(pSourceFileConfigKey => pSourceFileConfigKey);
|
||||
end if;
|
||||
|
||||
-- Strategy-based trigger logic (MARS-828)
|
||||
IF vSourceFileConfig.ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS' THEN
|
||||
-- MINIMUM_AGE_MONTHS: Archive based on age only, ignore thresholds
|
||||
vArchivalTriggeredBy := 'AGE_BASED';
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Archival strategy: MINIMUM_AGE_MONTHS (threshold-independent)','INFO');
|
||||
ELSE
|
||||
-- THRESHOLD_BASED and HYBRID: Check thresholds
|
||||
if vTableStat.OVER_ARCH_THRESOLD_FILE_COUNT >= vSourceFileConfig.FILES_COUNT_OVER_ARCHIVE_THRESHOLD then vArchivalTriggeredBy := 'FILES_COUNT';
|
||||
elsif vTableStat.OVER_ARCH_THRESOLD_ROW_COUNT >= vSourceFileConfig.ROWS_COUNT_OVER_ARCHIVE_THRESHOLD then vArchivalTriggeredBy := vArchivalTriggeredBy||', ROWS_COUNT';
|
||||
elsif vTableStat.OVER_ARCH_THRESOLD_SIZE >= vSourceFileConfig.BYTES_SUM_OVER_ARCHIVE_THRESHOLD then vArchivalTriggeredBy := vArchivalTriggeredBy||', BYTES_SUM';
|
||||
else CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Non of archival triggers reached','INFO');
|
||||
end if;
|
||||
END IF;
|
||||
|
||||
if LENGTH(vArchivalTriggeredBy)>0 THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Archival Triggered By: '||vArchivalTriggeredBy,'INFO');
|
||||
vTableName := DBMS_ASSERT.SCHEMA_NAME(vSourceFileConfig.ODS_SCHEMA_NAME) || '.'||DBMS_ASSERT.simple_sql_name(vSourceFileConfig.TABLE_ID)||'_ODS';
|
||||
|
||||
-- Use strategy-based WHERE clause (MARS-828)
|
||||
-- Using GROUP BY instead of DISTINCT to avoid ORA-22950 (object type ordering issue)
|
||||
vQuery := '
|
||||
select CT_MRDS.t_filename(
|
||||
file$name
|
||||
,file$path
|
||||
, to_char(h.workflow_start,''yyyy'')
|
||||
, to_char(h.workflow_start,''mm'')
|
||||
)
|
||||
from '||vTableName||' s
|
||||
join CT_MRDS.a_workflow_history h
|
||||
on s.a_workflow_history_key = h.a_workflow_history_key
|
||||
where ' || GET_ARCHIVAL_WHERE_CLAUSE(vSourceFileConfig) || '
|
||||
group by file$name, file$path, to_char(h.workflow_start,''yyyy''), to_char(h.workflow_start,''mm'')'
|
||||
;
|
||||
|
||||
-- Get all files that will be archived into "vfiles" collection ("regular data files")
|
||||
execute immediate vQuery bulk collect into vfiles;
|
||||
|
||||
-- Start EXPORT "regular data files" to parquet and DROP "csv"
|
||||
FOR ym_loop IN (select distinct year, month from table(vfiles) order by 1,2) LOOP
|
||||
dbms_output.put_line('year: '||ym_loop.year||' - '||'month: '||ym_loop.month);
|
||||
vQuery:=
|
||||
'select
|
||||
s.*
|
||||
from '|| vTableName ||' s
|
||||
join CT_MRDS.A_SOURCE_FILE_RECEIVED r
|
||||
on s.file$name = r.source_file_name
|
||||
and r.a_source_file_config_key = '||pSourceFileConfigKey||'
|
||||
and r.PROCESSING_STATUS = ''INGESTED''
|
||||
join CT_MRDS.a_workflow_history h
|
||||
on s.a_workflow_history_key = h.a_workflow_history_key
|
||||
and to_char(h.workflow_start,''yyyy'') = '''||ym_loop.year||'''
|
||||
and to_char(h.workflow_start,''mm'') = '''||ym_loop.month||'''
|
||||
'
|
||||
;
|
||||
vUri := CT_MRDS.FILE_MANAGER.GET_BUCKET_URI('ARCHIVE')||vSourceFileConfig.A_SOURCE_KEY||'/'||vSourceFileConfig.TABLE_ID||'/PARTITION_YEAR='||ym_loop.year||'/PARTITION_MONTH='||ym_loop.month||'/';
|
||||
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Start Archiving for YEAR_MONTH: '||ym_loop.year||'_'||ym_loop.month ,'INFO');
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Parameter for DBMS_CLOUD.EXPORT_DATA => file_uri_list' ,'DEBUG',vUri);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Parameter for DBMS_CLOUD.EXPORT_DATA => query' ,'DEBUG',vQuery);
|
||||
|
||||
|
||||
|
||||
BEGIN
|
||||
DBMS_CLOUD.EXPORT_DATA(
|
||||
credential_name => ENV_MANAGER.gvCredentialName,
|
||||
file_uri_list => vUri||'d' ,
|
||||
format => json_object('type' value 'parquet'),
|
||||
query => vQuery,
|
||||
operation_id => vOperationId
|
||||
);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
vProcessControlStatus :='EXPORT_FAILURE';
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_EXP_DATA_FOR_ARCH_FAILED, CT_MRDS.ENV_MANAGER.MSG_EXP_DATA_FOR_ARCH_FAILED);
|
||||
|
||||
END;
|
||||
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('vOperationId of export: '||vOperationId,'DEBUG');
|
||||
|
||||
-- Get USER_LOAD_OPERATIONS info
|
||||
select *
|
||||
into vUserLoadOperations
|
||||
from USER_LOAD_OPERATIONS
|
||||
where id = vOperationId;
|
||||
|
||||
IF vUserLoadOperations.STATUS <>'COMPLETED' THEN
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_EXP_DATA_FOR_ARCH_FAILED,
|
||||
CT_MRDS.ENV_MANAGER.MSG_EXP_DATA_FOR_ARCH_FAILED ||cgBL|| ' Export ended with status '||vUserLoadOperations.STATUS);
|
||||
ELSIF vUserLoadOperations.STATUS = 'COMPLETED' and vUserLoadOperations.ROWS_LOADED = 0 THEN
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_EXP_DATA_FOR_ARCH_FAILED,
|
||||
CT_MRDS.ENV_MANAGER.MSG_EXP_DATA_FOR_ARCH_FAILED ||cgBL|| ' Zero rows were exported.');
|
||||
ELSE
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Data exported to archival file for YEAR_MONTH: '||ym_loop.year||'_'||ym_loop.month,'INFO', vParameters);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.FILE_MANAGER.GET_DET_USER_LOAD_OPERATIONS (pOperationId => vOperationId),'DEBUG', vParameters);
|
||||
END IF;
|
||||
|
||||
-- Note: DBMS_CLOUD.EXPORT_DATA may create multiple parquet files (parallel execution)
|
||||
-- Instead of tracking individual files, we store the archive directory prefix
|
||||
-- ARCH_PATH will contain the directory URI where all parquet files are located
|
||||
vFilename := vUri; -- Store directory prefix instead of individual filename
|
||||
|
||||
-- Try to drop EXPORTED FILES ("regular data files")
|
||||
BEGIN
|
||||
FOR f in (select filename, pathname from table(vfiles) where year = ym_loop.year and month = ym_loop.month) loop
|
||||
|
||||
-- first change of status to ARCHIVED_AND_TRASHED (file will be moved to TRASH folder)
|
||||
BEGIN
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED r
|
||||
SET PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED' -- Status reflects file is archived and kept in TRASH
|
||||
,ARCH_PATH = vFilename -- Now contains directory prefix, not individual file
|
||||
,PARTITION_YEAR = ym_loop.year -- Record which partition year the data was archived to
|
||||
,PARTITION_MONTH = ym_loop.month -- Record which partition month the data was archived to
|
||||
WHERE r.a_source_file_config_key= pSourceFileConfigKey
|
||||
AND r.source_file_name = f.filename
|
||||
AND r.processing_status = 'INGESTED'
|
||||
;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
vProcessControlStatus := 'CHANGE_STATUS_TO_ARCHIVED_AND_TRASHED_FAILURE';
|
||||
END;
|
||||
EXIT WHEN vProcessControlStatus = 'CHANGE_STATUS_TO_ARCHIVED_AND_TRASHED_FAILURE';
|
||||
|
||||
-- move file to TRASH subfolder (DATA bucket: ODS/ → TRASH/) before dropping
|
||||
BEGIN
|
||||
DBMS_CLOUD.MOVE_OBJECT(source_credential_name => ENV_MANAGER.gvCredentialName,
|
||||
source_object_uri => f.pathname||'/'||f.filename,
|
||||
target_object_uri => replace(f.pathname,'ODS','TRASH')||'/'||f.filename,
|
||||
target_credential_name => ENV_MANAGER.gvCredentialName
|
||||
);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('File moved to TRASH folder.','DEBUG', f.pathname||'/'||f.filename);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Failed to move file to TRASH folder.','ERROR', f.pathname||'/'||f.filename);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
rollback;
|
||||
vProcessControlStatus := 'MOVE_FILE_TO_TRASH_FAILURE';
|
||||
END;
|
||||
EXIT WHEN vProcessControlStatus = 'MOVE_FILE_TO_TRASH_FAILURE';
|
||||
commit;
|
||||
END LOOP;
|
||||
|
||||
--------------------------------------------------------------------
|
||||
-- IF All goes fine till this point, we drop files from TRASH folder (if not then ROLLBACK PART)
|
||||
-- TRASH is a subfolder in DATA bucket (e.g., TRASH/LM/TABLE_NAME instead of ODS/LM/TABLE_NAME)
|
||||
IF vProcessControlStatus = 'OK' THEN
|
||||
IF NOT pKeepInTrash THEN
|
||||
-- Delete files from TRASH folder (cleanup) and update status to ARCHIVED_AND_PURGED
|
||||
FOR f in (select filename, pathname from table(vfiles) where year = ym_loop.year and month = ym_loop.month) LOOP
|
||||
DBMS_CLOUD.DELETE_OBJECT(credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
object_uri => replace(f.pathname,'ODS','TRASH')||'/'||f.filename);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('File dropped from TRASH folder.','DEBUG', f.pathname||'/'||f.filename);
|
||||
|
||||
-- Update status to ARCHIVED_AND_PURGED
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED r
|
||||
SET PROCESSING_STATUS = 'ARCHIVED_AND_PURGED'
|
||||
WHERE r.a_source_file_config_key = pSourceFileConfigKey
|
||||
AND r.source_file_name = f.filename
|
||||
AND r.PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED';
|
||||
END LOOP;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('All archived files removed from TRASH folder and marked as ARCHIVED_AND_PURGED.','INFO');
|
||||
ELSE
|
||||
-- Keep files in TRASH folder (status remains ARCHIVED_AND_TRASHED)
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Archived files kept in TRASH folder for retention (status: ARCHIVED_AND_TRASHED).','INFO');
|
||||
END IF;
|
||||
|
||||
--ROLLBACK PART
|
||||
--ROLLBACK PROCESS in case of FAILURE (restore files from TRASH subfolder in DATA bucket)
|
||||
ELSIF vProcessControlStatus = 'MOVE_FILE_TO_TRASH_FAILURE' THEN
|
||||
FOR f in ( SELECT vf.filename, vf.pathname
|
||||
FROM TABLE(vfiles) vf
|
||||
JOIN CT_MRDS.A_SOURCE_FILE_RECEIVED r
|
||||
ON r.source_file_name = vf.filename
|
||||
AND r.a_source_file_config_key = pSourceFileConfigKey
|
||||
AND r.PROCESSING_STATUS IN ('ARCHIVED_AND_TRASHED', 'ARCHIVED_AND_PURGED')
|
||||
AND vf.year = ym_loop.year
|
||||
AND vf.month = ym_loop.month
|
||||
) LOOP
|
||||
BEGIN
|
||||
DBMS_CLOUD.MOVE_OBJECT(source_credential_name => ENV_MANAGER.gvCredentialName,
|
||||
source_object_uri => replace(f.pathname,'ODS','TRASH')||'/'||f.filename,
|
||||
target_object_uri => f.pathname||'/'||f.filename,
|
||||
target_credential_name => ENV_MANAGER.gvCredentialName
|
||||
);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('File restored from TRASH folder.','DEBUG', f.pathname||'/'||f.filename);
|
||||
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED r
|
||||
SET PROCESSING_STATUS = 'INGESTED'
|
||||
,ARCH_PATH = NULL
|
||||
WHERE r.a_source_file_config_key = pSourceFileConfigKey
|
||||
AND r.source_file_name = f.filename
|
||||
;
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Failed to restore file from TRASH folder.','ERROR', replace(f.pathname,'ODS','TRASH')||'/'||f.filename);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
vProcessControlStatus := 'RESTORE_FILE_FROM_TRASH_FAILURE';
|
||||
END;
|
||||
END LOOP;
|
||||
|
||||
-- ROLLBACK: Delete all parquet files from archive directory
|
||||
FOR arch_file IN (
|
||||
SELECT object_name
|
||||
FROM DBMS_CLOUD.LIST_OBJECTS(
|
||||
credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
location_uri => vFilename -- vFilename now contains directory prefix
|
||||
)
|
||||
) LOOP
|
||||
DBMS_CLOUD.DELETE_OBJECT(
|
||||
credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
object_uri => vFilename || arch_file.object_name
|
||||
);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('ROLLBACK operation: Archival PARQUET file dropped.','DEBUG', vFilename || arch_file.object_name);
|
||||
END LOOP;
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_MOVE_FILE_TO_TRASH_FAILED, CT_MRDS.ENV_MANAGER.MSG_MOVE_FILE_TO_TRASH_FAILED);
|
||||
|
||||
ELSIF vProcessControlStatus = 'CHANGE_STATUS_TO_ARCHIVED_FAILURE' THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.MSG_CHANGE_STAT_TO_ARCHIVED_FAILED, 'ERROR', vParameters);
|
||||
-- ROLLBACK: Delete all parquet files from archive directory
|
||||
FOR arch_file IN (
|
||||
SELECT object_name
|
||||
FROM DBMS_CLOUD.LIST_OBJECTS(
|
||||
credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
location_uri => vFilename -- vFilename now contains directory prefix
|
||||
)
|
||||
) LOOP
|
||||
DBMS_CLOUD.DELETE_OBJECT(
|
||||
credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
object_uri => vFilename || arch_file.object_name
|
||||
);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Archival PARQUET file dropped.','DEBUG', vFilename || arch_file.object_name);
|
||||
END LOOP;
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_CHANGE_STAT_TO_ARCHIVED_FAILED, CT_MRDS.ENV_MANAGER.MSG_CHANGE_STAT_TO_ARCHIVED_FAILED);
|
||||
|
||||
ELSIF vProcessControlStatus = 'RESTORE_FILE_FROM_TRASH_FAILURE' THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Some files were not restored from TRASH. Check A_PROCESS_LOG table for details','ERROR');
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_RESTORE_FILE_FROM_TRASH, CT_MRDS.ENV_MANAGER.MSG_RESTORE_FILE_FROM_TRASH);
|
||||
END IF;
|
||||
|
||||
EXCEPTION
|
||||
WHEN CT_MRDS.ENV_MANAGER.ERR_CHANGE_STAT_TO_ARCHIVED_FAILED THEN
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_CHANGE_STAT_TO_ARCHIVED_FAILED, CT_MRDS.ENV_MANAGER.MSG_CHANGE_STAT_TO_ARCHIVED_FAILED);
|
||||
|
||||
WHEN CT_MRDS.ENV_MANAGER.ERR_MOVE_FILE_TO_TRASH_FAILED THEN
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_MOVE_FILE_TO_TRASH_FAILED, CT_MRDS.ENV_MANAGER.MSG_MOVE_FILE_TO_TRASH_FAILED);
|
||||
|
||||
WHEN CT_MRDS.ENV_MANAGER.ERR_RESTORE_FILE_FROM_TRASH THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_RESTORE_FILE_FROM_TRASH, CT_MRDS.ENV_MANAGER.MSG_RESTORE_FILE_FROM_TRASH);
|
||||
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Error during archiving process','ERROR');
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_DROP_EXPORTED_FILES_FAILED, CT_MRDS.ENV_MANAGER.MSG_DROP_EXPORTED_FILES_FAILED);
|
||||
END;
|
||||
-- END of "Try to drop EXPORTED FILES"
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End Archiving for YEAR_MONTH: '||ym_loop.year||'_'||ym_loop.month ,'INFO');
|
||||
END LOOP; --ym_loop end (YEAR_MONTH)
|
||||
|
||||
COMMIT;
|
||||
|
||||
ELSE
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Non of archival thresholds reached. Skip archiving.'||vArchivalTriggeredBy,'INFO');
|
||||
END IF;
|
||||
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End','INFO',vParameters);
|
||||
EXCEPTION
|
||||
WHEN CT_MRDS.ENV_MANAGER.ERR_NOT_INPUT_SOURCE_FILE_TYPE THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.MSG_NOT_INPUT_SOURCE_FILE_TYPE , 'ERROR', vParameters);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_NOT_INPUT_SOURCE_FILE_TYPE, CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'OUTPUT', pCode=> SQLCODE));
|
||||
|
||||
WHEN CT_MRDS.ENV_MANAGER.ERR_EXP_DATA_FOR_ARCH_FAILED THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.MSG_EXP_DATA_FOR_ARCH_FAILED , 'ERROR', vParameters);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_EXP_DATA_FOR_ARCH_FAILED, CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'OUTPUT', pCode=> SQLCODE));
|
||||
|
||||
WHEN CT_MRDS.ENV_MANAGER.ERR_CHANGE_STAT_TO_ARCHIVED_FAILED THEN
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_CHANGE_STAT_TO_ARCHIVED_FAILED, CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'OUTPUT', pCode=> SQLCODE));
|
||||
|
||||
WHEN CT_MRDS.ENV_MANAGER.ERR_MOVE_FILE_TO_TRASH_FAILED THEN
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_MOVE_FILE_TO_TRASH_FAILED, CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'OUTPUT', pCode=> SQLCODE));
|
||||
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.MSG_UNKNOWN , 'ERROR', vParameters);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_UNKNOWN, CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'OUTPUT', pCode=> SQLCODE));
|
||||
|
||||
END ARCHIVE_TABLE_DATA;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
PROCEDURE GATHER_TABLE_STAT (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
) IS
|
||||
vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE;
|
||||
vStats CT_MRDS.A_TABLE_STAT%ROWTYPE;
|
||||
vSourceFileConfig CT_MRDS.A_SOURCE_FILE_CONFIG%ROWTYPE;
|
||||
vTableName VARCHAR2(200);
|
||||
vQuery VARCHAR2(32000);
|
||||
vWhereClause VARCHAR2(4000);
|
||||
vOdsBucketUri VARCHAR2(1000);
|
||||
BEGIN
|
||||
vParameters := CT_MRDS.ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST('pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey), 'NULL')));
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Start','INFO', vParameters);
|
||||
vSourceFileConfig := CT_MRDS.FILE_MANAGER.GET_SOURCE_FILE_CONFIG(pSourceFileConfigKey => pSourceFileConfigKey);
|
||||
|
||||
vTableName := DBMS_ASSERT.SCHEMA_NAME(vSourceFileConfig.ODS_SCHEMA_NAME) || '.'||DBMS_ASSERT.simple_sql_name(vSourceFileConfig.TABLE_ID)||'_ODS';
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('vTableName','DEBUG',vTableName);
|
||||
|
||||
-- Get WHERE clause based on archival strategy (MARS-828)
|
||||
vWhereClause := GET_ARCHIVAL_WHERE_CLAUSE(vSourceFileConfig);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('vWhereClause','DEBUG',vWhereClause);
|
||||
|
||||
-- Get ODS bucket URI before building query
|
||||
vOdsBucketUri := CT_MRDS.FILE_MANAGER.GET_BUCKET_URI('ODS') || 'ODS/' || vSourceFileConfig.A_SOURCE_KEY || '/' || vSourceFileConfig.TABLE_ID || '/';
|
||||
|
||||
-- Use strategy-based WHERE clause for statistics (MARS-828)
|
||||
vQuery :=
|
||||
'with tmp as (
|
||||
select
|
||||
s.*
|
||||
,file$name as filename
|
||||
,h.workflow_start
|
||||
, to_char(h.workflow_start,''yyyy'') as year
|
||||
, to_char(h.workflow_start,''mm'') as month
|
||||
from '||vTableName||' s
|
||||
join CT_MRDS.a_workflow_history h
|
||||
on s.a_workflow_history_key = h.a_workflow_history_key
|
||||
)
|
||||
, tmp_gr as (
|
||||
select
|
||||
filename, count(*) as row_count_per_file, min(workflow_start) as workflow_start
|
||||
from tmp
|
||||
group by filename
|
||||
)
|
||||
select
|
||||
NULL as A_TABLE_STAT_KEY
|
||||
,'||pSourceFileConfigKey||' as A_SOURCE_FILE_CONFIG_KEY
|
||||
,'''||vTableName||''' as TABLE_NAME
|
||||
,count(*) as FILE_COUNT
|
||||
,sum(case when ' || vWhereClause || ' then 1 else 0 end) as OLD_FILE_COUNT
|
||||
,sum (row_count_per_file) as ROW_COUNT
|
||||
,sum(case when ' || vWhereClause || ' then row_count_per_file else 0 end) as OLD_ROW_COUNT
|
||||
,sum(r.bytes) as BYTES
|
||||
,sum(case when ' || vWhereClause || ' then r.bytes else 0 end) as OLD_BYTES
|
||||
,'||COALESCE(TO_CHAR(vSourceFileConfig.DAYS_FOR_ARCHIVE_THRESHOLD), 'NULL')||' as DAYS_FOR_ARCHIVE_THRESHOLD
|
||||
,systimestamp as CREATED
|
||||
from tmp_gr t
|
||||
join (SELECT * from DBMS_CLOUD.LIST_OBJECTS(
|
||||
credential_name => '''||CT_MRDS.ENV_MANAGER.gvCredentialName||''',
|
||||
location_uri => '''||vOdsBucketUri||'''
|
||||
)
|
||||
) r
|
||||
on t.filename = r.object_name'
|
||||
;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('vQuery','DEBUG',vQuery);
|
||||
execute immediate vQuery into vStats;
|
||||
|
||||
vStats.A_TABLE_STAT_KEY := CT_MRDS.A_TABLE_STAT_KEY_SEQ.NEXTVAL;
|
||||
insert into CT_MRDS.A_TABLE_STAT_HIST values vStats;
|
||||
delete from CT_MRDS.A_TABLE_STAT where A_SOURCE_FILE_CONFIG_KEY = pSourceFileConfigKey;
|
||||
insert into CT_MRDS.A_TABLE_STAT values vStats;
|
||||
COMMIT;
|
||||
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End','INFO',vParameters);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.MSG_UNKNOWN , 'ERROR', vParameters);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_UNKNOWN, CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'OUTPUT', pCode=> SQLCODE));
|
||||
END GATHER_TABLE_STAT;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
-- TRASH FOLDER MANAGEMENT PROCEDURES
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
PROCEDURE RESTORE_FILE_FROM_TRASH (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pRestoreAll IN BOOLEAN DEFAULT FALSE
|
||||
)
|
||||
IS
|
||||
vSourceFileConfig CT_MRDS.A_SOURCE_FILE_CONFIG%ROWTYPE;
|
||||
vSourceFileReceived CT_MRDS.A_SOURCE_FILE_RECEIVED%ROWTYPE;
|
||||
vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE;
|
||||
vTrashPath VARCHAR2(1000);
|
||||
vOdsPath VARCHAR2(1000);
|
||||
vFilesRestored PLS_INTEGER := 0;
|
||||
vFilesUpdated PLS_INTEGER := 0;
|
||||
vRestoreLevel VARCHAR2(50);
|
||||
cgBL CONSTANT VARCHAR2(2) := CHR(13)||CHR(10);
|
||||
BEGIN
|
||||
vParameters := CT_MRDS.ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST(
|
||||
'pSourceFileReceivedKey => '||nvl(to_char(pSourceFileReceivedKey), 'NULL'),
|
||||
'pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey), 'NULL'),
|
||||
'pRestoreAll => '||CASE WHEN pRestoreAll THEN 'TRUE' ELSE 'FALSE' END
|
||||
));
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Start','INFO', vParameters);
|
||||
|
||||
-- Determine restore level (priority: LEVEL 3 > LEVEL 2 > LEVEL 1)
|
||||
IF pSourceFileReceivedKey IS NOT NULL THEN
|
||||
vRestoreLevel := 'LEVEL_3_SINGLE_FILE';
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Restore level: LEVEL 3 - Single file restoration','INFO', 'A_SOURCE_FILE_RECEIVED_KEY: ' || pSourceFileReceivedKey);
|
||||
|
||||
-- LEVEL 3: Restore single file by A_SOURCE_FILE_RECEIVED_KEY
|
||||
BEGIN
|
||||
SELECT *
|
||||
INTO vSourceFileReceived
|
||||
FROM CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
WHERE A_SOURCE_FILE_RECEIVED_KEY = pSourceFileReceivedKey
|
||||
AND PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED';
|
||||
|
||||
vSourceFileConfig := CT_MRDS.FILE_MANAGER.GET_SOURCE_FILE_CONFIG(pSourceFileConfigKey => vSourceFileReceived.A_SOURCE_FILE_CONFIG_KEY);
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
RAISE_APPLICATION_ERROR(-20101, 'File not found or status is not ARCHIVED_AND_TRASHED for A_SOURCE_FILE_RECEIVED_KEY: ' || pSourceFileReceivedKey);
|
||||
END;
|
||||
|
||||
vTrashPath := CT_MRDS.FILE_MANAGER.GET_BUCKET_URI('DATA') || 'TRASH/' || vSourceFileConfig.A_SOURCE_KEY || '/' || vSourceFileConfig.TABLE_ID || '/' || vSourceFileReceived.SOURCE_FILE_NAME;
|
||||
vOdsPath := CT_MRDS.FILE_MANAGER.GET_BUCKET_URI('DATA') || 'ODS/' || vSourceFileConfig.A_SOURCE_KEY || '/' || vSourceFileConfig.TABLE_ID || '/' || vSourceFileReceived.SOURCE_FILE_NAME;
|
||||
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Restoring single file from TRASH to ODS','INFO', 'Source: ' || vTrashPath || cgBL || 'Target: ' || vOdsPath);
|
||||
|
||||
BEGIN
|
||||
DBMS_CLOUD.MOVE_OBJECT(
|
||||
source_credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
source_object_uri => vTrashPath,
|
||||
target_object_uri => vOdsPath,
|
||||
target_credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName
|
||||
);
|
||||
vFilesRestored := 1;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('File successfully moved from TRASH to ODS','INFO', vSourceFileReceived.SOURCE_FILE_NAME);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Failed to move file from TRASH to ODS','ERROR', vTrashPath);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(-20103, 'Failed to restore file from TRASH: ' || SQLERRM);
|
||||
END;
|
||||
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
SET PROCESSING_STATUS = 'INGESTED',
|
||||
ARCH_PATH = NULL,
|
||||
PARTITION_YEAR = NULL,
|
||||
PARTITION_MONTH = NULL
|
||||
WHERE A_SOURCE_FILE_RECEIVED_KEY = pSourceFileReceivedKey
|
||||
AND PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED';
|
||||
vFilesUpdated := SQL%ROWCOUNT;
|
||||
|
||||
ELSIF pSourceFileConfigKey IS NOT NULL THEN
|
||||
vRestoreLevel := 'LEVEL_2_CONFIG_FILES';
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Restore level: LEVEL 2 - Configuration-based restoration','INFO', 'pSourceFileConfigKey: ' || pSourceFileConfigKey);
|
||||
|
||||
-- LEVEL 2: Restore all files for specific pSourceFileConfigKey
|
||||
vSourceFileConfig := CT_MRDS.FILE_MANAGER.GET_SOURCE_FILE_CONFIG(pSourceFileConfigKey => pSourceFileConfigKey);
|
||||
|
||||
FOR file_rec IN (
|
||||
SELECT A_SOURCE_FILE_RECEIVED_KEY, SOURCE_FILE_NAME
|
||||
FROM CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
WHERE A_SOURCE_FILE_CONFIG_KEY = pSourceFileConfigKey
|
||||
AND PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED'
|
||||
) LOOP
|
||||
vTrashPath := CT_MRDS.FILE_MANAGER.GET_BUCKET_URI('DATA') || 'TRASH/' || vSourceFileConfig.A_SOURCE_KEY || '/' || vSourceFileConfig.TABLE_ID || '/' || file_rec.SOURCE_FILE_NAME;
|
||||
vOdsPath := CT_MRDS.FILE_MANAGER.GET_BUCKET_URI('DATA') || 'ODS/' || vSourceFileConfig.A_SOURCE_KEY || '/' || vSourceFileConfig.TABLE_ID || '/' || file_rec.SOURCE_FILE_NAME;
|
||||
|
||||
BEGIN
|
||||
DBMS_CLOUD.MOVE_OBJECT(
|
||||
source_credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
source_object_uri => vTrashPath,
|
||||
target_object_uri => vOdsPath,
|
||||
target_credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName
|
||||
);
|
||||
vFilesRestored := vFilesRestored + 1;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('File restored from TRASH','DEBUG', file_rec.SOURCE_FILE_NAME);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Failed to restore file from TRASH','ERROR', file_rec.SOURCE_FILE_NAME);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
END;
|
||||
END LOOP;
|
||||
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
SET PROCESSING_STATUS = 'INGESTED',
|
||||
ARCH_PATH = NULL,
|
||||
PARTITION_YEAR = NULL,
|
||||
PARTITION_MONTH = NULL
|
||||
WHERE A_SOURCE_FILE_CONFIG_KEY = pSourceFileConfigKey
|
||||
AND PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED';
|
||||
vFilesUpdated := SQL%ROWCOUNT;
|
||||
|
||||
ELSIF pRestoreAll THEN
|
||||
vRestoreLevel := 'LEVEL_1_GLOBAL_RESTORE';
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Restore level: LEVEL 1 - Global TRASH restoration','INFO', 'Restoring ALL files with ARCHIVED_AND_TRASHED status');
|
||||
|
||||
-- LEVEL 1: Restore all files with ARCHIVED_AND_TRASHED status across all configurations
|
||||
FOR file_rec IN (
|
||||
SELECT r.A_SOURCE_FILE_RECEIVED_KEY, r.SOURCE_FILE_NAME,
|
||||
c.A_SOURCE_KEY, c.TABLE_ID
|
||||
FROM CT_MRDS.A_SOURCE_FILE_RECEIVED r
|
||||
JOIN CT_MRDS.A_SOURCE_FILE_CONFIG c ON r.A_SOURCE_FILE_CONFIG_KEY = c.A_SOURCE_FILE_CONFIG_KEY
|
||||
WHERE r.PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED'
|
||||
) LOOP
|
||||
vTrashPath := CT_MRDS.FILE_MANAGER.GET_BUCKET_URI('DATA') || 'TRASH/' || file_rec.A_SOURCE_KEY || '/' || file_rec.TABLE_ID || '/' || file_rec.SOURCE_FILE_NAME;
|
||||
vOdsPath := CT_MRDS.FILE_MANAGER.GET_BUCKET_URI('DATA') || 'ODS/' || file_rec.A_SOURCE_KEY || '/' || file_rec.TABLE_ID || '/' || file_rec.SOURCE_FILE_NAME;
|
||||
|
||||
BEGIN
|
||||
DBMS_CLOUD.MOVE_OBJECT(
|
||||
source_credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
source_object_uri => vTrashPath,
|
||||
target_object_uri => vOdsPath,
|
||||
target_credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName
|
||||
);
|
||||
vFilesRestored := vFilesRestored + 1;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('File restored from TRASH','DEBUG', file_rec.SOURCE_FILE_NAME);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Failed to restore file from TRASH','ERROR', file_rec.SOURCE_FILE_NAME);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
END;
|
||||
END LOOP;
|
||||
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
SET PROCESSING_STATUS = 'INGESTED',
|
||||
ARCH_PATH = NULL,
|
||||
PARTITION_YEAR = NULL,
|
||||
PARTITION_MONTH = NULL
|
||||
WHERE PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED';
|
||||
vFilesUpdated := SQL%ROWCOUNT;
|
||||
|
||||
ELSE
|
||||
RAISE_APPLICATION_ERROR(-20104, 'No restore level specified. Provide pSourceFileReceivedKey, pSourceFileConfigKey, or set pRestoreAll=TRUE');
|
||||
END IF;
|
||||
|
||||
COMMIT;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Total files restored from TRASH: ' || vFilesRestored,'INFO');
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Total file records updated to INGESTED: ' || vFilesUpdated,'INFO');
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('TRASH restoration completed successfully','INFO', 'Level: ' || vRestoreLevel || ', Files restored: ' || vFilesRestored || ', Records updated: ' || vFilesUpdated);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End','INFO', vParameters);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
ROLLBACK;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.MSG_UNKNOWN , 'ERROR', vParameters);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_UNKNOWN, CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'OUTPUT', pCode=> SQLCODE));
|
||||
END RESTORE_FILE_FROM_TRASH;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
PROCEDURE PURGE_TRASH_FOLDER (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pPurgeAll IN BOOLEAN DEFAULT FALSE
|
||||
)
|
||||
IS
|
||||
vSourceFileConfig CT_MRDS.A_SOURCE_FILE_CONFIG%ROWTYPE;
|
||||
vSourceFileReceived CT_MRDS.A_SOURCE_FILE_RECEIVED%ROWTYPE;
|
||||
vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE;
|
||||
vTrashLocationUri VARCHAR2(1000);
|
||||
vFilesDeleted PLS_INTEGER := 0;
|
||||
vFilesUpdated PLS_INTEGER := 0;
|
||||
vPurgeLevel VARCHAR2(50);
|
||||
cgBL CONSTANT VARCHAR2(2) := CHR(13)||CHR(10);
|
||||
BEGIN
|
||||
vParameters := CT_MRDS.ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST(
|
||||
'pSourceFileReceivedKey => '||nvl(to_char(pSourceFileReceivedKey), 'NULL'),
|
||||
'pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey), 'NULL'),
|
||||
'pPurgeAll => '||CASE WHEN pPurgeAll THEN 'TRUE' ELSE 'FALSE' END
|
||||
));
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Start','INFO', vParameters);
|
||||
|
||||
-- Determine purge level (priority: LEVEL 3 > LEVEL 2 > LEVEL 1)
|
||||
IF pSourceFileReceivedKey IS NOT NULL THEN
|
||||
vPurgeLevel := 'LEVEL_3_SINGLE_FILE';
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Purge level: LEVEL 3 - Single file deletion','INFO', 'A_SOURCE_FILE_RECEIVED_KEY: ' || pSourceFileReceivedKey);
|
||||
|
||||
-- LEVEL 3: Delete single file by A_SOURCE_FILE_RECEIVED_KEY
|
||||
BEGIN
|
||||
SELECT *
|
||||
INTO vSourceFileReceived
|
||||
FROM CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
WHERE A_SOURCE_FILE_RECEIVED_KEY = pSourceFileReceivedKey
|
||||
AND PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED';
|
||||
|
||||
vSourceFileConfig := CT_MRDS.FILE_MANAGER.GET_SOURCE_FILE_CONFIG(pSourceFileConfigKey => vSourceFileReceived.A_SOURCE_FILE_CONFIG_KEY);
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
RAISE_APPLICATION_ERROR(-20301, 'File not found or status is not ARCHIVED_AND_TRASHED for A_SOURCE_FILE_RECEIVED_KEY: ' || pSourceFileReceivedKey);
|
||||
END;
|
||||
|
||||
vTrashLocationUri := CT_MRDS.FILE_MANAGER.GET_BUCKET_URI('DATA') || 'TRASH/' || vSourceFileConfig.A_SOURCE_KEY || '/' || vSourceFileConfig.TABLE_ID || '/' || vSourceFileReceived.SOURCE_FILE_NAME;
|
||||
|
||||
BEGIN
|
||||
DBMS_CLOUD.DELETE_OBJECT(
|
||||
credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
object_uri => vTrashLocationUri
|
||||
);
|
||||
vFilesDeleted := 1;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Single file deleted from TRASH','INFO', vSourceFileReceived.SOURCE_FILE_NAME);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Failed to delete file from TRASH','ERROR', vTrashLocationUri);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(-20302, 'Failed to delete single file from TRASH: ' || SQLERRM);
|
||||
END;
|
||||
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
SET PROCESSING_STATUS = 'ARCHIVED_AND_PURGED'
|
||||
WHERE A_SOURCE_FILE_RECEIVED_KEY = pSourceFileReceivedKey
|
||||
AND PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED';
|
||||
vFilesUpdated := SQL%ROWCOUNT;
|
||||
|
||||
ELSIF pSourceFileConfigKey IS NOT NULL THEN
|
||||
vPurgeLevel := 'LEVEL_2_CONFIG_FILES';
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Purge level: LEVEL 2 - Configuration-based deletion','INFO', 'pSourceFileConfigKey: ' || pSourceFileConfigKey);
|
||||
|
||||
-- LEVEL 2: Delete all files for specific pSourceFileConfigKey
|
||||
vSourceFileConfig := CT_MRDS.FILE_MANAGER.GET_SOURCE_FILE_CONFIG(pSourceFileConfigKey => pSourceFileConfigKey);
|
||||
vTrashLocationUri := CT_MRDS.FILE_MANAGER.GET_BUCKET_URI('DATA') || 'TRASH/' || vSourceFileConfig.A_SOURCE_KEY || '/' || vSourceFileConfig.TABLE_ID || '/';
|
||||
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Purging TRASH folder for configuration','INFO', 'Location: ' || vTrashLocationUri);
|
||||
|
||||
BEGIN
|
||||
FOR trash_file IN (
|
||||
SELECT object_name
|
||||
FROM DBMS_CLOUD.LIST_OBJECTS(
|
||||
credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
location_uri => vTrashLocationUri
|
||||
)
|
||||
) LOOP
|
||||
BEGIN
|
||||
DBMS_CLOUD.DELETE_OBJECT(
|
||||
credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
object_uri => vTrashLocationUri || trash_file.object_name
|
||||
);
|
||||
vFilesDeleted := vFilesDeleted + 1;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('File deleted from TRASH','DEBUG', trash_file.object_name);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Failed to delete file from TRASH','ERROR', trash_file.object_name);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
END;
|
||||
END LOOP;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Failed to list or delete TRASH files','ERROR', vTrashLocationUri);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(-20303, 'Failed to purge TRASH folder for configuration: ' || SQLERRM);
|
||||
END;
|
||||
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
SET PROCESSING_STATUS = 'ARCHIVED_AND_PURGED'
|
||||
WHERE A_SOURCE_FILE_CONFIG_KEY = pSourceFileConfigKey
|
||||
AND PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED';
|
||||
vFilesUpdated := SQL%ROWCOUNT;
|
||||
|
||||
ELSIF pPurgeAll THEN
|
||||
vPurgeLevel := 'LEVEL_1_GLOBAL_PURGE';
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Purge level: LEVEL 1 - Global TRASH purge','INFO', 'Deleting ALL files with ARCHIVED_AND_TRASHED status');
|
||||
|
||||
-- LEVEL 1: Delete all files with ARCHIVED_AND_TRASHED status across all configurations
|
||||
FOR config_rec IN (
|
||||
SELECT DISTINCT c.A_SOURCE_FILE_CONFIG_KEY, c.A_SOURCE_KEY, c.TABLE_ID
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG c
|
||||
JOIN CT_MRDS.A_SOURCE_FILE_RECEIVED r ON r.A_SOURCE_FILE_CONFIG_KEY = c.A_SOURCE_FILE_CONFIG_KEY
|
||||
WHERE r.PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED'
|
||||
) LOOP
|
||||
vTrashLocationUri := CT_MRDS.FILE_MANAGER.GET_BUCKET_URI('DATA') || 'TRASH/' || config_rec.A_SOURCE_KEY || '/' || config_rec.TABLE_ID || '/';
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Processing TRASH location','DEBUG', vTrashLocationUri);
|
||||
|
||||
BEGIN
|
||||
FOR trash_file IN (
|
||||
SELECT object_name
|
||||
FROM DBMS_CLOUD.LIST_OBJECTS(
|
||||
credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
location_uri => vTrashLocationUri
|
||||
)
|
||||
) LOOP
|
||||
BEGIN
|
||||
DBMS_CLOUD.DELETE_OBJECT(
|
||||
credential_name => CT_MRDS.ENV_MANAGER.gvCredentialName,
|
||||
object_uri => vTrashLocationUri || trash_file.object_name
|
||||
);
|
||||
vFilesDeleted := vFilesDeleted + 1;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('File deleted from TRASH','DEBUG', trash_file.object_name);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Failed to delete file from TRASH','ERROR', trash_file.object_name);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
END;
|
||||
END LOOP;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Failed to list TRASH files','WARNING', vTrashLocationUri || ' - ' || SQLERRM);
|
||||
END;
|
||||
END LOOP;
|
||||
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
SET PROCESSING_STATUS = 'ARCHIVED_AND_PURGED'
|
||||
WHERE PROCESSING_STATUS = 'ARCHIVED_AND_TRASHED';
|
||||
vFilesUpdated := SQL%ROWCOUNT;
|
||||
|
||||
ELSE
|
||||
RAISE_APPLICATION_ERROR(-20304, 'No purge level specified. Provide pSourceFileReceivedKey, pSourceFileConfigKey, or set pPurgeAll=TRUE');
|
||||
END IF;
|
||||
|
||||
COMMIT;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Total files deleted from TRASH: ' || vFilesDeleted,'INFO');
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Total file records updated to ARCHIVED_AND_PURGED: ' || vFilesUpdated,'INFO');
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('TRASH folder purge completed successfully','INFO', 'Level: ' || vPurgeLevel || ', Files deleted: ' || vFilesDeleted || ', Records updated: ' || vFilesUpdated);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End','INFO', vParameters);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
ROLLBACK;
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.MSG_UNKNOWN , 'ERROR', vParameters);
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RAISE_APPLICATION_ERROR(CT_MRDS.ENV_MANAGER.CODE_UNKNOWN, CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'OUTPUT', pCode=> SQLCODE));
|
||||
END PURGE_TRASH_FOLDER;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION PURGE_TRASH_FOLDER (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pPurgeAll IN BOOLEAN DEFAULT FALSE
|
||||
) RETURN PLS_INTEGER
|
||||
IS
|
||||
PRAGMA AUTONOMOUS_TRANSACTION;
|
||||
vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE;
|
||||
BEGIN
|
||||
vParameters := CT_MRDS.ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST(
|
||||
'pSourceFileReceivedKey => '||nvl(to_char(pSourceFileReceivedKey), 'NULL'),
|
||||
'pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey), 'NULL'),
|
||||
'pPurgeAll => '||CASE WHEN pPurgeAll THEN 'TRUE' ELSE 'FALSE' END
|
||||
));
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Start','INFO', vParameters);
|
||||
----
|
||||
PURGE_TRASH_FOLDER(
|
||||
pSourceFileReceivedKey => pSourceFileReceivedKey,
|
||||
pSourceFileConfigKey => pSourceFileConfigKey,
|
||||
pPurgeAll => pPurgeAll
|
||||
);
|
||||
----
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End','INFO',vParameters);
|
||||
RETURN SQLCODE;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RETURN SQLCODE;
|
||||
END PURGE_TRASH_FOLDER;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION RESTORE_FILE_FROM_TRASH (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pRestoreAll IN BOOLEAN DEFAULT FALSE
|
||||
) RETURN PLS_INTEGER
|
||||
IS
|
||||
PRAGMA AUTONOMOUS_TRANSACTION;
|
||||
vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE;
|
||||
BEGIN
|
||||
vParameters := CT_MRDS.ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST(
|
||||
'pSourceFileReceivedKey => '||nvl(to_char(pSourceFileReceivedKey), 'NULL'),
|
||||
'pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey), 'NULL'),
|
||||
'pRestoreAll => '||CASE WHEN pRestoreAll THEN 'TRUE' ELSE 'FALSE' END
|
||||
));
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Start','INFO', vParameters);
|
||||
----
|
||||
RESTORE_FILE_FROM_TRASH(
|
||||
pSourceFileReceivedKey => pSourceFileReceivedKey,
|
||||
pSourceFileConfigKey => pSourceFileConfigKey,
|
||||
pRestoreAll => pRestoreAll
|
||||
);
|
||||
----
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End','INFO',vParameters);
|
||||
RETURN SQLCODE;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RETURN SQLCODE;
|
||||
END RESTORE_FILE_FROM_TRASH;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
-- PACKAGE VERSION MANAGEMENT FUNCTIONS IMPLEMENTATION
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION GET_VERSION
|
||||
RETURN VARCHAR2
|
||||
IS
|
||||
BEGIN
|
||||
RETURN PACKAGE_VERSION;
|
||||
END GET_VERSION;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION GET_BUILD_INFO
|
||||
RETURN VARCHAR2
|
||||
IS
|
||||
BEGIN
|
||||
RETURN CT_MRDS.ENV_MANAGER.GET_PACKAGE_VERSION_INFO(
|
||||
pPackageName => 'FILE_ARCHIVER',
|
||||
pVersion => PACKAGE_VERSION,
|
||||
pBuildDate => PACKAGE_BUILD_DATE,
|
||||
pAuthor => PACKAGE_AUTHOR
|
||||
);
|
||||
END GET_BUILD_INFO;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION GET_VERSION_HISTORY
|
||||
RETURN VARCHAR2
|
||||
IS
|
||||
BEGIN
|
||||
RETURN CT_MRDS.ENV_MANAGER.FORMAT_VERSION_HISTORY(
|
||||
pPackageName => 'FILE_ARCHIVER',
|
||||
pVersionHistory => VERSION_HISTORY
|
||||
);
|
||||
END GET_VERSION_HISTORY;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION ARCHIVE_TABLE_DATA (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE,
|
||||
pKeepInTrash IN BOOLEAN DEFAULT TRUE
|
||||
) RETURN PLS_INTEGER
|
||||
IS
|
||||
vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE;
|
||||
BEGIN
|
||||
vParameters := CT_MRDS.ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST(
|
||||
'pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey), 'NULL'),
|
||||
'pKeepInTrash => '||CASE WHEN pKeepInTrash THEN 'TRUE' ELSE 'FALSE' END
|
||||
));
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Start','INFO', vParameters);
|
||||
----
|
||||
ARCHIVE_TABLE_DATA(pSourceFileConfigKey => pSourceFileConfigKey, pKeepInTrash => pKeepInTrash);
|
||||
----
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End','INFO',vParameters);
|
||||
RETURN SQLCODE;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RETURN SQLCODE;
|
||||
END ARCHIVE_TABLE_DATA;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION GATHER_TABLE_STAT (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
) RETURN PLS_INTEGER
|
||||
IS
|
||||
vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE;
|
||||
BEGIN
|
||||
vParameters := CT_MRDS.ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST('pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey), 'NULL')));
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('Start','INFO', vParameters);
|
||||
----
|
||||
GATHER_TABLE_STAT(pSourceFileConfigKey => pSourceFileConfigKey);
|
||||
----
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End','INFO',vParameters);
|
||||
RETURN SQLCODE;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT(CT_MRDS.ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RETURN SQLCODE;
|
||||
END GATHER_TABLE_STAT;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
END;
|
||||
|
||||
/
|
||||
@@ -0,0 +1,195 @@
|
||||
create or replace PACKAGE CT_MRDS.FILE_ARCHIVER
|
||||
AUTHID CURRENT_USER
|
||||
AS
|
||||
/**
|
||||
* General comment for package: Please put comments for functions and procedures as shown in below example.
|
||||
* It is a standard.
|
||||
* The structure of comment is used by GET_PACKAGE_DOCUMENTATION function
|
||||
* which returns documentation text for confluence page (to Copy-Paste it).
|
||||
**/
|
||||
|
||||
-- Example comment:
|
||||
/**
|
||||
* @name EX_PROCEDURE_NAME
|
||||
* @desc Procedure description
|
||||
* @example select LOGGING_AND_ERROR_MANAGER.EX_PROCEDURE_NAME(pParameter => 129) from dual;
|
||||
* @ex_rslt Example Result
|
||||
**/
|
||||
|
||||
-- Package Version Information (Semantic Versioning: MAJOR.MINOR.PATCH)
|
||||
PACKAGE_VERSION CONSTANT VARCHAR2(10) := '3.2.1';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2026-02-10 09:00:00';
|
||||
PACKAGE_AUTHOR CONSTANT VARCHAR2(100) := 'Grzegorz Michalski';
|
||||
|
||||
-- Version History (Latest changes first)
|
||||
VERSION_HISTORY CONSTANT VARCHAR2(4000) :=
|
||||
'3.2.1 (2026-02-10): Fixed status update - ARCHIVED → ARCHIVED_AND_TRASHED when moving files to TRASH folder (critical bug fix)' || CHR(13)||CHR(10) ||
|
||||
'3.2.0 (2026-02-06): Added pKeepInTrash parameter (DEFAULT TRUE) to ARCHIVE_TABLE_DATA for TRASH folder retention control - files kept in TRASH subfolder (DATA bucket) by default for safety and compliance' || CHR(13)||CHR(10) ||
|
||||
'3.1.2 (2026-02-06): Fixed missing PARTITION_YEAR/PARTITION_MONTH assignments in UPDATE statement and export query circular dependency (now filters by workflow_start instead of partition fields)' || CHR(13)||CHR(10) ||
|
||||
'3.1.1 (2026-02-06): Fixed ORA-01422 error when DBMS_CLOUD.EXPORT_DATA creates multiple parquet files (parallel execution). Now stores archive directory prefix instead of individual filenames' || CHR(13)||CHR(10) ||
|
||||
'3.1.0 (2026-01-29): Added function overloads for ARCHIVE_TABLE_DATA and GATHER_TABLE_STAT returning SQLCODE for Python library integration' || CHR(13)||CHR(10) ||
|
||||
'3.0.0 (2026-01-27): MARS-828 - Added flexible archival strategies (MINIMUM_AGE_MONTHS with 0=current month, HYBRID) via ARCHIVAL_STRATEGY configuration' || CHR(13)||CHR(10) ||
|
||||
'2.0.0 (2025-10-22): Added package versioning system using centralized ENV_MANAGER functions' || CHR(13)||CHR(10) ||
|
||||
'1.5.0 (2025-10-18): Enhanced ARCHIVE_TABLE_DATA with Hive-style partitioning support' || CHR(13)||CHR(10) ||
|
||||
'1.0.0 (2025-09-15): Initial release with table archival and statistics gathering';
|
||||
|
||||
cgBL CONSTANT VARCHAR2(2) := ENV_MANAGER.cgBL;
|
||||
|
||||
/**
|
||||
* @name ARCHIVE_TABLE_DATA
|
||||
* @desc Wrapper procedure for DBMS_CLOUD.EXPORT_DATA.
|
||||
* Exports data from table specified by pSourceFileConfigKey(A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY) into PARQUET file on OCI infrustructure.
|
||||
* Each YEAR_MONTH pair goes to seperate file (implicit partitioning).
|
||||
* @param pKeepInTrash - When TRUE (default), files are kept in TRASH folder (DATA bucket subfolder) for safety. When FALSE, files are deleted from TRASH after successful archive.
|
||||
**/
|
||||
PROCEDURE ARCHIVE_TABLE_DATA (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE,
|
||||
pKeepInTrash IN BOOLEAN DEFAULT TRUE
|
||||
);
|
||||
|
||||
/**
|
||||
* @name ARCHIVE_TABLE_DATA
|
||||
* @desc Function overload for ARCHIVE_TABLE_DATA procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main ARCHIVE_TABLE_DATA procedure and captures execution result.
|
||||
* @param pKeepInTrash - When TRUE (default), files are kept in TRASH folder (DATA bucket subfolder) for safety. When FALSE, files are deleted from TRASH after successful archive.
|
||||
* @example SELECT FILE_ARCHIVER.ARCHIVE_TABLE_DATA(pSourceFileConfigKey => 123) FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION ARCHIVE_TABLE_DATA (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE,
|
||||
pKeepInTrash IN BOOLEAN DEFAULT TRUE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @name GATHER_TABLE_STAT
|
||||
* @desc Gather info about EXTERNAL TABLE specified by pSourceFileConfigKey parameter (A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY).
|
||||
* Data is inserted into A_TABLE_STAT and A_TABLE_STAT_HIST.
|
||||
**/
|
||||
PROCEDURE GATHER_TABLE_STAT (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
);
|
||||
|
||||
/**
|
||||
* @name GATHER_TABLE_STAT
|
||||
* @desc Function overload for GATHER_TABLE_STAT procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main GATHER_TABLE_STAT procedure and captures execution result.
|
||||
* @example SELECT FILE_ARCHIVER.GATHER_TABLE_STAT(pSourceFileConfigKey => 123) FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION GATHER_TABLE_STAT (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
/**
|
||||
* @name RESTORE_FILE_FROM_TRASH
|
||||
* @desc Restores files from TRASH folder back to ODS at three different granularity levels.
|
||||
* Moves files from TRASH subfolder back to ODS subfolder in DATA bucket.
|
||||
* Updates status from ARCHIVED_AND_TRASHED to INGESTED and clears archival metadata.
|
||||
* @param pSourceFileReceivedKey - (LEVEL 3) Specific file to restore by A_SOURCE_FILE_RECEIVED_KEY (highest priority)
|
||||
* @param pSourceFileConfigKey - (LEVEL 2) Restore all files for specific configuration key (medium priority)
|
||||
* @param pRestoreAll - (LEVEL 1) When TRUE, restore ALL files with ARCHIVED_AND_TRASHED status (lowest priority)
|
||||
* @example -- Restore single file: CALL FILE_ARCHIVER.RESTORE_FILE_FROM_TRASH(pSourceFileReceivedKey => 12345);
|
||||
* @example -- Restore all files for config: CALL FILE_ARCHIVER.RESTORE_FILE_FROM_TRASH(pSourceFileConfigKey => 341);
|
||||
* @example -- Restore all TRASH globally: CALL FILE_ARCHIVER.RESTORE_FILE_FROM_TRASH(pRestoreAll => TRUE);
|
||||
**/
|
||||
PROCEDURE RESTORE_FILE_FROM_TRASH (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pRestoreAll IN BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
|
||||
/**
|
||||
* @name RESTORE_FILE_FROM_TRASH
|
||||
* @desc Function overload for RESTORE_FILE_FROM_TRASH procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main RESTORE_FILE_FROM_TRASH procedure and captures execution result.
|
||||
* @param pSourceFileReceivedKey - (LEVEL 3) Specific file to restore by A_SOURCE_FILE_RECEIVED_KEY (highest priority)
|
||||
* @param pSourceFileConfigKey - (LEVEL 2) Restore all files for specific configuration key (medium priority)
|
||||
* @param pRestoreAll - (LEVEL 1) When TRUE, restore ALL files with ARCHIVED_AND_TRASHED status (lowest priority)
|
||||
* @example SELECT FILE_ARCHIVER.RESTORE_FILE_FROM_TRASH(pSourceFileReceivedKey => 12345) FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION RESTORE_FILE_FROM_TRASH (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pRestoreAll IN BOOLEAN DEFAULT FALSE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
/**
|
||||
* @name PURGE_TRASH_FOLDER
|
||||
* @desc Deletes files from TRASH folder at three different granularity levels.
|
||||
* Updates status from ARCHIVED_AND_TRASHED to ARCHIVED_AND_PURGED for all affected files.
|
||||
* WARNING: This operation is irreversible - files are permanently deleted from TRASH.
|
||||
* @param pSourceFileReceivedKey - (LEVEL 3) Specific file to delete by A_SOURCE_FILE_RECEIVED_KEY (highest priority)
|
||||
* @param pSourceFileConfigKey - (LEVEL 2) Delete all files for specific configuration key (medium priority)
|
||||
* @param pPurgeAll - (LEVEL 1) When TRUE, delete ALL files with ARCHIVED_AND_TRASHED status (lowest priority)
|
||||
* @example -- Delete single file: CALL FILE_ARCHIVER.PURGE_TRASH_FOLDER(pSourceFileReceivedKey => 12345);
|
||||
* @example -- Delete all files for config: CALL FILE_ARCHIVER.PURGE_TRASH_FOLDER(pSourceFileConfigKey => 341);
|
||||
* @example -- Delete all TRASH globally: CALL FILE_ARCHIVER.PURGE_TRASH_FOLDER(pPurgeAll => TRUE);
|
||||
**/
|
||||
PROCEDURE PURGE_TRASH_FOLDER (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pPurgeAll IN BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
|
||||
/**
|
||||
* @name PURGE_TRASH_FOLDER
|
||||
* @desc Function overload for PURGE_TRASH_FOLDER procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main PURGE_TRASH_FOLDER procedure and captures execution result.
|
||||
* WARNING: This operation is irreversible - files are permanently deleted from TRASH.
|
||||
* @param pSourceFileReceivedKey - (LEVEL 3) Specific file to delete by A_SOURCE_FILE_RECEIVED_KEY (highest priority)
|
||||
* @param pSourceFileConfigKey - (LEVEL 2) Delete all files for specific configuration key (medium priority)
|
||||
* @param pPurgeAll - (LEVEL 1) When TRUE, delete ALL files with ARCHIVED_AND_TRASHED status (lowest priority)
|
||||
* @example SELECT FILE_ARCHIVER.PURGE_TRASH_FOLDER(pSourceFileReceivedKey => 12345) FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION PURGE_TRASH_FOLDER (
|
||||
pSourceFileReceivedKey IN CT_MRDS.A_SOURCE_FILE_RECEIVED.A_SOURCE_FILE_RECEIVED_KEY%TYPE DEFAULT NULL,
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE DEFAULT NULL,
|
||||
pPurgeAll IN BOOLEAN DEFAULT FALSE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
-- PACKAGE VERSION MANAGEMENT FUNCTIONS
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @name GET_VERSION
|
||||
* @desc Returns the current version number of the FILE_ARCHIVER package.
|
||||
* Uses semantic versioning format (MAJOR.MINOR.PATCH).
|
||||
* @example SELECT FILE_ARCHIVER.GET_VERSION() FROM DUAL;
|
||||
* @ex_rslt 2.0.0
|
||||
**/
|
||||
FUNCTION GET_VERSION RETURN VARCHAR2;
|
||||
|
||||
/**
|
||||
* @name GET_BUILD_INFO
|
||||
* @desc Returns comprehensive build information including version, build date, and author.
|
||||
* Uses centralized ENV_MANAGER.GET_PACKAGE_VERSION_INFO function.
|
||||
* @example SELECT FILE_ARCHIVER.GET_BUILD_INFO() FROM DUAL;
|
||||
* @ex_rslt Package: FILE_ARCHIVER
|
||||
* Version: 2.0.0
|
||||
* Build Date: 2025-10-22 16:45:00
|
||||
* Author: Grzegorz Michalski
|
||||
**/
|
||||
FUNCTION GET_BUILD_INFO RETURN VARCHAR2;
|
||||
|
||||
/**
|
||||
* @name GET_VERSION_HISTORY
|
||||
* @desc Returns complete version history with all releases and changes.
|
||||
* Uses centralized ENV_MANAGER.FORMAT_VERSION_HISTORY function.
|
||||
* @example SELECT FILE_ARCHIVER.GET_VERSION_HISTORY() FROM DUAL;
|
||||
* @ex_rslt FILE_ARCHIVER Version History:
|
||||
* 2.0.0 (2025-10-22): Added package versioning system...
|
||||
**/
|
||||
FUNCTION GET_VERSION_HISTORY RETURN VARCHAR2;
|
||||
|
||||
END;
|
||||
|
||||
/
|
||||
@@ -1,253 +0,0 @@
|
||||
-- MARS-828: Test archival strategies
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2026-01-27
|
||||
-- Description: Comprehensive test scenarios for all archival strategies
|
||||
|
||||
SET SERVEROUTPUT ON SIZE UNLIMITED
|
||||
|
||||
PROMPT ========================================
|
||||
PROMPT MARS-828: Testing Archival Strategies
|
||||
PROMPT ========================================
|
||||
|
||||
-- Test 1: THRESHOLD_BASED (backward compatibility)
|
||||
PROMPT
|
||||
PROMPT Test 1: THRESHOLD_BASED strategy
|
||||
DECLARE
|
||||
vTestKey NUMBER := -1000;
|
||||
BEGIN
|
||||
INSERT INTO CT_MRDS.A_SOURCE_FILE_CONFIG (
|
||||
A_SOURCE_FILE_CONFIG_KEY,
|
||||
A_SOURCE_KEY,
|
||||
SOURCE_FILE_TYPE,
|
||||
SOURCE_FILE_ID,
|
||||
SOURCE_FILE_DESC,
|
||||
SOURCE_FILE_NAME_PATTERN,
|
||||
TABLE_ID,
|
||||
TEMPLATE_TABLE_NAME,
|
||||
ARCHIVAL_STRATEGY,
|
||||
DAYS_FOR_ARCHIVE_THRESHOLD
|
||||
) VALUES (
|
||||
vTestKey,
|
||||
'TEST1',
|
||||
'INPUT',
|
||||
'TEST_THRESHOLD',
|
||||
'Test threshold-based',
|
||||
'test*.csv',
|
||||
'TEST_TABLE',
|
||||
'CT_ET_TEMPLATES.TEST',
|
||||
'THRESHOLD_BASED',
|
||||
30
|
||||
);
|
||||
|
||||
DBMS_OUTPUT.PUT_LINE('SUCCESS: THRESHOLD_BASED strategy configured');
|
||||
ROLLBACK;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
DBMS_OUTPUT.PUT_LINE('FAILED: ' || SQLERRM);
|
||||
ROLLBACK;
|
||||
END;
|
||||
/
|
||||
|
||||
-- Test 2: CURRENT_MONTH_ONLY
|
||||
PROMPT
|
||||
PROMPT Test 2: CURRENT_MONTH_ONLY strategy
|
||||
DECLARE
|
||||
vTestKey NUMBER := -1001;
|
||||
BEGIN
|
||||
INSERT INTO CT_MRDS.A_SOURCE_FILE_CONFIG (
|
||||
A_SOURCE_FILE_CONFIG_KEY,
|
||||
A_SOURCE_KEY,
|
||||
SOURCE_FILE_TYPE,
|
||||
SOURCE_FILE_ID,
|
||||
SOURCE_FILE_DESC,
|
||||
SOURCE_FILE_NAME_PATTERN,
|
||||
TABLE_ID,
|
||||
TEMPLATE_TABLE_NAME,
|
||||
ARCHIVAL_STRATEGY
|
||||
) VALUES (
|
||||
vTestKey,
|
||||
'TEST2',
|
||||
'INPUT',
|
||||
'TEST_CURRENT_MONTH',
|
||||
'Test current month only',
|
||||
'test*.csv',
|
||||
'TEST_TABLE',
|
||||
'CT_ET_TEMPLATES.TEST',
|
||||
'CURRENT_MONTH_ONLY'
|
||||
);
|
||||
|
||||
DBMS_OUTPUT.PUT_LINE('SUCCESS: CURRENT_MONTH_ONLY strategy configured');
|
||||
ROLLBACK;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
DBMS_OUTPUT.PUT_LINE('FAILED: ' || SQLERRM);
|
||||
ROLLBACK;
|
||||
END;
|
||||
/
|
||||
|
||||
-- Test 3: MINIMUM_AGE_MONTHS (should succeed)
|
||||
PROMPT
|
||||
PROMPT Test 3: MINIMUM_AGE_MONTHS strategy with valid config
|
||||
DECLARE
|
||||
vTestKey NUMBER := -1002;
|
||||
BEGIN
|
||||
INSERT INTO CT_MRDS.A_SOURCE_FILE_CONFIG (
|
||||
A_SOURCE_FILE_CONFIG_KEY,
|
||||
A_SOURCE_KEY,
|
||||
SOURCE_FILE_TYPE,
|
||||
SOURCE_FILE_ID,
|
||||
SOURCE_FILE_DESC,
|
||||
SOURCE_FILE_NAME_PATTERN,
|
||||
TABLE_ID,
|
||||
TEMPLATE_TABLE_NAME,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS
|
||||
) VALUES (
|
||||
vTestKey,
|
||||
'TEST3',
|
||||
'INPUT',
|
||||
'TEST_MIN_AGE',
|
||||
'Test minimum age months',
|
||||
'test*.csv',
|
||||
'TEST_TABLE',
|
||||
'CT_ET_TEMPLATES.TEST',
|
||||
'MINIMUM_AGE_MONTHS',
|
||||
6
|
||||
);
|
||||
|
||||
DBMS_OUTPUT.PUT_LINE('SUCCESS: MINIMUM_AGE_MONTHS strategy configured with 6 months');
|
||||
ROLLBACK;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
DBMS_OUTPUT.PUT_LINE('FAILED: ' || SQLERRM);
|
||||
ROLLBACK;
|
||||
END;
|
||||
/
|
||||
|
||||
-- Test 4: MINIMUM_AGE_MONTHS without value (should fail)
|
||||
PROMPT
|
||||
PROMPT Test 4: MINIMUM_AGE_MONTHS strategy without value (should fail)
|
||||
DECLARE
|
||||
vTestKey NUMBER := -1003;
|
||||
BEGIN
|
||||
INSERT INTO CT_MRDS.A_SOURCE_FILE_CONFIG (
|
||||
A_SOURCE_FILE_CONFIG_KEY,
|
||||
A_SOURCE_KEY,
|
||||
SOURCE_FILE_TYPE,
|
||||
SOURCE_FILE_ID,
|
||||
SOURCE_FILE_DESC,
|
||||
SOURCE_FILE_NAME_PATTERN,
|
||||
TABLE_ID,
|
||||
TEMPLATE_TABLE_NAME,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS
|
||||
) VALUES (
|
||||
vTestKey,
|
||||
'TEST4',
|
||||
'INPUT',
|
||||
'TEST_MIN_AGE_FAIL',
|
||||
'Test minimum age months failure',
|
||||
'test*.csv',
|
||||
'TEST_TABLE',
|
||||
'CT_ET_TEMPLATES.TEST',
|
||||
'MINIMUM_AGE_MONTHS',
|
||||
NULL -- Should trigger error
|
||||
);
|
||||
|
||||
DBMS_OUTPUT.PUT_LINE('FAILED: Trigger did not fire - this should have failed!');
|
||||
ROLLBACK;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
IF SQLCODE = -20999 THEN
|
||||
DBMS_OUTPUT.PUT_LINE('SUCCESS: Trigger correctly prevented invalid config');
|
||||
ELSE
|
||||
DBMS_OUTPUT.PUT_LINE('FAILED: Unexpected error: ' || SQLERRM);
|
||||
END IF;
|
||||
ROLLBACK;
|
||||
END;
|
||||
/
|
||||
|
||||
-- Test 5: HYBRID strategy
|
||||
PROMPT
|
||||
PROMPT Test 5: HYBRID strategy
|
||||
DECLARE
|
||||
vTestKey NUMBER := -1004;
|
||||
BEGIN
|
||||
INSERT INTO CT_MRDS.A_SOURCE_FILE_CONFIG (
|
||||
A_SOURCE_FILE_CONFIG_KEY,
|
||||
A_SOURCE_KEY,
|
||||
SOURCE_FILE_TYPE,
|
||||
SOURCE_FILE_ID,
|
||||
SOURCE_FILE_DESC,
|
||||
SOURCE_FILE_NAME_PATTERN,
|
||||
TABLE_ID,
|
||||
TEMPLATE_TABLE_NAME,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS
|
||||
) VALUES (
|
||||
vTestKey,
|
||||
'TEST5',
|
||||
'INPUT',
|
||||
'TEST_HYBRID',
|
||||
'Test hybrid strategy',
|
||||
'test*.csv',
|
||||
'TEST_TABLE',
|
||||
'CT_ET_TEMPLATES.TEST',
|
||||
'HYBRID',
|
||||
3
|
||||
);
|
||||
|
||||
DBMS_OUTPUT.PUT_LINE('SUCCESS: HYBRID strategy configured');
|
||||
ROLLBACK;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
DBMS_OUTPUT.PUT_LINE('FAILED: ' || SQLERRM);
|
||||
ROLLBACK;
|
||||
END;
|
||||
/
|
||||
|
||||
-- Test 6: Invalid strategy (should fail)
|
||||
PROMPT
|
||||
PROMPT Test 6: Invalid strategy (should fail)
|
||||
DECLARE
|
||||
vTestKey NUMBER := -1005;
|
||||
BEGIN
|
||||
INSERT INTO CT_MRDS.A_SOURCE_FILE_CONFIG (
|
||||
A_SOURCE_FILE_CONFIG_KEY,
|
||||
A_SOURCE_KEY,
|
||||
SOURCE_FILE_TYPE,
|
||||
SOURCE_FILE_ID,
|
||||
SOURCE_FILE_DESC,
|
||||
SOURCE_FILE_NAME_PATTERN,
|
||||
TABLE_ID,
|
||||
TEMPLATE_TABLE_NAME,
|
||||
ARCHIVAL_STRATEGY
|
||||
) VALUES (
|
||||
vTestKey,
|
||||
'TEST6',
|
||||
'INPUT',
|
||||
'TEST_INVALID',
|
||||
'Test invalid strategy',
|
||||
'test*.csv',
|
||||
'TEST_TABLE',
|
||||
'CT_ET_TEMPLATES.TEST',
|
||||
'INVALID_STRATEGY'
|
||||
);
|
||||
|
||||
DBMS_OUTPUT.PUT_LINE('FAILED: Check constraint did not fire!');
|
||||
ROLLBACK;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
IF SQLCODE = -2290 THEN
|
||||
DBMS_OUTPUT.PUT_LINE('SUCCESS: Check constraint prevented invalid strategy');
|
||||
ELSE
|
||||
DBMS_OUTPUT.PUT_LINE('FAILED: Unexpected error: ' || SQLERRM);
|
||||
END IF;
|
||||
ROLLBACK;
|
||||
END;
|
||||
/
|
||||
|
||||
PROMPT
|
||||
PROMPT ========================================
|
||||
PROMPT MARS-828: Testing Complete
|
||||
PROMPT ========================================
|
||||
@@ -1,16 +1,16 @@
|
||||
--=============================================================================================================================
|
||||
-- MARS-1057: Install FILE_MANAGER Package Specification v3.4.0
|
||||
-- MARS-1057: Install FILE_MANAGER Package Specification v3.5.0
|
||||
--=============================================================================================================================
|
||||
-- Purpose: Deploy FILE_MANAGER package specification with new batch external table creation procedures
|
||||
-- Purpose: Deploy FILE_MANAGER package specification with batch external table creation and area filter functionality
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2025-11-27
|
||||
-- Related: MARS-1057 Batch External Table Creation
|
||||
-- Date: 2026-02-18
|
||||
-- Related: MARS-1057 Batch External Table Creation + Area Filter Enhancement
|
||||
--=============================================================================================================================
|
||||
|
||||
SET SERVEROUTPUT ON
|
||||
|
||||
PROMPT ========================================================================
|
||||
PROMPT Installing FILE_MANAGER Package Specification v3.4.0
|
||||
PROMPT Installing FILE_MANAGER Package Specification v3.5.0
|
||||
PROMPT ========================================================================
|
||||
|
||||
@@new_version/FILE_MANAGER.pkg
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
--=============================================================================================================================
|
||||
-- MARS-1057: Install FILE_MANAGER Package Body v3.4.0
|
||||
-- MARS-1057: Install FILE_MANAGER Package Body v3.5.0
|
||||
--=============================================================================================================================
|
||||
-- Purpose: Deploy FILE_MANAGER package body with implementation of batch external table creation procedures
|
||||
-- Purpose: Deploy FILE_MANAGER package body with batch external table creation and area filter functionality
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2025-11-27
|
||||
-- Related: MARS-1057 Batch External Table Creation
|
||||
-- Date: 2026-02-18
|
||||
-- Related: MARS-1057 Batch External Table Creation + Area Filter Enhancement
|
||||
--=============================================================================================================================
|
||||
|
||||
SET SERVEROUTPUT ON
|
||||
|
||||
PROMPT ========================================================================
|
||||
PROMPT Installing FILE_MANAGER Package Body v3.4.0
|
||||
PROMPT Installing FILE_MANAGER Package Body v3.5.0
|
||||
PROMPT ========================================================================
|
||||
|
||||
@@new_version/FILE_MANAGER.pkb
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
-- ===================================================================
|
||||
-- MARS-1057: Install ODS.FILE_MANAGER_ODS Package Specification
|
||||
-- ===================================================================
|
||||
-- Purpose: Deploy FILE_MANAGER_ODS package specification v2.2.0
|
||||
-- Purpose: Deploy FILE_MANAGER_ODS package specification v2.4.0
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2025-11-27
|
||||
-- Date: 2026-02-18
|
||||
-- Package: ODS.FILE_MANAGER_ODS
|
||||
-- Version: 2.1.0 -> 2.2.0
|
||||
-- Changes: Added CREATE_EXTERNAL_TABLES_SET and CREATE_EXTERNAL_TABLES_BATCH wrappers
|
||||
-- Version: 2.1.0 -> 2.4.0
|
||||
-- Changes: Added CREATE_EXTERNAL_TABLES_SET and CREATE_EXTERNAL_TABLES_BATCH wrappers with pArea and pRestoreGrants parameters
|
||||
|
||||
SET ECHO ON
|
||||
SET DEFINE OFF
|
||||
|
||||
PROMPT Installing ODS.FILE_MANAGER_ODS Package Specification v2.2.0...
|
||||
PROMPT Installing ODS.FILE_MANAGER_ODS Package Specification v2.4.0...
|
||||
|
||||
@@new_version/FILE_MANAGER_ODS.pkg
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
-- ===================================================================
|
||||
-- MARS-1057: Install ODS.FILE_MANAGER_ODS Package Body
|
||||
-- ===================================================================
|
||||
-- Purpose: Deploy FILE_MANAGER_ODS package body v2.2.0
|
||||
-- Purpose: Deploy FILE_MANAGER_ODS package body v2.4.0
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2025-11-27
|
||||
-- Date: 2026-02-18
|
||||
-- Package: ODS.FILE_MANAGER_ODS
|
||||
-- Version: 2.1.0 -> 2.2.0
|
||||
-- Changes: Added CREATE_EXTERNAL_TABLES_SET and CREATE_EXTERNAL_TABLES_BATCH wrapper implementations
|
||||
-- Version: 2.1.0 -> 2.4.0
|
||||
-- Changes: Added CREATE_EXTERNAL_TABLES_SET and CREATE_EXTERNAL_TABLES_BATCH wrapper implementations with pArea and pRestoreGrants parameters
|
||||
|
||||
SET ECHO ON
|
||||
SET DEFINE OFF
|
||||
|
||||
PROMPT Installing ODS.FILE_MANAGER_ODS Package Body v2.2.0...
|
||||
PROMPT Installing ODS.FILE_MANAGER_ODS Package Body v2.4.0...
|
||||
|
||||
@@new_version/FILE_MANAGER_ODS.pkb
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
--=============================================================================================================================
|
||||
-- MARS-1057: Rollback FILE_MANAGER Package Specification to v3.3.0
|
||||
--=============================================================================================================================
|
||||
-- Purpose: Restore FILE_MANAGER package specification to version before MARS-1057 changes
|
||||
-- Purpose: Restore FILE_MANAGER package specification to version before MARS-1057 changes (from v3.5.0 to v3.3.0)
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2025-11-27
|
||||
-- Related: MARS-1057 Batch External Table Creation (ROLLBACK)
|
||||
-- Date: 2026-02-18
|
||||
-- Related: MARS-1057 Batch External Table Creation + Area Filter (ROLLBACK)
|
||||
--=============================================================================================================================
|
||||
|
||||
SET SERVEROUTPUT ON
|
||||
|
||||
PROMPT ========================================================================
|
||||
PROMPT Rolling back FILE_MANAGER Package Specification to v3.3.0
|
||||
PROMPT Rolling back FILE_MANAGER Package Specification from v3.5.0 to v3.3.0
|
||||
PROMPT ========================================================================
|
||||
|
||||
@@current_version/FILE_MANAGER.pkg
|
||||
@@rollback_version/FILE_MANAGER.pkg
|
||||
|
||||
-- Verify compilation status (check specific schema when installing as ADMIN)
|
||||
SELECT object_name, object_type, status
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
--=============================================================================================================================
|
||||
-- MARS-1057: Rollback FILE_MANAGER Package Body to v3.3.0
|
||||
--=============================================================================================================================
|
||||
-- Purpose: Restore FILE_MANAGER package body to version before MARS-1057 changes
|
||||
-- Purpose: Restore FILE_MANAGER package body to version before MARS-1057 changes (from v3.5.0 to v3.3.0)
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2025-11-27
|
||||
-- Related: MARS-1057 Batch External Table Creation (ROLLBACK)
|
||||
-- Date: 2026-02-18
|
||||
-- Related: MARS-1057 Batch External Table Creation + Area Filter (ROLLBACK)
|
||||
--=============================================================================================================================
|
||||
|
||||
SET SERVEROUTPUT ON
|
||||
|
||||
PROMPT ========================================================================
|
||||
PROMPT Rolling back FILE_MANAGER Package Body to v3.3.0
|
||||
PROMPT Rolling back FILE_MANAGER Package Body from v3.5.0 to v3.3.0
|
||||
PROMPT ========================================================================
|
||||
|
||||
@@current_version/FILE_MANAGER.pkb
|
||||
@@rollback_version/FILE_MANAGER.pkb
|
||||
|
||||
-- Verify compilation status (check specific schema when installing as ADMIN)
|
||||
SELECT object_name, object_type, status
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
-- ===================================================================
|
||||
-- Purpose: Restore FILE_MANAGER_ODS package body to v2.1.0
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2025-11-27
|
||||
-- Date: 2026-02-18
|
||||
-- Package: ODS.FILE_MANAGER_ODS
|
||||
-- Version: 2.2.0 -> 2.1.0 (rollback)
|
||||
-- Version: 2.4.0 -> 2.1.0 (rollback)
|
||||
|
||||
SET ECHO ON
|
||||
SET DEFINE OFF
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
-- ===================================================================
|
||||
-- Purpose: Restore FILE_MANAGER_ODS package specification to v2.1.0
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2025-11-27
|
||||
-- Date: 2026-02-18
|
||||
-- Package: ODS.FILE_MANAGER_ODS
|
||||
-- Version: 2.2.0 -> 2.1.0 (rollback)
|
||||
-- Version: 2.4.0 -> 2.1.0 (rollback)
|
||||
|
||||
SET ECHO ON
|
||||
SET DEFINE OFF
|
||||
|
||||
@@ -1,376 +0,0 @@
|
||||
# MARS-1057: Batch External Table Creation
|
||||
|
||||
## Overview
|
||||
This MARS package adds batch external table creation capabilities to the FILE_MANAGER and FILE_MANAGER_ODS packages, enabling automatic creation of external table sets (INBOX, ODS, ARCHIVE) based on A_SOURCE_FILE_CONFIG metadata.
|
||||
|
||||
**Jira Issue:** MARS-1057
|
||||
**Package Version:** FILE_MANAGER 3.4.0, FILE_MANAGER_ODS 2.2.0
|
||||
**Author:** Grzegorz Michalski
|
||||
**Date:** 2025-11-27
|
||||
|
||||
## Contents
|
||||
- `install_mars1057.sql` - Master installation script with SPOOL logging
|
||||
- `rollback_mars1057.sql` - Master rollback script
|
||||
- `01_MARS_1057_install_CT_MRDS_FILE_MANAGER_SPEC.sql` - Install FILE_MANAGER package specification
|
||||
- `02_MARS_1057_install_CT_MRDS_FILE_MANAGER_BODY.sql` - Install FILE_MANAGER package body
|
||||
- `03_MARS_1057_install_ODS_FILE_MANAGER_ODS_SPEC.sql` - Install FILE_MANAGER_ODS package specification
|
||||
- `04_MARS_1057_install_ODS_FILE_MANAGER_ODS_BODY.sql` - Install FILE_MANAGER_ODS package body
|
||||
- `91_MARS_1057_rollback_CT_MRDS_FILE_MANAGER_SPEC.sql` - Rollback FILE_MANAGER package specification
|
||||
- `92_MARS_1057_rollback_CT_MRDS_FILE_MANAGER_BODY.sql` - Rollback FILE_MANAGER package body
|
||||
- `93_MARS_1057_rollback_ODS_FILE_MANAGER_ODS_BODY.sql` - Rollback FILE_MANAGER_ODS package body
|
||||
- `94_MARS_1057_rollback_ODS_FILE_MANAGER_ODS_SPEC.sql` - Rollback FILE_MANAGER_ODS package specification
|
||||
- `track_package_versions.sql` - Universal package version tracking
|
||||
- `verify_packages_version.sql` - Universal package verification
|
||||
- `rollback_version/` - FILE_MANAGER v3.3.0, FILE_MANAGER_ODS v2.1.0 (before MARS-1057)
|
||||
- `new_version/` - FILE_MANAGER v3.4.0, FILE_MANAGER_ODS v2.2.0 (after MARS-1057)
|
||||
- `.gitignore` - Git exclusions for temporary files
|
||||
|
||||
## Prerequisites
|
||||
- Oracle Database 23ai
|
||||
- FILE_MANAGER package v3.3.0 installed
|
||||
- FILE_MANAGER_ODS package v2.1.0 installed
|
||||
- ENV_MANAGER package v3.1.0+ with version tracking
|
||||
- ADMIN user access for deployment
|
||||
- ODS schema with necessary privileges
|
||||
|
||||
## New Features
|
||||
|
||||
### 1. CREATE_EXTERNAL_TABLES_SET
|
||||
Creates a complete set of 3 external tables (INBOX, ODS, ARCHIVE) for a single configuration from A_SOURCE_FILE_CONFIG.
|
||||
|
||||
**Signature:**
|
||||
```sql
|
||||
PROCEDURE CREATE_EXTERNAL_TABLES_SET (
|
||||
pSourceFileConfigKey IN NUMBER,
|
||||
pRecreate IN BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```sql
|
||||
BEGIN
|
||||
FILE_MANAGER.CREATE_EXTERNAL_TABLES_SET(
|
||||
pSourceFileConfigKey => 123,
|
||||
pRecreate => FALSE
|
||||
);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Automatic table naming: `{TABLE_ID}_{INBOX|ODS|ARCHIVE}`
|
||||
- Official path patterns compliance
|
||||
- Optional drop and recreate
|
||||
- Full ENV_MANAGER logging
|
||||
- Error handling with detailed messages
|
||||
|
||||
### 2. CREATE_EXTERNAL_TABLES_BATCH
|
||||
Creates external table sets for multiple configurations based on filter criteria.
|
||||
|
||||
**Signature:**
|
||||
```sql
|
||||
PROCEDURE CREATE_EXTERNAL_TABLES_BATCH (
|
||||
pSourceKey IN VARCHAR2 DEFAULT NULL,
|
||||
pSourceFileId IN VARCHAR2 DEFAULT NULL,
|
||||
pTableId IN VARCHAR2 DEFAULT NULL,
|
||||
pRecreate IN BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
```sql
|
||||
-- All external tables for C2D source
|
||||
BEGIN
|
||||
FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
pSourceKey => 'C2D'
|
||||
);
|
||||
END;
|
||||
/
|
||||
|
||||
-- Recreate all external tables
|
||||
BEGIN
|
||||
FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
pRecreate => TRUE
|
||||
);
|
||||
END;
|
||||
/
|
||||
|
||||
-- Specific table across all sources
|
||||
BEGIN
|
||||
FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
pTableId => 'A_UC_DISSEM_METADATA_LOADS'
|
||||
);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Filters only INPUT type files
|
||||
- Continues processing on errors
|
||||
- Returns summary (Total/Processed/Failed)
|
||||
- Comprehensive logging
|
||||
|
||||
### 3. FILE_MANAGER_ODS Wrapper Procedures
|
||||
The ODS.FILE_MANAGER_ODS package now includes DEFINER rights wrappers for the new batch procedures.
|
||||
|
||||
**New Wrappers:**
|
||||
```sql
|
||||
-- Create single external table set via ODS wrapper
|
||||
EXEC ODS.FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_SET(
|
||||
pSourceFileConfigKey => 123,
|
||||
pRecreate => FALSE
|
||||
);
|
||||
|
||||
-- Create batch external tables via ODS wrapper
|
||||
EXEC ODS.FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
pSourceKey => 'C2D',
|
||||
pRecreate => FALSE
|
||||
);
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Objects created in ODS schema regardless of execution user
|
||||
- Same functionality as CT_MRDS.FILE_MANAGER with DEFINER rights
|
||||
- Full logging and error handling
|
||||
- Consistent API with original package
|
||||
|
||||
## Installation
|
||||
|
||||
### Option 1: Master Script (Recommended)
|
||||
```powershell
|
||||
# IMPORTANT: Execute as ADMIN user
|
||||
Get-Content "MARS_Packages/REL03/MARS-1057/install_mars1057.sql" | sql "ADMIN/password@service"
|
||||
|
||||
# Log file created: log/INSTALL_MARS_1057_<PDB>_<timestamp>.log
|
||||
```
|
||||
|
||||
**Installation Steps:**
|
||||
1. Install FILE_MANAGER package specification v3.4.0
|
||||
2. Install FILE_MANAGER package body v3.4.0
|
||||
3. Install FILE_MANAGER_ODS package specification v2.2.0
|
||||
4. Install FILE_MANAGER_ODS package body v2.2.0
|
||||
5. Track versions in A_PACKAGE_VERSION_TRACKING
|
||||
6. Verify all tracked packages for untracked changes
|
||||
|
||||
### Option 2: Individual Scripts
|
||||
```powershell
|
||||
# IMPORTANT: Execute as ADMIN user
|
||||
Get-Content "01_MARS_1057_install_CT_MRDS_FILE_MANAGER_SPEC.sql" | sql "ADMIN/password@service"
|
||||
Get-Content "02_MARS_1057_install_CT_MRDS_FILE_MANAGER_BODY.sql" | sql "ADMIN/password@service"
|
||||
Get-Content "03_MARS_1057_install_ODS_FILE_MANAGER_ODS_SPEC.sql" | sql "ADMIN/password@service"
|
||||
Get-Content "04_MARS_1057_install_ODS_FILE_MANAGER_ODS_BODY.sql" | sql "ADMIN/password@service"
|
||||
Get-Content "track_package_versions.sql" | sql "ADMIN/password@service"
|
||||
Get-Content "verify_packages_version.sql" | sql "ADMIN/password@service"
|
||||
```
|
||||
|
||||
## Verification
|
||||
```sql
|
||||
-- Check FILE_MANAGER version
|
||||
SELECT CT_MRDS.FILE_MANAGER.GET_VERSION() FROM DUAL;
|
||||
-- Expected: 3.4.0
|
||||
|
||||
-- Check FILE_MANAGER_ODS version
|
||||
SELECT ODS.FILE_MANAGER_ODS.GET_VERSION() FROM DUAL;
|
||||
-- Expected: 2.2.0
|
||||
|
||||
-- Check for errors (ADMIN user checks specific schema)
|
||||
SELECT * FROM ALL_ERRORS
|
||||
WHERE OWNER IN ('CT_MRDS', 'ODS')
|
||||
AND NAME IN ('FILE_MANAGER', 'FILE_MANAGER_ODS');
|
||||
-- Expected: No rows
|
||||
|
||||
-- Verify new FILE_MANAGER procedures exist
|
||||
SELECT procedure_name
|
||||
FROM ALL_PROCEDURES
|
||||
WHERE OWNER = 'CT_MRDS'
|
||||
AND object_name = 'FILE_MANAGER'
|
||||
AND procedure_name IN ('CREATE_EXTERNAL_TABLES_SET', 'CREATE_EXTERNAL_TABLES_BATCH');
|
||||
-- Expected: 2 rows
|
||||
|
||||
-- Verify new FILE_MANAGER_ODS procedures exist
|
||||
SELECT procedure_name
|
||||
FROM ALL_PROCEDURES
|
||||
WHERE OWNER = 'ODS'
|
||||
AND object_name = 'FILE_MANAGER_ODS'
|
||||
AND procedure_name IN ('CREATE_EXTERNAL_TABLES_SET', 'CREATE_EXTERNAL_TABLES_BATCH');
|
||||
-- Expected: 2 rows
|
||||
|
||||
-- Check for untracked changes
|
||||
SELECT CT_MRDS.ENV_MANAGER.CHECK_PACKAGE_CHANGES('CT_MRDS', 'FILE_MANAGER') FROM DUAL;
|
||||
-- Expected: OK: Package CT_MRDS.FILE_MANAGER has not changed.
|
||||
|
||||
SELECT CT_MRDS.ENV_MANAGER.CHECK_PACKAGE_CHANGES('ODS', 'FILE_MANAGER_ODS') FROM DUAL;
|
||||
-- Expected: OK: Package ODS.FILE_MANAGER_ODS has not changed.
|
||||
```
|
||||
|
||||
## Rollback
|
||||
```powershell
|
||||
# IMPORTANT: Execute as ADMIN user
|
||||
Get-Content "MARS_Packages/REL03/MARS-1057/rollback_mars1057.sql" | sql "ADMIN/password@service"
|
||||
```
|
||||
|
||||
**Rollback restores:**
|
||||
- FILE_MANAGER package specification v3.3.0
|
||||
- FILE_MANAGER package body v3.3.0
|
||||
- FILE_MANAGER_ODS package specification v2.1.0
|
||||
- FILE_MANAGER_ODS package body v2.1.0
|
||||
- Removes CREATE_EXTERNAL_TABLES_SET procedures from both packages
|
||||
- Removes CREATE_EXTERNAL_TABLES_BATCH procedures from both packages
|
||||
|
||||
## Expected Changes
|
||||
- **FILE_MANAGER package**: v3.3.0 → v3.4.0
|
||||
- **FILE_MANAGER_ODS package**: v2.1.0 → v2.2.0
|
||||
- **New procedures in FILE_MANAGER**: CREATE_EXTERNAL_TABLES_SET, CREATE_EXTERNAL_TABLES_BATCH
|
||||
- **New procedures in FILE_MANAGER_ODS**: CREATE_EXTERNAL_TABLES_SET, CREATE_EXTERNAL_TABLES_BATCH
|
||||
- **FILE_MANAGER SPEC size**: +3.3 KB (declaration and documentation)
|
||||
- **FILE_MANAGER BODY size**: +8.6 KB (implementation with logging)
|
||||
- **FILE_MANAGER_ODS SPEC size**: +2.8 KB (wrapper declarations)
|
||||
- **FILE_MANAGER_ODS BODY size**: +4.5 KB (wrapper implementations)
|
||||
|
||||
## Testing
|
||||
|
||||
### Test 1: Create Single Set (CT_MRDS.FILE_MANAGER)
|
||||
```sql
|
||||
BEGIN
|
||||
CT_MRDS.FILE_MANAGER.CREATE_EXTERNAL_TABLES_SET(
|
||||
pSourceFileConfigKey => 123
|
||||
);
|
||||
END;
|
||||
/
|
||||
|
||||
-- Verify tables created
|
||||
SELECT table_name
|
||||
FROM ALL_TABLES
|
||||
WHERE OWNER = 'ODS'
|
||||
AND (table_name LIKE '%_INBOX'
|
||||
OR table_name LIKE '%_ODS'
|
||||
OR table_name LIKE '%_ARCHIVE');
|
||||
```
|
||||
|
||||
### Test 2: Create Single Set (ODS.FILE_MANAGER_ODS)
|
||||
```sql
|
||||
BEGIN
|
||||
ODS.FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_SET(
|
||||
pSourceFileConfigKey => 123,
|
||||
pRecreate => TRUE
|
||||
);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
### Test 3: Batch Creation (CT_MRDS.FILE_MANAGER)
|
||||
```sql
|
||||
BEGIN
|
||||
FILE_MANAGER.CREATE_EXTERNAL_TABLES_SET(
|
||||
pSourceFileConfigKey => 123
|
||||
);
|
||||
END;
|
||||
/
|
||||
|
||||
-- Verify tables created
|
||||
SELECT table_name
|
||||
FROM ALL_TABLES
|
||||
WHERE OWNER = 'ODS'
|
||||
AND table_name LIKE '%_INBOX'
|
||||
OR table_name LIKE '%_ODS'
|
||||
OR table_name LIKE '%_ARCHIVE';
|
||||
```
|
||||
|
||||
### Test 2: Batch Creation
|
||||
```sql
|
||||
BEGIN
|
||||
FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
pSourceKey => 'C2D'
|
||||
);
|
||||
END;
|
||||
/
|
||||
|
||||
-- Check process log for results
|
||||
SELECT *
|
||||
FROM CT_MRDS.A_PROCESS_LOG
|
||||
WHERE LOG_TIMESTAMP > SYSDATE - INTERVAL '1' HOUR
|
||||
AND PROCEDURE_NAME LIKE '%CREATE_EXTERNAL_TABLES%'
|
||||
ORDER BY LOG_TIMESTAMP DESC;
|
||||
```
|
||||
|
||||
### Test 3: Recreate Existing Tables
|
||||
```sql
|
||||
BEGIN
|
||||
FILE_MANAGER.CREATE_EXTERNAL_TABLES_SET(
|
||||
pSourceFileConfigKey => 123,
|
||||
pRecreate => TRUE
|
||||
);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Example 1: Setup All External Tables for New Source
|
||||
```sql
|
||||
-- 1. Add source configuration
|
||||
CALL FILE_MANAGER.ADD_SOURCE('LM', 'Liquidity Management');
|
||||
|
||||
-- 2. Add file configurations
|
||||
CALL FILE_MANAGER.ADD_SOURCE_FILE_CONFIG(
|
||||
pSourceKey => 'LM',
|
||||
pSourceFileType => 'INPUT',
|
||||
pSourceFileId => 'STANDING_FACILITIES',
|
||||
pSourceFileDesc => 'Standing Facilities Data',
|
||||
pSourceFileNamePattern => 'SF_*.csv',
|
||||
pTableId => 'STANDING_FACILITIES',
|
||||
pTemplateTableName => 'CT_ET_TEMPLATES.LM_STANDING_FACILITIES',
|
||||
pEncoding => 'UTF8'
|
||||
);
|
||||
|
||||
-- 3. Create all external tables for this source
|
||||
BEGIN
|
||||
FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
pSourceKey => 'LM'
|
||||
);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
### Example 2: Recreate All External Tables
|
||||
```sql
|
||||
-- Useful after bucket URI changes or template table modifications
|
||||
BEGIN
|
||||
FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
pRecreate => TRUE
|
||||
);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
### Example 3: Create Tables for Specific File Type
|
||||
```sql
|
||||
BEGIN
|
||||
FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
pSourceFileId => 'UC_DISSEM'
|
||||
);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
## Known Issues
|
||||
None
|
||||
|
||||
## Dependencies
|
||||
- **CT_MRDS.ENV_MANAGER** - Logging and error handling
|
||||
- **ODS.FILE_MANAGER_ODS** - AUTHID DEFINER wrapper for external table creation
|
||||
- **CT_MRDS.A_SOURCE_FILE_CONFIG** - Source file configuration metadata
|
||||
- **CT_ET_TEMPLATES schema** - Template table definitions
|
||||
|
||||
## Related
|
||||
- **MARS-1056** - VARCHAR2 CHAR/BYTE semantics fix
|
||||
- **MARS-1049** - CSV encoding support
|
||||
- **Package Deployment Guide** - Standard deployment procedures
|
||||
- **Tables Setup Guide** - External table configuration guide
|
||||
|
||||
## Notes
|
||||
- All installations must be executed as ADMIN user
|
||||
- Use `ALL_*` views instead of `USER_*` views for verification
|
||||
- Master scripts include SPOOL logging for audit trail
|
||||
- ACCEPT validation prevents accidental execution
|
||||
- Follows official path patterns: INBOX (3-level), ODS (2-level), ARCHIVE (2-level)
|
||||
@@ -1,10 +1,11 @@
|
||||
-- ===================================================================
|
||||
-- MARS-1057 INSTALL SCRIPT: Batch External Table Creation
|
||||
-- ===================================================================
|
||||
-- Purpose: Install FILE_MANAGER v3.4.0 with batch external table creation procedures
|
||||
-- Purpose: Install FILE_MANAGER v3.5.0 with batch external table creation procedures
|
||||
-- and area filter functionality
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2025-11-27
|
||||
-- Version: 3.4.0
|
||||
-- Date: 2026-02-18
|
||||
-- Version: 3.5.0
|
||||
|
||||
-- Dynamic spool file generation (using SYS_CONTEXT - no DBA privileges required)
|
||||
-- Log files are automatically created in log/ subdirectory
|
||||
@@ -29,20 +30,28 @@ SET PAUSE OFF
|
||||
-- ALTER SESSION SET CURRENT_SCHEMA = CT_MRDS;
|
||||
|
||||
PROMPT =========================================================================
|
||||
PROMPT MARS-1057: Batch External Table Creation
|
||||
PROMPT MARS-1057: Batch External Table Creation + Area Filter
|
||||
PROMPT =========================================================================
|
||||
PROMPT
|
||||
PROMPT This script will install FILE_MANAGER package v3.4.0 with new features:
|
||||
PROMPT This script will install FILE_MANAGER package v3.5.0 with new features:
|
||||
PROMPT - CREATE_EXTERNAL_TABLES_SET procedure
|
||||
PROMPT - CREATE_EXTERNAL_TABLES_BATCH procedure
|
||||
PROMPT - pArea parameter for selective table creation (INBOX/ODS/ARCHIVE/ALL)
|
||||
PROMPT - pRestoreGrants parameter for grant preservation during recreate
|
||||
PROMPT
|
||||
PROMPT And FILE_MANAGER_ODS package v2.2.0 with wrapper procedures.
|
||||
PROMPT And FILE_MANAGER_ODS package v2.4.0 with wrapper procedures.
|
||||
PROMPT
|
||||
PROMPT Changes:
|
||||
PROMPT - FILE_MANAGER package specification (3.3.0 -> 3.4.0)
|
||||
PROMPT - FILE_MANAGER package body (3.3.0 -> 3.4.0)
|
||||
PROMPT - FILE_MANAGER_ODS package specification (2.1.0 -> 2.2.0)
|
||||
PROMPT - FILE_MANAGER_ODS package body (2.1.0 -> 2.2.0)
|
||||
PROMPT - FILE_MANAGER package specification (3.3.0 -> 3.5.0)
|
||||
PROMPT - FILE_MANAGER package body (3.3.0 -> 3.5.0)
|
||||
PROMPT - FILE_MANAGER_ODS package specification (2.1.0 -> 2.4.0)
|
||||
PROMPT - FILE_MANAGER_ODS package body (2.1.0 -> 2.4.0)
|
||||
PROMPT
|
||||
PROMPT New functionality:
|
||||
PROMPT - pArea => 'INBOX' : creates only INBOX table
|
||||
PROMPT - pArea => 'ODS' : creates only ODS table
|
||||
PROMPT - pArea => 'ARCHIVE' : creates only ARCHIVE table
|
||||
PROMPT - pArea => 'ALL' : creates all tables (default)
|
||||
PROMPT
|
||||
PROMPT Expected Duration: 1-2 minutes
|
||||
PROMPT =========================================================================
|
||||
@@ -60,25 +69,25 @@ WHENEVER SQLERROR CONTINUE
|
||||
|
||||
PROMPT
|
||||
PROMPT =========================================================================
|
||||
PROMPT Step 1: Install FILE_MANAGER Package Specification v3.4.0
|
||||
PROMPT Step 1: Install FILE_MANAGER Package Specification v3.5.0
|
||||
PROMPT =========================================================================
|
||||
@@01_MARS_1057_install_CT_MRDS_FILE_MANAGER_SPEC.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT =========================================================================
|
||||
PROMPT Step 2: Install FILE_MANAGER Package Body v3.4.0
|
||||
PROMPT Step 2: Install FILE_MANAGER Package Body v3.5.0
|
||||
PROMPT =========================================================================
|
||||
@@02_MARS_1057_install_CT_MRDS_FILE_MANAGER_BODY.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT =========================================================================
|
||||
PROMPT Step 3: Install FILE_MANAGER_ODS Package Specification v2.2.0
|
||||
PROMPT Step 3: Install FILE_MANAGER_ODS Package Specification v2.4.0
|
||||
PROMPT =========================================================================
|
||||
@@03_MARS_1057_install_ODS_FILE_MANAGER_ODS_SPEC.sql
|
||||
|
||||
PROMPT
|
||||
PROMPT =========================================================================
|
||||
PROMPT Step 4: Install FILE_MANAGER_ODS Package Body v2.2.0
|
||||
PROMPT Step 4: Install FILE_MANAGER_ODS Package Body v2.4.0
|
||||
PROMPT =========================================================================
|
||||
@@04_MARS_1057_install_ODS_FILE_MANAGER_ODS_BODY.sql
|
||||
|
||||
|
||||
@@ -1,6 +1,66 @@
|
||||
create or replace PACKAGE BODY CT_MRDS.FILE_MANAGER
|
||||
AS
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
-- PRIVATE FUNCTION: NORMALIZE_DATE_FORMAT
|
||||
----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* Purpose: Normalize Oracle date format strings for use in external tables
|
||||
*
|
||||
* Problem: ISO 8601 formats like 'YYYY-MM-DDTHH24:MI:SS.FF3TZH:TZM' fail because
|
||||
* literal character 'T' must be enclosed in double quotes for Oracle
|
||||
* external table DATE column definitions.
|
||||
*
|
||||
* Solution: Detect unquoted 'T' separator and wrap it in double quotes
|
||||
*
|
||||
* Parameters:
|
||||
* pDateFormat - Original date format from A_COLUMN_DATE_FORMAT table
|
||||
*
|
||||
* Returns: Normalized format with quoted 'T' if applicable
|
||||
*
|
||||
* Examples:
|
||||
* Input: 'YYYY-MM-DDTHH24:MI:SS.FF3TZH:TZM'
|
||||
* Output: 'YYYY-MM-DD"T"HH24:MI:SS.FF3TZH:TZM'
|
||||
*
|
||||
* Input: 'DD/MM/YYYY HH24:MI:SS' (no T)
|
||||
* Output: 'DD/MM/YYYY HH24:MI:SS' (unchanged)
|
||||
*
|
||||
* Input: 'YYYY-MM-DD"T"HH24:MI:SS' (already quoted)
|
||||
* Output: 'YYYY-MM-DD"T"HH24:MI:SS' (unchanged)
|
||||
*
|
||||
* Author: Grzegorz Michalski
|
||||
* Date: 2025-11-27
|
||||
* Version: 1.0.0 (MARS-1046)
|
||||
*/
|
||||
FUNCTION NORMALIZE_DATE_FORMAT(pDateFormat VARCHAR2) RETURN VARCHAR2 IS
|
||||
vNormalizedFormat VARCHAR2(500);
|
||||
BEGIN
|
||||
-- Return NULL if input is NULL
|
||||
IF pDateFormat IS NULL THEN
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
vNormalizedFormat := pDateFormat;
|
||||
|
||||
-- Check if 'T' separator exists and is NOT already quoted
|
||||
-- Pattern: [YMD]T[HM] (date component + T + time component)
|
||||
IF INSTR(vNormalizedFormat, '"T"') = 0 AND
|
||||
REGEXP_LIKE(vNormalizedFormat, '[YMD]T[HM]') THEN
|
||||
|
||||
-- Wrap 'T' in double quotes using regex replace
|
||||
-- Pattern matches: (date format char) + T + (time format char)
|
||||
-- Replacement: \1 + "T" + \2
|
||||
vNormalizedFormat := REGEXP_REPLACE(vNormalizedFormat, '([YMD])T([HM])', '\1"T"\2');
|
||||
END IF;
|
||||
|
||||
RETURN vNormalizedFormat;
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
-- If normalization fails, return original format (safety fallback)
|
||||
RETURN pDateFormat;
|
||||
END NORMALIZE_DATE_FORMAT;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION GET_SOURCE_FILE_CONFIG(pFileUri IN VARCHAR2 DEFAULT NULL
|
||||
@@ -1254,8 +1314,17 @@ AS
|
||||
-- Note: field_list uses CHAR() for CSV field definitions - this is correct behavior
|
||||
pFieldList := pFieldList ||
|
||||
CASE
|
||||
WHEN REGEXP_SUBSTR(rec.data_type, '^[A-Z]+') IN ('DATE', 'TIMESTAMP') THEN
|
||||
rec.quoted_column_name || ' DATE ' || CHR(39) || GET_DATE_FORMAT(pTemplateTableName => pTemplateTableName, pColumnName => rec.column_name) || CHR(39)
|
||||
WHEN rec.data_type = 'DATE' THEN
|
||||
-- MARS-1046: DATE format - wrap with NORMALIZE_DATE_FORMAT to fix ISO 8601 'T' separator
|
||||
rec.quoted_column_name || ' DATE ' || CHR(39) || NORMALIZE_DATE_FORMAT(GET_DATE_FORMAT(pTemplateTableName => pTemplateTableName, pColumnName => rec.column_name)) || CHR(39)
|
||||
WHEN rec.data_type LIKE 'TIMESTAMP%WITH TIME ZONE' THEN
|
||||
-- MARS-1046: TIMESTAMP WITH TIME ZONE format for ISO 8601 with fractional seconds and timezone
|
||||
-- Syntax: column_name CHAR(length) DATE_FORMAT TIMESTAMP WITH TIME ZONE MASK "format"
|
||||
-- Use fixed length of 50 for ISO 8601 format (e.g., "2012-03-02T14:16:23.798+01:00" = 29 chars)
|
||||
rec.quoted_column_name || ' CHAR(50) DATE_FORMAT TIMESTAMP WITH TIME ZONE MASK ' || CHR(39) || NORMALIZE_DATE_FORMAT(GET_DATE_FORMAT(pTemplateTableName => pTemplateTableName, pColumnName => rec.column_name)) || CHR(39)
|
||||
WHEN REGEXP_SUBSTR(rec.data_type, '^[A-Z]+') = 'TIMESTAMP' THEN
|
||||
-- Other TIMESTAMP types (without timezone)
|
||||
rec.quoted_column_name || ' TIMESTAMP ' || CHR(39) || NORMALIZE_DATE_FORMAT(GET_DATE_FORMAT(pTemplateTableName => pTemplateTableName, pColumnName => rec.column_name)) || CHR(39)
|
||||
WHEN rec.data_type IN ('CHAR', 'NCHAR', 'VARCHAR2', 'NVARCHAR2') THEN
|
||||
-- For CSV field definitions, use data_length for CHAR() specification
|
||||
rec.quoted_column_name || ' CHAR(' || rec.data_length || ')'
|
||||
@@ -1899,9 +1968,23 @@ AS
|
||||
|
||||
PROCEDURE CREATE_EXTERNAL_TABLES_SET (
|
||||
pSourceFileConfigKey IN NUMBER,
|
||||
pRecreate IN BOOLEAN DEFAULT FALSE
|
||||
pRecreate IN BOOLEAN DEFAULT FALSE,
|
||||
pRestoreGrants IN BOOLEAN DEFAULT TRUE,
|
||||
pArea IN VARCHAR2 DEFAULT 'ALL'
|
||||
)
|
||||
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);
|
||||
@@ -1917,28 +2000,124 @@ AS
|
||||
vOdsPrefix VARCHAR2(500);
|
||||
vArchivePrefix VARCHAR2(500);
|
||||
|
||||
vTableExists NUMBER;
|
||||
vParameters VARCHAR2(4000);
|
||||
vAreaUpper VARCHAR2(20);
|
||||
|
||||
-- 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 ALL_TAB_PRIVS
|
||||
WHERE table_schema = SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA')
|
||||
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: ' || SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') || '.' || 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 ' || SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') || '.' || 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: ' || SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') || '.' || 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
|
||||
FROM ALL_TABLES
|
||||
WHERE OWNER = 'ODS' AND TABLE_NAME = pTableName;
|
||||
|
||||
IF vTableExists > 0 THEN
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Dropping existing table: ' || pTableName, 'INFO');
|
||||
EXECUTE IMMEDIATE 'DROP TABLE ODS.' || pTableName;
|
||||
END IF;
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Attempting to drop table: ' || pTableName, 'DEBUG');
|
||||
EXECUTE IMMEDIATE 'DROP TABLE ' || SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') || '.' || pTableName;
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Table dropped successfully: ' || pTableName, 'INFO');
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Error dropping table ' || pTableName || ': ' || SQLERRM, 'WARNING');
|
||||
IF SQLCODE = -942 THEN -- ORA-00942: table or view does not exist
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Table does not exist, skipping drop: ' || pTableName, 'INFO');
|
||||
ELSE
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Error dropping table ' || pTableName || ': ' || SQLERRM, 'WARNING');
|
||||
RAISE; -- Re-raise if not "table not exists" error
|
||||
END IF;
|
||||
END DROP_IF_EXISTS;
|
||||
|
||||
BEGIN
|
||||
-- Validate and normalize pArea parameter
|
||||
vAreaUpper := UPPER(TRIM(pArea));
|
||||
|
||||
IF vAreaUpper NOT IN ('INBOX', 'ODS', 'ARCHIVE', 'ALL') THEN
|
||||
vgMsgTmp := 'Invalid pArea parameter: ''' || pArea || '''. Must be one of: INBOX, ODS, ARCHIVE, ALL';
|
||||
RAISE_APPLICATION_ERROR(-20010, vgMsgTmp);
|
||||
END IF;
|
||||
|
||||
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,
|
||||
'pArea => ''' || vAreaUpper || ''''
|
||||
));
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Start CREATE_EXTERNAL_TABLES_SET', 'INFO', vParameters);
|
||||
|
||||
@@ -1971,52 +2150,103 @@ AS
|
||||
vArchivePrefix := 'ARCHIVE/' || vSourceKey || '/' || vTableId;
|
||||
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT(
|
||||
'Creating external tables for: ' || vSourceKey || '/' || vSourceFileId || '/' || vTableId,
|
||||
'Creating external tables for: ' || vSourceKey || '/' || vSourceFileId || '/' || vTableId ||
|
||||
' (Area: ' || vAreaUpper || ')',
|
||||
'INFO'
|
||||
);
|
||||
|
||||
-- 4. DROP existing tables if pRecreate = TRUE
|
||||
IF pRecreate THEN
|
||||
DROP_IF_EXISTS(vInboxTableName);
|
||||
DROP_IF_EXISTS(vOdsTableName);
|
||||
DROP_IF_EXISTS(vArchiveTableName);
|
||||
-- Save grants before dropping tables (if pRestoreGrants = TRUE)
|
||||
IF pRestoreGrants THEN
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Saving grants before dropping tables...', 'INFO');
|
||||
|
||||
IF vAreaUpper IN ('INBOX', 'ALL') THEN
|
||||
SAVE_GRANTS(vInboxTableName, vInboxGrants);
|
||||
END IF;
|
||||
|
||||
IF vAreaUpper IN ('ODS', 'ALL') THEN
|
||||
SAVE_GRANTS(vOdsTableName, vOdsGrants);
|
||||
END IF;
|
||||
|
||||
IF vAreaUpper IN ('ARCHIVE', 'ALL') THEN
|
||||
SAVE_GRANTS(vArchiveTableName, vArchiveGrants);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- Drop existing tables based on pArea
|
||||
IF vAreaUpper IN ('INBOX', 'ALL') THEN
|
||||
DROP_IF_EXISTS(vInboxTableName);
|
||||
END IF;
|
||||
|
||||
IF vAreaUpper IN ('ODS', 'ALL') THEN
|
||||
DROP_IF_EXISTS(vOdsTableName);
|
||||
END IF;
|
||||
|
||||
IF vAreaUpper IN ('ARCHIVE', 'ALL') THEN
|
||||
DROP_IF_EXISTS(vArchiveTableName);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- 5. Create INBOX external table
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Creating INBOX external table: ' || vInboxTableName, 'INFO');
|
||||
CREATE_EXTERNAL_TABLE(
|
||||
pTableName => vInboxTableName,
|
||||
pTemplateTableName => vTemplateTableName,
|
||||
pPrefix => vInboxPrefix,
|
||||
pBucketUri => ENV_MANAGER.gvInboxBucketUri,
|
||||
pDelimiter => vDelimiter,
|
||||
pEncoding => vEncoding
|
||||
);
|
||||
-- 5. Create INBOX external table (if requested)
|
||||
IF vAreaUpper IN ('INBOX', 'ALL') THEN
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Creating INBOX external table: ' || vInboxTableName, 'INFO');
|
||||
CREATE_EXTERNAL_TABLE(
|
||||
pTableName => vInboxTableName,
|
||||
pTemplateTableName => vTemplateTableName,
|
||||
pPrefix => vInboxPrefix,
|
||||
pBucketUri => ENV_MANAGER.gvInboxBucketUri,
|
||||
pDelimiter => vDelimiter,
|
||||
pEncoding => vEncoding
|
||||
);
|
||||
END IF;
|
||||
|
||||
-- 6. Create ODS external table
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Creating ODS external table: ' || vOdsTableName, 'INFO');
|
||||
CREATE_EXTERNAL_TABLE(
|
||||
pTableName => vOdsTableName,
|
||||
pTemplateTableName => vTemplateTableName,
|
||||
pPrefix => vOdsPrefix,
|
||||
pBucketUri => ENV_MANAGER.gvDataBucketUri,
|
||||
pDelimiter => vDelimiter,
|
||||
pEncoding => vEncoding
|
||||
);
|
||||
-- 6. Create ODS external table (if requested)
|
||||
IF vAreaUpper IN ('ODS', 'ALL') THEN
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Creating ODS external table: ' || vOdsTableName, 'INFO');
|
||||
CREATE_EXTERNAL_TABLE(
|
||||
pTableName => vOdsTableName,
|
||||
pTemplateTableName => vTemplateTableName,
|
||||
pPrefix => vOdsPrefix,
|
||||
pBucketUri => ENV_MANAGER.gvDataBucketUri,
|
||||
pDelimiter => vDelimiter,
|
||||
pEncoding => vEncoding
|
||||
);
|
||||
END IF;
|
||||
|
||||
-- 7. Create ARCHIVE external table
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Creating ARCHIVE external table: ' || vArchiveTableName, 'INFO');
|
||||
CREATE_EXTERNAL_TABLE(
|
||||
pTableName => vArchiveTableName,
|
||||
pTemplateTableName => vTemplateTableName,
|
||||
pPrefix => vArchivePrefix,
|
||||
pBucketUri => ENV_MANAGER.gvArchiveBucketUri,
|
||||
pDelimiter => vDelimiter,
|
||||
pEncoding => vEncoding
|
||||
);
|
||||
-- 7. Create ARCHIVE external table (if requested)
|
||||
IF vAreaUpper IN ('ARCHIVE', 'ALL') THEN
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Creating ARCHIVE external table: ' || vArchiveTableName, 'INFO');
|
||||
CREATE_EXTERNAL_TABLE(
|
||||
pTableName => vArchiveTableName,
|
||||
pTemplateTableName => vTemplateTableName,
|
||||
pPrefix => vArchivePrefix,
|
||||
pBucketUri => ENV_MANAGER.gvArchiveBucketUri,
|
||||
pDelimiter => vDelimiter,
|
||||
pEncoding => vEncoding
|
||||
);
|
||||
END IF;
|
||||
|
||||
-- 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');
|
||||
|
||||
IF vAreaUpper IN ('INBOX', 'ALL') THEN
|
||||
RESTORE_GRANTS(vInboxTableName, vInboxGrants);
|
||||
END IF;
|
||||
|
||||
IF vAreaUpper IN ('ODS', 'ALL') THEN
|
||||
RESTORE_GRANTS(vOdsTableName, vOdsGrants);
|
||||
END IF;
|
||||
|
||||
IF vAreaUpper IN ('ARCHIVE', 'ALL') THEN
|
||||
RESTORE_GRANTS(vArchiveTableName, vArchiveGrants);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT(
|
||||
'End CREATE_EXTERNAL_TABLES_SET - Successfully created all 3 external tables for config: ' || pSourceFileConfigKey,
|
||||
'End CREATE_EXTERNAL_TABLES_SET - Successfully created external tables for config: ' ||
|
||||
pSourceFileConfigKey || ' (Area: ' || vAreaUpper || ')',
|
||||
'INFO',
|
||||
vParameters
|
||||
);
|
||||
@@ -2034,19 +2264,32 @@ 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,
|
||||
pArea IN VARCHAR2 DEFAULT 'ALL'
|
||||
)
|
||||
IS
|
||||
vCount NUMBER := 0;
|
||||
vProcessed NUMBER := 0;
|
||||
vFailed NUMBER := 0;
|
||||
vParameters VARCHAR2(4000);
|
||||
vAreaUpper VARCHAR2(20);
|
||||
BEGIN
|
||||
-- Validate and normalize pArea parameter
|
||||
vAreaUpper := UPPER(TRIM(pArea));
|
||||
|
||||
IF vAreaUpper NOT IN ('INBOX', 'ODS', 'ARCHIVE', 'ALL') THEN
|
||||
vgMsgTmp := 'Invalid pArea parameter: ''' || pArea || '''. Must be one of: INBOX, ODS, ARCHIVE, ALL';
|
||||
RAISE_APPLICATION_ERROR(-20010, vgMsgTmp);
|
||||
END IF;
|
||||
|
||||
vParameters := ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST(
|
||||
'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,
|
||||
'pArea => ''' || vAreaUpper || ''''
|
||||
));
|
||||
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Start CREATE_EXTERNAL_TABLES_BATCH', 'INFO', vParameters);
|
||||
@@ -2066,14 +2309,16 @@ AS
|
||||
BEGIN
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT(
|
||||
'Creating external tables set for: ' || rec.A_SOURCE_KEY || '/' ||
|
||||
rec.SOURCE_FILE_ID || '/' || rec.TABLE_ID,
|
||||
rec.SOURCE_FILE_ID || '/' || rec.TABLE_ID || ' (Area: ' || vAreaUpper || ')',
|
||||
'INFO'
|
||||
);
|
||||
|
||||
-- Call procedure to create set of 3 tables
|
||||
-- Call procedure to create set of tables (based on pArea)
|
||||
CREATE_EXTERNAL_TABLES_SET(
|
||||
pSourceFileConfigKey => rec.A_SOURCE_FILE_CONFIG_KEY,
|
||||
pRecreate => pRecreate
|
||||
pRecreate => pRecreate,
|
||||
pRestoreGrants => pRestoreGrants,
|
||||
pArea => vAreaUpper
|
||||
);
|
||||
|
||||
vProcessed := vProcessed + 1;
|
||||
@@ -2092,7 +2337,7 @@ AS
|
||||
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT(
|
||||
'End CREATE_EXTERNAL_TABLES_BATCH - Total: ' || vCount ||
|
||||
', Processed: ' || vProcessed || ', Failed: ' || vFailed,
|
||||
', Processed: ' || vProcessed || ', Failed: ' || vFailed || ' (Area: ' || vAreaUpper || ')',
|
||||
'INFO',
|
||||
vParameters
|
||||
);
|
||||
|
||||
@@ -17,13 +17,15 @@ AS
|
||||
**/
|
||||
|
||||
-- Package Version Information (Semantic Versioning: MAJOR.MINOR.PATCH)
|
||||
PACKAGE_VERSION CONSTANT VARCHAR2(10) := '3.4.0';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2025-11-27 14:00:00';
|
||||
PACKAGE_VERSION CONSTANT VARCHAR2(10) := '3.5.0';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2026-02-18 16:00:00';
|
||||
PACKAGE_AUTHOR CONSTANT VARCHAR2(100) := 'Grzegorz Michalski';
|
||||
|
||||
-- Version History (Latest changes first)
|
||||
VERSION_HISTORY CONSTANT VARCHAR2(4000) :=
|
||||
'3.5.0 (2026-02-18): MARS-1057 - Added pArea parameter for selective table creation (INBOX/ODS/ARCHIVE/ALL)' || CHR(13)||CHR(10) ||
|
||||
'3.4.0 (2025-11-27): MARS-1057 - Added CREATE_EXTERNAL_TABLES_SET and CREATE_EXTERNAL_TABLES_BATCH procedures for batch external table creation' || CHR(13)||CHR(10) ||
|
||||
'3.3.1 (2025-11-27): MARS-1046 - Fixed ISO 8601 datetime format parsing with milliseconds and timezone (e.g., 2012-03-02T14:16:23.798+01:00)' || CHR(13)||CHR(10) ||
|
||||
'3.3.0 (2025-11-26): MARS-1056 - Fixed VARCHAR2 definitions in GENERATE_EXTERNAL_TABLE_PARAMS to preserve CHAR/BYTE semantics from template tables' || CHR(13)||CHR(10) ||
|
||||
'3.2.1 (2025-11-24): MARS-1049 - Added pEncoding parameter support for CSV character set specification' || CHR(13)||CHR(10) ||
|
||||
'3.2.0 (2025-10-22): Added package versioning system using centralized ENV_MANAGER functions' || CHR(13)||CHR(10) ||
|
||||
@@ -601,48 +603,72 @@ AS
|
||||
|
||||
/**
|
||||
* @name CREATE_EXTERNAL_TABLES_SET
|
||||
* @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.
|
||||
* @desc Creates a complete set of external tables 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.
|
||||
* The pArea parameter allows selective table creation.
|
||||
* @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
|
||||
* @example BEGIN
|
||||
* @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
|
||||
* @param pArea - Specifies which tables to create: 'INBOX', 'ODS', 'ARCHIVE', or 'ALL' (default)
|
||||
* 'INBOX' - creates only INBOX table
|
||||
* 'ODS' - creates only ODS table
|
||||
* 'ARCHIVE' - creates only ARCHIVE table
|
||||
* 'ALL' - creates all three tables (default)
|
||||
* @example -- Create only INBOX table
|
||||
* BEGIN
|
||||
* FILE_MANAGER.CREATE_EXTERNAL_TABLES_SET(
|
||||
* pSourceFileConfigKey => 123,
|
||||
* pRecreate => FALSE
|
||||
* pArea => 'INBOX'
|
||||
* );
|
||||
* 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
|
||||
*
|
||||
* -- Create all tables with grant preservation
|
||||
* BEGIN
|
||||
* FILE_MANAGER.CREATE_EXTERNAL_TABLES_SET(
|
||||
* pSourceFileConfigKey => 123,
|
||||
* pRecreate => TRUE,
|
||||
* pRestoreGrants => TRUE,
|
||||
* pArea => 'ALL'
|
||||
* );
|
||||
* END;
|
||||
* @ex_rslt Creates external table(s) in ODS schema based on pArea parameter
|
||||
**/
|
||||
PROCEDURE CREATE_EXTERNAL_TABLES_SET (
|
||||
pSourceFileConfigKey IN NUMBER,
|
||||
pRecreate IN BOOLEAN DEFAULT FALSE
|
||||
pRecreate IN BOOLEAN DEFAULT FALSE,
|
||||
pRestoreGrants IN BOOLEAN DEFAULT TRUE,
|
||||
pArea IN VARCHAR2 DEFAULT 'ALL'
|
||||
);
|
||||
|
||||
/**
|
||||
* @name CREATE_EXTERNAL_TABLES_BATCH
|
||||
* @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.
|
||||
* Processes only INPUT type files from A_SOURCE_FILE_CONFIG. Creates tables based on pArea parameter
|
||||
* (INBOX, ODS, ARCHIVE, or ALL). 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
|
||||
* @param pArea - Specifies which tables to create: 'INBOX', 'ODS', 'ARCHIVE', or 'ALL' (default)
|
||||
* @example -- Create only INBOX tables for C2D source
|
||||
* BEGIN
|
||||
* FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
* pSourceKey => 'C2D',
|
||||
* pRecreate => FALSE
|
||||
* pArea => 'INBOX'
|
||||
* );
|
||||
* END;
|
||||
*
|
||||
* -- Recreate all external tables for all sources
|
||||
* -- Create all external tables for all sources with grant preservation
|
||||
* BEGIN
|
||||
* FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
* pRecreate => TRUE
|
||||
* pRecreate => TRUE,
|
||||
* pRestoreGrants => TRUE,
|
||||
* pArea => 'ALL'
|
||||
* );
|
||||
* END;
|
||||
* @ex_rslt Returns summary: Total: 10, Processed: 9, Failed: 1
|
||||
@@ -651,7 +677,9 @@ 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,
|
||||
pArea IN VARCHAR2 DEFAULT 'ALL'
|
||||
);
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -63,20 +63,26 @@ AS
|
||||
*/
|
||||
PROCEDURE CREATE_EXTERNAL_TABLES_SET (
|
||||
pSourceFileConfigKey IN NUMBER,
|
||||
pRecreate IN BOOLEAN DEFAULT FALSE
|
||||
pRecreate IN BOOLEAN DEFAULT FALSE,
|
||||
pRestoreGrants IN BOOLEAN DEFAULT TRUE,
|
||||
pArea IN VARCHAR2 DEFAULT 'ALL'
|
||||
)
|
||||
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,
|
||||
'pArea => ''' || pArea || ''''
|
||||
)
|
||||
);
|
||||
|
||||
@@ -87,7 +93,9 @@ 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,
|
||||
pArea => pArea
|
||||
);
|
||||
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_SET', 'INFO', vParameters);
|
||||
@@ -111,14 +119,18 @@ 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,
|
||||
pArea IN VARCHAR2 DEFAULT 'ALL'
|
||||
)
|
||||
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 +138,9 @@ AS
|
||||
'pSourceKey => ''' || NVL(pSourceKey, 'NULL') || '''',
|
||||
'pSourceFileId => ''' || NVL(pSourceFileId, 'NULL') || '''',
|
||||
'pTableId => ''' || NVL(pTableId, 'NULL') || '''',
|
||||
'pRecreate => ' || vRecreateStr
|
||||
'pRecreate => ' || vRecreateStr,
|
||||
'pRestoreGrants => ' || vRestoreGrantsStr,
|
||||
'pArea => ''' || pArea || ''''
|
||||
)
|
||||
);
|
||||
|
||||
@@ -139,7 +153,9 @@ AS
|
||||
pSourceKey => pSourceKey,
|
||||
pSourceFileId => pSourceFileId,
|
||||
pTableId => pTableId,
|
||||
pRecreate => pRecreate
|
||||
pRecreate => pRecreate,
|
||||
pRestoreGrants => pRestoreGrants,
|
||||
pArea => pArea
|
||||
);
|
||||
|
||||
CT_MRDS.ENV_MANAGER.LOG_PROCESS_EVENT('End FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_BATCH', 'INFO', vParameters);
|
||||
|
||||
@@ -16,12 +16,14 @@ 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.4.0';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2026-02-18 16:00:00';
|
||||
PACKAGE_AUTHOR CONSTANT VARCHAR2(100) := 'Grzegorz Michalski';
|
||||
|
||||
-- Version History (Latest changes first)
|
||||
VERSION_HISTORY CONSTANT VARCHAR2(4000) :=
|
||||
'2.4.0 (2026-02-18): MARS-1057 - Added pArea parameter for selective table creation (INBOX/ODS/ARCHIVE/ALL)' || CHR(13)||CHR(10) ||
|
||||
'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) ||
|
||||
@@ -63,45 +65,62 @@ AS
|
||||
|
||||
/**
|
||||
* @name CREATE_EXTERNAL_TABLES_SET
|
||||
* @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. Wrapper for CT_MRDS.FILE_MANAGER.CREATE_EXTERNAL_TABLES_SET
|
||||
* with DEFINER rights to ensure objects are created in ODS schema.
|
||||
* @desc Creates a complete set of external tables for a single configuration 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.
|
||||
* If pRestoreGrants is TRUE, saves and restores table grants during recreate operation.
|
||||
* The pArea parameter allows selective table creation.
|
||||
* @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
|
||||
* @example EXEC ODS.FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_SET(
|
||||
* @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
|
||||
* @param pArea - Specifies which tables to create: 'INBOX', 'ODS', 'ARCHIVE', or 'ALL' (default)
|
||||
* @example -- Create only INBOX table
|
||||
* EXEC ODS.FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_SET(
|
||||
* pSourceFileConfigKey => 123,
|
||||
* pRecreate => FALSE
|
||||
* pArea => 'INBOX'
|
||||
* );
|
||||
* @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
|
||||
*
|
||||
* -- Create all tables with grant preservation
|
||||
* EXEC ODS.FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_SET(
|
||||
* pSourceFileConfigKey => 123,
|
||||
* pRecreate => TRUE,
|
||||
* pRestoreGrants => TRUE,
|
||||
* pArea => 'ALL'
|
||||
* );
|
||||
* @ex_rslt Creates external table(s) in ODS schema based on pArea parameter
|
||||
*/
|
||||
PROCEDURE CREATE_EXTERNAL_TABLES_SET (
|
||||
pSourceFileConfigKey IN NUMBER,
|
||||
pRecreate IN BOOLEAN DEFAULT FALSE
|
||||
pRecreate IN BOOLEAN DEFAULT FALSE,
|
||||
pRestoreGrants IN BOOLEAN DEFAULT TRUE,
|
||||
pArea IN VARCHAR2 DEFAULT 'ALL'
|
||||
);
|
||||
|
||||
/**
|
||||
* @name CREATE_EXTERNAL_TABLES_BATCH
|
||||
* @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). Wrapper for CT_MRDS.FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH
|
||||
* with DEFINER rights to ensure objects are created in ODS schema.
|
||||
* Processes only INPUT type files from A_SOURCE_FILE_CONFIG. Creates tables based on pArea parameter.
|
||||
* Wrapper for CT_MRDS.FILE_MANAGER.CREATE_EXTERNAL_TABLES_BATCH with DEFINER rights.
|
||||
* 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
|
||||
* @param pArea - Specifies which tables to create: 'INBOX', 'ODS', 'ARCHIVE', or 'ALL' (default)
|
||||
* @example -- Create only INBOX tables for C2D source
|
||||
* EXEC ODS.FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
* pSourceKey => 'C2D',
|
||||
* pRecreate => FALSE
|
||||
* pArea => 'INBOX'
|
||||
* );
|
||||
*
|
||||
* -- Recreate all external tables for all sources
|
||||
* -- Create all tables with grant preservation
|
||||
* EXEC ODS.FILE_MANAGER_ODS.CREATE_EXTERNAL_TABLES_BATCH(
|
||||
* pRecreate => TRUE
|
||||
* pRecreate => TRUE,
|
||||
* pRestoreGrants => TRUE,
|
||||
* pArea => 'ALL'
|
||||
* );
|
||||
* @ex_rslt Returns summary: Total: 10, Processed: 9, Failed: 1
|
||||
*/
|
||||
@@ -109,7 +128,9 @@ 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,
|
||||
pArea IN VARCHAR2 DEFAULT 'ALL'
|
||||
);
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
-- ===================================================================
|
||||
-- MARS-1057 ROLLBACK SCRIPT: Batch External Table Creation
|
||||
-- ===================================================================
|
||||
-- Purpose: Rollback FILE_MANAGER package to v3.3.0 (remove batch external table procedures)
|
||||
-- Purpose: Rollback FILE_MANAGER package to v3.3.0 (remove batch external table procedures and area filter)
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: 2025-11-27
|
||||
-- Date: 2026-02-18
|
||||
|
||||
-- Dynamic spool file generation (using SYS_CONTEXT - no DBA privileges required)
|
||||
-- Log files are automatically created in log/ subdirectory
|
||||
@@ -25,17 +25,19 @@ SET SERVEROUTPUT ON SIZE UNLIMITED
|
||||
SET PAUSE OFF
|
||||
|
||||
PROMPT =========================================================================
|
||||
PROMPT MARS-1057: Rollback Batch External Table Creation
|
||||
PROMPT MARS-1057: Rollback Batch External Table Creation + Area Filter
|
||||
PROMPT =========================================================================
|
||||
PROMPT WARNING: This will reverse all changes from MARS-1057 installation!
|
||||
PROMPT
|
||||
PROMPT Changes to be rolled back:
|
||||
PROMPT - FILE_MANAGER package specification (3.4.0 -> 3.3.0)
|
||||
PROMPT - FILE_MANAGER package body (3.4.0 -> 3.3.0)
|
||||
PROMPT - FILE_MANAGER_ODS package specification (2.2.0 -> 2.1.0)
|
||||
PROMPT - FILE_MANAGER_ODS package body (2.2.0 -> 2.1.0)
|
||||
PROMPT - FILE_MANAGER package specification (3.5.0 -> 3.3.0)
|
||||
PROMPT - FILE_MANAGER package body (3.5.0 -> 3.3.0)
|
||||
PROMPT - FILE_MANAGER_ODS package specification (2.4.0 -> 2.1.0)
|
||||
PROMPT - FILE_MANAGER_ODS package body (2.4.0 -> 2.1.0)
|
||||
PROMPT - Remove CREATE_EXTERNAL_TABLES_SET procedures
|
||||
PROMPT - Remove CREATE_EXTERNAL_TABLES_BATCH procedures
|
||||
PROMPT - Remove pArea parameter (selective table creation)
|
||||
PROMPT - Remove pRestoreGrants parameter (grant preservation)
|
||||
PROMPT =========================================================================
|
||||
|
||||
-- Confirm rollback with user
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,22 +9,65 @@ AS
|
||||
**/
|
||||
|
||||
-- Package Version Information
|
||||
PACKAGE_VERSION CONSTANT VARCHAR2(10) := '2.1.1';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(19) := '2025-12-04 13:10:00';
|
||||
PACKAGE_VERSION CONSTANT VARCHAR2(10) := '2.6.3';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(19) := '2026-01-28 19:30:00';
|
||||
PACKAGE_AUTHOR CONSTANT VARCHAR2(50) := 'MRDS Development Team';
|
||||
|
||||
-- Version History (last 3-5 changes)
|
||||
VERSION_HISTORY CONSTANT VARCHAR2(4000) :=
|
||||
'v2.6.3 (2026-01-28): COMPILATION FIX - Resolved ORA-00904 error in EXPORT_PARTITION_PARALLEL. SQLERRM and DBMS_UTILITY.FORMAT_ERROR_BACKTRACE cannot be used directly in SQL UPDATE statements. Now properly assigned to vgMsgTmp variable before UPDATE.' || CHR(10) ||
|
||||
'v2.6.2 (2026-01-28): CRITICAL FIX - Race condition when multiple exports run simultaneously. Changed DELETE to filter by age (>24h) instead of deleting all COMPLETED chunks. Prevents concurrent sessions from deleting each other chunks. Session-safe cleanup with TASK_NAME filtering. Enables true parallel execution of multiple export jobs.' || CHR(10) ||
|
||||
'v2.6.1 (2026-01-28): Added DELETE_FAILED_EXPORT_FILE procedure to clean up partial/corrupted files before retry. When partition fails mid-export, partial file is deleted before retry to prevent Oracle from creating _1 suffixed duplicates. Ensures clean retry without orphaned files in OCI bucket.' || CHR(10) ||
|
||||
'v2.6.0 (2026-01-28): CRITICAL FIX - Added STATUS tracking to A_PARALLEL_EXPORT_CHUNKS table to prevent data duplication on retry. System now restarts ONLY failed partitions instead of re-exporting all data. Added ERROR_MESSAGE and EXPORT_TIMESTAMP columns for better error handling and monitoring. Prevents duplicate file creation when parallel tasks fail (e.g., 22 partitions with 16 threads, 3 failures no longer duplicates 19 successful exports).' || CHR(10) ||
|
||||
'v2.5.0 (2026-01-26): Added recorddelimiter parameter with CRLF (CHR(13)||CHR(10)) for CSV exports to ensure Windows-compatible line endings. Improves cross-platform compatibility when CSV files are opened in Windows applications (Notepad, Excel).' || CHR(10) ||
|
||||
'v2.4.0 (2026-01-11): Added pTemplateTableName parameter for per-column date format configuration. Implements dynamic query building with TO_CHAR for each date/timestamp column using FILE_MANAGER.GET_DATE_FORMAT. Supports 3-tier hierarchy: column-specific, template DEFAULT, global fallback. Eliminates single dateformat limitation of DBMS_CLOUD.EXPORT_DATA.' || CHR(10) ||
|
||||
'v2.3.0 (2025-12-20): Added parallel partition processing using DBMS_PARALLEL_EXECUTE. New pParallelDegree parameter (1-16, default 1) for EXPORT_TABLE_DATA_BY_DATE and EXPORT_TABLE_DATA_TO_CSV_BY_DATE procedures. Each year/month partition processed in separate thread for improved performance.' || CHR(10) ||
|
||||
'v2.2.0 (2025-12-19): DRY refactoring - extracted shared helper functions (sanitizeFilename, VALIDATE_TABLE_AND_COLUMNS, GET_PARTITIONS, EXPORT_SINGLE_PARTITION worker procedure). Reduced code duplication by ~400 lines. Prepared architecture for v2.3.0 parallel processing.' || CHR(10) ||
|
||||
'v2.1.1 (2025-12-04): Fixed JOIN column reference A_WORKFLOW_HISTORY_KEY -> A_ETL_LOAD_SET_KEY, added consistent column mapping and dynamic column list to EXPORT_TABLE_DATA procedure, enhanced DEBUG logging for all export operations' || CHR(10) ||
|
||||
'v2.1.1 (2025-12-04): Fixed JOIN column reference A_WORKFLOW_HISTORY_KEY -> A_ETL_LOAD_SET_KEY' || CHR(10) ||
|
||||
'v2.1.0 (2025-10-22): Added version tracking and PARTITION_YEAR/PARTITION_MONTH support' || CHR(10) ||
|
||||
'v2.0.0 (2025-10-01): Separated export functionality from FILE_MANAGER package' || CHR(10) ||
|
||||
'v1.0.0 (2025-09-15): Initial implementation within FILE_MANAGER package' || CHR(10);
|
||||
'v2.0.0 (2025-10-01): Separated export functionality from FILE_MANAGER package' || CHR(10);
|
||||
|
||||
cgBL CONSTANT VARCHAR2(2) := CHR(13)||CHR(10);
|
||||
vgMsgTmp VARCHAR2(32000);
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
-- TYPE DEFINITIONS FOR PARTITION HANDLING
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Record type for year/month partition information
|
||||
**/
|
||||
TYPE partition_rec IS RECORD (
|
||||
year VARCHAR2(4),
|
||||
month VARCHAR2(2)
|
||||
);
|
||||
|
||||
/**
|
||||
* Table type for collection of partition records
|
||||
**/
|
||||
TYPE partition_tab IS TABLE OF partition_rec;
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
-- INTERNAL PARALLEL PROCESSING CALLBACK
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @name EXPORT_PARTITION_PARALLEL
|
||||
* @desc Internal callback procedure for DBMS_PARALLEL_EXECUTE.
|
||||
* Processes single partition (year/month) chunk in parallel task.
|
||||
* Called by DBMS_PARALLEL_EXECUTE framework for each chunk.
|
||||
* This procedure is PUBLIC because DBMS_PARALLEL_EXECUTE requires it,
|
||||
* but should NOT be called directly by external code.
|
||||
* @param pStartId - Chunk start ID (CHUNK_ID from A_PARALLEL_EXPORT_CHUNKS table)
|
||||
* @param pEndId - Chunk end ID (same as pStartId for single-row chunks)
|
||||
**/
|
||||
PROCEDURE EXPORT_PARTITION_PARALLEL (
|
||||
pStartId IN NUMBER,
|
||||
pEndId IN NUMBER
|
||||
);
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
-- MAIN EXPORT PROCEDURES
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -62,6 +105,7 @@ AS
|
||||
* Allows specifying custom column list or uses T.* if pColumnList is NULL.
|
||||
* Validates that all columns in pColumnList exist in the target table.
|
||||
* Automatically adds 'T.' prefix to column names in pColumnList.
|
||||
* Supports parallel partition processing via pParallelDegree parameter (default 1, range 1-16).
|
||||
* pBucketArea parameter accepts: 'INBOX', 'ODS', 'DATA', 'ARCHIVE'
|
||||
* @example
|
||||
* begin
|
||||
@@ -73,20 +117,23 @@ AS
|
||||
* pFolderName => 'parquet_exports',
|
||||
* pColumnList => 'COLUMN1, COLUMN2, COLUMN3', -- Optional
|
||||
* pMinDate => DATE '2024-01-01',
|
||||
* pMaxDate => SYSDATE
|
||||
* pMaxDate => SYSDATE,
|
||||
* pParallelDegree => 8 -- Optional, default 1, range 1-16
|
||||
* );
|
||||
* end;
|
||||
**/
|
||||
PROCEDURE EXPORT_TABLE_DATA_BY_DATE (
|
||||
pSchemaName IN VARCHAR2,
|
||||
pTableName IN VARCHAR2,
|
||||
pKeyColumnName IN VARCHAR2,
|
||||
pBucketArea IN VARCHAR2,
|
||||
pFolderName IN VARCHAR2,
|
||||
pColumnList IN VARCHAR2 default NULL,
|
||||
pMinDate IN DATE default DATE '1900-01-01',
|
||||
pMaxDate IN DATE default SYSDATE,
|
||||
pCredentialName IN VARCHAR2 default ENV_MANAGER.gvCredentialName
|
||||
pSchemaName IN VARCHAR2,
|
||||
pTableName IN VARCHAR2,
|
||||
pKeyColumnName IN VARCHAR2,
|
||||
pBucketArea IN VARCHAR2,
|
||||
pFolderName IN VARCHAR2,
|
||||
pColumnList IN VARCHAR2 default NULL,
|
||||
pMinDate IN DATE default DATE '1900-01-01',
|
||||
pMaxDate IN DATE default SYSDATE,
|
||||
pParallelDegree IN NUMBER default 1,
|
||||
pTemplateTableName IN VARCHAR2 default NULL,
|
||||
pCredentialName IN VARCHAR2 default ENV_MANAGER.gvCredentialName
|
||||
);
|
||||
|
||||
|
||||
@@ -97,6 +144,7 @@ AS
|
||||
* Creates one CSV file for each year/month combination found in the data.
|
||||
* Uses the same date filtering mechanism with CT_ODS.A_LOAD_HISTORY as EXPORT_TABLE_DATA_BY_DATE,
|
||||
* but exports to CSV format instead of Parquet.
|
||||
* Supports parallel partition processing via pParallelDegree parameter (1-16).
|
||||
* File naming pattern: {pFileName}_YYYYMM.csv or {TABLENAME}_YYYYMM.csv (if pFileName is NULL)
|
||||
* @example
|
||||
* begin
|
||||
@@ -109,7 +157,8 @@ AS
|
||||
* pFolderName => 'exports',
|
||||
* pFileName => 'my_export.csv',
|
||||
* pMinDate => DATE '2024-01-01',
|
||||
* pMaxDate => SYSDATE
|
||||
* pMaxDate => SYSDATE,
|
||||
* pParallelDegree => 8 -- Optional, default 1, range 1-16
|
||||
* );
|
||||
*
|
||||
* -- With auto-generated filename (based on table name only)
|
||||
@@ -127,16 +176,19 @@ AS
|
||||
* end;
|
||||
**/
|
||||
PROCEDURE EXPORT_TABLE_DATA_TO_CSV_BY_DATE (
|
||||
pSchemaName IN VARCHAR2,
|
||||
pTableName IN VARCHAR2,
|
||||
pKeyColumnName IN VARCHAR2,
|
||||
pBucketArea IN VARCHAR2,
|
||||
pFolderName IN VARCHAR2,
|
||||
pFileName IN VARCHAR2 DEFAULT NULL,
|
||||
pColumnList IN VARCHAR2 default NULL,
|
||||
pMinDate IN DATE default DATE '1900-01-01',
|
||||
pMaxDate IN DATE default SYSDATE,
|
||||
pCredentialName IN VARCHAR2 default ENV_MANAGER.gvCredentialName
|
||||
pSchemaName IN VARCHAR2,
|
||||
pTableName IN VARCHAR2,
|
||||
pKeyColumnName IN VARCHAR2,
|
||||
pBucketArea IN VARCHAR2,
|
||||
pFolderName IN VARCHAR2,
|
||||
pFileName IN VARCHAR2 DEFAULT NULL,
|
||||
pColumnList IN VARCHAR2 default NULL,
|
||||
pMinDate IN DATE default DATE '1900-01-01',
|
||||
pMaxDate IN DATE default SYSDATE,
|
||||
pParallelDegree IN NUMBER default 1,
|
||||
pTemplateTableName IN VARCHAR2 default NULL,
|
||||
pMaxFileSize IN NUMBER default 104857600,
|
||||
pCredentialName IN VARCHAR2 default ENV_MANAGER.gvCredentialName
|
||||
);
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -39,6 +39,8 @@ AS
|
||||
Errors(CODE_MOVE_FILE_TO_TRASH_FAILED) := Error_Record(CODE_MOVE_FILE_TO_TRASH_FAILED, MSG_MOVE_FILE_TO_TRASH_FAILED); -- -20032
|
||||
Errors(CODE_DROP_EXPORTED_FILES_FAILED) := Error_Record(CODE_DROP_EXPORTED_FILES_FAILED, MSG_DROP_EXPORTED_FILES_FAILED); -- -20033
|
||||
Errors(CODE_INVALID_BUCKET_AREA) := Error_Record(CODE_INVALID_BUCKET_AREA, MSG_INVALID_BUCKET_AREA); -- -20034
|
||||
Errors(CODE_INVALID_PARALLEL_DEGREE) := Error_Record(CODE_INVALID_PARALLEL_DEGREE, MSG_INVALID_PARALLEL_DEGREE); -- -20110
|
||||
Errors(CODE_PARALLEL_EXECUTION_FAILED) := Error_Record(CODE_PARALLEL_EXECUTION_FAILED, MSG_PARALLEL_EXECUTION_FAILED); -- -20111
|
||||
|
||||
Errors(CODE_UNKNOWN) := Error_Record(CODE_UNKNOWN, MSG_UNKNOWN); -- -20999
|
||||
|
||||
@@ -1163,3 +1165,7 @@ BEGIN
|
||||
|
||||
INIT_VARIABLES(pEnv => gvEnv);
|
||||
END ENV_MANAGER;
|
||||
|
||||
/
|
||||
|
||||
/
|
||||
|
||||
@@ -17,12 +17,13 @@ AS
|
||||
**/
|
||||
|
||||
-- Package Version Information (Semantic Versioning: MAJOR.MINOR.PATCH)
|
||||
PACKAGE_VERSION CONSTANT VARCHAR2(10) := '3.1.0';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2025-10-22 20:57:00';
|
||||
PACKAGE_VERSION CONSTANT VARCHAR2(10) := '3.2.0';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2025-12-20 10:00:00';
|
||||
PACKAGE_AUTHOR CONSTANT VARCHAR2(100) := 'Grzegorz Michalski';
|
||||
|
||||
-- Version History (Latest changes first)
|
||||
VERSION_HISTORY CONSTANT VARCHAR2(4000) :=
|
||||
'3.2.0 (2025-12-20): Added error codes for parallel execution support (CODE_INVALID_PARALLEL_DEGREE -20110, CODE_PARALLEL_EXECUTION_FAILED -20111)' || CHR(13)||CHR(10) ||
|
||||
'3.1.0 (2025-10-22): Added package hash tracking and automatic change detection system (SHA256 hashing)' || CHR(13)||CHR(10) ||
|
||||
'3.0.0 (2025-10-22): Added package versioning system with centralized version management functions' || CHR(13)||CHR(10) ||
|
||||
'2.1.0 (2025-10-15): Added ANALYZE_VALIDATION_ERRORS function for comprehensive CSV validation analysis' || CHR(13)||CHR(10) ||
|
||||
@@ -296,6 +297,18 @@ AS
|
||||
PRAGMA EXCEPTION_INIT( ERR_INVALID_BUCKET_AREA
|
||||
,CODE_INVALID_BUCKET_AREA);
|
||||
|
||||
ERR_INVALID_PARALLEL_DEGREE EXCEPTION;
|
||||
CODE_INVALID_PARALLEL_DEGREE CONSTANT PLS_INTEGER := -20110;
|
||||
MSG_INVALID_PARALLEL_DEGREE VARCHAR2(4000) := 'Invalid parallel degree parameter. Must be between 1 and 16';
|
||||
PRAGMA EXCEPTION_INIT( ERR_INVALID_PARALLEL_DEGREE
|
||||
,CODE_INVALID_PARALLEL_DEGREE);
|
||||
|
||||
ERR_PARALLEL_EXECUTION_FAILED EXCEPTION;
|
||||
CODE_PARALLEL_EXECUTION_FAILED CONSTANT PLS_INTEGER := -20111;
|
||||
MSG_PARALLEL_EXECUTION_FAILED VARCHAR2(4000) := 'Parallel execution failed';
|
||||
PRAGMA EXCEPTION_INIT( ERR_PARALLEL_EXECUTION_FAILED
|
||||
,CODE_PARALLEL_EXECUTION_FAILED);
|
||||
|
||||
ERR_UNKNOWN EXCEPTION;
|
||||
CODE_UNKNOWN CONSTANT PLS_INTEGER := -20999;
|
||||
MSG_UNKNOWN VARCHAR2(4000) := 'Unknown Error Occured';
|
||||
@@ -609,3 +622,4 @@ AS
|
||||
) RETURN VARCHAR2;
|
||||
|
||||
END ENV_MANAGER;
|
||||
/
|
||||
|
||||
@@ -1,6 +1,54 @@
|
||||
create or replace PACKAGE BODY CT_MRDS.FILE_ARCHIVER
|
||||
AS
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
-- PRIVATE FUNCTION: GET_ARCHIVAL_WHERE_CLAUSE
|
||||
----------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @name GET_ARCHIVAL_WHERE_CLAUSE
|
||||
* @desc Private function that generates WHERE clause based on ARCHIVAL_STRATEGY configuration.
|
||||
* Supports four strategies: THRESHOLD_BASED, CURRENT_MONTH_ONLY, MINIMUM_AGE_MONTHS, HYBRID.
|
||||
* @param pSourceFileConfig - Source file configuration record with ARCHIVAL_STRATEGY
|
||||
* @return VARCHAR2 - WHERE clause for filtering archival candidates
|
||||
**/
|
||||
FUNCTION GET_ARCHIVAL_WHERE_CLAUSE(
|
||||
pSourceFileConfig IN CT_MRDS.A_SOURCE_FILE_CONFIG%ROWTYPE
|
||||
) RETURN VARCHAR2
|
||||
IS
|
||||
vWhereClause VARCHAR2(4000);
|
||||
cgBL CONSTANT VARCHAR2(2) := CHR(13)||CHR(10);
|
||||
BEGIN
|
||||
CASE pSourceFileConfig.ARCHIVAL_STRATEGY
|
||||
-- Legacy threshold-based strategy (backward compatible)
|
||||
WHEN 'THRESHOLD_BASED' THEN
|
||||
vWhereClause := 'extract(day from (systimestamp - workflow_start)) > ' || pSourceFileConfig.DAYS_FOR_ARCHIVE_THRESHOLD;
|
||||
|
||||
-- Archive all data except current month
|
||||
WHEN 'CURRENT_MONTH_ONLY' THEN
|
||||
vWhereClause := 'TRUNC(workflow_start, ''MM'') < TRUNC(SYSDATE, ''MM'')';
|
||||
|
||||
-- Archive only data older than X months
|
||||
WHEN 'MINIMUM_AGE_MONTHS' THEN
|
||||
IF pSourceFileConfig.MINIMUM_AGE_MONTHS IS NULL THEN
|
||||
RAISE_APPLICATION_ERROR(-20001, 'MINIMUM_AGE_MONTHS must be configured for MINIMUM_AGE_MONTHS strategy');
|
||||
END IF;
|
||||
vWhereClause := 'workflow_start < ADD_MONTHS(TRUNC(SYSDATE, ''MM''), -' || pSourceFileConfig.MINIMUM_AGE_MONTHS || ')';
|
||||
|
||||
-- Hybrid: Current month exclusion AND minimum age requirement
|
||||
WHEN 'HYBRID' THEN
|
||||
IF pSourceFileConfig.MINIMUM_AGE_MONTHS IS NULL THEN
|
||||
RAISE_APPLICATION_ERROR(-20001, 'MINIMUM_AGE_MONTHS must be configured for HYBRID strategy');
|
||||
END IF;
|
||||
vWhereClause := 'TRUNC(workflow_start, ''MM'') < TRUNC(SYSDATE, ''MM'') ' ||
|
||||
'AND workflow_start < ADD_MONTHS(TRUNC(SYSDATE, ''MM''), -' || pSourceFileConfig.MINIMUM_AGE_MONTHS || ')';
|
||||
|
||||
ELSE
|
||||
RAISE_APPLICATION_ERROR(-20002, 'Invalid ARCHIVAL_STRATEGY: ' || pSourceFileConfig.ARCHIVAL_STRATEGY);
|
||||
END CASE;
|
||||
|
||||
RETURN vWhereClause;
|
||||
END GET_ARCHIVAL_WHERE_CLAUSE;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION GET_TABLE_STAT(pSourceFileConfigKey IN NUMBER)
|
||||
@@ -85,6 +133,8 @@ AS
|
||||
if LENGTH(vArchivalTriggeredBy)>0 THEN
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Archival Triggered By: '||vArchivalTriggeredBy,'INFO');
|
||||
vTableName := DBMS_ASSERT.SCHEMA_NAME(vSourceFileConfig.ODS_SCHEMA_NAME) || '.'||vSourceFileConfig.A_SOURCE_KEY||'_'||DBMS_ASSERT.simple_sql_name(vSourceFileConfig.TABLE_ID)||'_ODS';
|
||||
|
||||
-- Use strategy-based WHERE clause (MARS-828)
|
||||
vQuery := '
|
||||
select t_filename(
|
||||
file$name
|
||||
@@ -96,7 +146,7 @@ AS
|
||||
from '||vTableName||' s
|
||||
join CT_MRDS.a_workflow_history h
|
||||
on s.a_workflow_history_key = h.a_workflow_history_key
|
||||
where extract(day from (systimestamp - workflow_start)) > '||vSourceFileConfig.DAYS_FOR_ARCHIVE_THRESHOLD
|
||||
where ' || GET_ARCHIVAL_WHERE_CLAUSE(vSourceFileConfig)
|
||||
;
|
||||
|
||||
-- Get all files that will be archived into "vfiles" collection ("regular data files")
|
||||
@@ -337,6 +387,7 @@ AS
|
||||
vSourceFileConfig CT_MRDS.A_SOURCE_FILE_CONFIG%ROWTYPE;
|
||||
vTableName VARCHAR2(200);
|
||||
vQuery VARCHAR2(32000);
|
||||
vWhereClause VARCHAR2(4000);
|
||||
BEGIN
|
||||
vParameters := ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST('pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey), 'NULL')));
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Start','INFO', vParameters);
|
||||
@@ -344,6 +395,12 @@ AS
|
||||
|
||||
vTableName := DBMS_ASSERT.SCHEMA_NAME(vSourceFileConfig.ODS_SCHEMA_NAME) || '.'||vSourceFileConfig.A_SOURCE_KEY||'_'||DBMS_ASSERT.simple_sql_name(vSourceFileConfig.TABLE_ID)||'_ODS';
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('vTableName','DEBUG',vTableName);
|
||||
|
||||
-- Get WHERE clause based on archival strategy (MARS-828)
|
||||
vWhereClause := GET_ARCHIVAL_WHERE_CLAUSE(vSourceFileConfig);
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('vWhereClause','DEBUG',vWhereClause);
|
||||
|
||||
-- Use strategy-based WHERE clause for statistics (MARS-828)
|
||||
vQuery :=
|
||||
'with tmp as (
|
||||
select
|
||||
@@ -367,11 +424,11 @@ AS
|
||||
,'||pSourceFileConfigKey||' as A_SOURCE_FILE_CONFIG_KEY
|
||||
,'''||vTableName||''' as TABLE_NAME
|
||||
,count(*) as FILE_COUNT
|
||||
,sum(case when extract(day from (systimestamp - workflow_start)) > '||vSourceFileConfig.DAYS_FOR_ARCHIVE_THRESHOLD||' then 1 else 0 end) as OLD_FILE_COUNT
|
||||
,sum(case when ' || vWhereClause || ' then 1 else 0 end) as OLD_FILE_COUNT
|
||||
,sum (row_count_per_file) as ROW_COUNT
|
||||
,sum(case when extract(day from (systimestamp - workflow_start)) > '||vSourceFileConfig.DAYS_FOR_ARCHIVE_THRESHOLD||' then row_count_per_file else 0 end) as OLD_ROW_COUNT
|
||||
,sum(case when ' || vWhereClause || ' then row_count_per_file else 0 end) as OLD_ROW_COUNT
|
||||
,sum(r.bytes) as BYTES
|
||||
,sum(case when extract(day from (systimestamp - workflow_start)) > '||vSourceFileConfig.DAYS_FOR_ARCHIVE_THRESHOLD||' then r.bytes else 0 end) as OLD_BYTES
|
||||
,sum(case when ' || vWhereClause || ' then r.bytes else 0 end) as OLD_BYTES
|
||||
,'||vSourceFileConfig.DAYS_FOR_ARCHIVE_THRESHOLD||' as DAYS_FOR_ARCHIVE_THRESHOLD
|
||||
,systimestamp as CREATED
|
||||
from tmp_gr t
|
||||
@@ -438,6 +495,48 @@ AS
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION ARCHIVE_TABLE_DATA (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
) RETURN PLS_INTEGER
|
||||
IS
|
||||
vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE;
|
||||
BEGIN
|
||||
vParameters := ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST('pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey), 'NULL')));
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Start','INFO', vParameters);
|
||||
----
|
||||
ARCHIVE_TABLE_DATA(pSourceFileConfigKey => pSourceFileConfigKey);
|
||||
----
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('End','INFO',vParameters);
|
||||
RETURN SQLCODE;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT(ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RETURN SQLCODE;
|
||||
END ARCHIVE_TABLE_DATA;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
FUNCTION GATHER_TABLE_STAT (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
) RETURN PLS_INTEGER
|
||||
IS
|
||||
vParameters CT_MRDS.A_PROCESS_LOG.PROCEDURE_PARAMETERS%TYPE;
|
||||
BEGIN
|
||||
vParameters := ENV_MANAGER.FORMAT_PARAMETERS(SYS.ODCIVARCHAR2LIST('pSourceFileConfigKey => '||nvl(to_char(pSourceFileConfigKey), 'NULL')));
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('Start','INFO', vParameters);
|
||||
----
|
||||
GATHER_TABLE_STAT(pSourceFileConfigKey => pSourceFileConfigKey);
|
||||
----
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT('End','INFO',vParameters);
|
||||
RETURN SQLCODE;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
ENV_MANAGER.LOG_PROCESS_EVENT(ENV_MANAGER.GET_ERROR_STACK(pFormat => 'TABLE', pCode=> SQLCODE), 'ERROR', vParameters);
|
||||
RETURN SQLCODE;
|
||||
END GATHER_TABLE_STAT;
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
|
||||
END;
|
||||
|
||||
/
|
||||
|
||||
@@ -17,12 +17,14 @@ AS
|
||||
**/
|
||||
|
||||
-- Package Version Information (Semantic Versioning: MAJOR.MINOR.PATCH)
|
||||
PACKAGE_VERSION CONSTANT VARCHAR2(10) := '2.0.0';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2025-10-22 16:45:00';
|
||||
PACKAGE_VERSION CONSTANT VARCHAR2(10) := '3.1.0';
|
||||
PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2026-01-29 21:00:00';
|
||||
PACKAGE_AUTHOR CONSTANT VARCHAR2(100) := 'Grzegorz Michalski';
|
||||
|
||||
-- Version History (Latest changes first)
|
||||
VERSION_HISTORY CONSTANT VARCHAR2(4000) :=
|
||||
'3.1.0 (2026-01-29): Added function overloads for ARCHIVE_TABLE_DATA and GATHER_TABLE_STAT returning SQLCODE for Python library integration' || CHR(13)||CHR(10) ||
|
||||
'3.0.0 (2026-01-27): MARS-828 - Added flexible archival strategies (CURRENT_MONTH_ONLY, MINIMUM_AGE_MONTHS, HYBRID) via ARCHIVAL_STRATEGY configuration' || CHR(13)||CHR(10) ||
|
||||
'2.0.0 (2025-10-22): Added package versioning system using centralized ENV_MANAGER functions' || CHR(13)||CHR(10) ||
|
||||
'1.5.0 (2025-10-18): Enhanced ARCHIVE_TABLE_DATA with Hive-style partitioning support' || CHR(13)||CHR(10) ||
|
||||
'1.0.0 (2025-09-15): Initial release with table archival and statistics gathering';
|
||||
@@ -39,6 +41,18 @@ AS
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
);
|
||||
|
||||
/**
|
||||
* @name ARCHIVE_TABLE_DATA
|
||||
* @desc Function overload for ARCHIVE_TABLE_DATA procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main ARCHIVE_TABLE_DATA procedure and captures execution result.
|
||||
* @example SELECT FILE_ARCHIVER.ARCHIVE_TABLE_DATA(pSourceFileConfigKey => 123) FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION ARCHIVE_TABLE_DATA (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -50,6 +64,18 @@ AS
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
);
|
||||
|
||||
/**
|
||||
* @name GATHER_TABLE_STAT
|
||||
* @desc Function overload for GATHER_TABLE_STAT procedure.
|
||||
* Returns SQLCODE for Python library integration.
|
||||
* Calls the main GATHER_TABLE_STAT procedure and captures execution result.
|
||||
* @example SELECT FILE_ARCHIVER.GATHER_TABLE_STAT(pSourceFileConfigKey => 123) FROM DUAL;
|
||||
* @ex_rslt 0 (success) or error code
|
||||
**/
|
||||
FUNCTION GATHER_TABLE_STAT (
|
||||
pSourceFileConfigKey IN CT_MRDS.A_SOURCE_FILE_CONFIG.A_SOURCE_FILE_CONFIG_KEY%TYPE
|
||||
) RETURN PLS_INTEGER;
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
-- PACKAGE VERSION MANAGEMENT FUNCTIONS
|
||||
---------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
-- ====================================================================
|
||||
-- Purpose: Store source file configuration and processing rules
|
||||
-- MARS-1049: Added ENCODING column for CSV character set support
|
||||
-- MARS-828: Added ARCHIVAL_STRATEGY and MINIMUM_AGE_MONTHS for archival automation
|
||||
-- ====================================================================
|
||||
|
||||
CREATE TABLE CT_MRDS.A_SOURCE_FILE_CONFIG (
|
||||
@@ -21,8 +22,14 @@ CREATE TABLE CT_MRDS.A_SOURCE_FILE_CONFIG (
|
||||
ODS_SCHEMA_NAME VARCHAR2(100),
|
||||
ROWS_COUNT_OVER_ARCHIVE_THRESHOLD NUMBER(38,0),
|
||||
HOURS_TO_EXPIRE_STATISTICS NUMBER(38,3),
|
||||
ARCHIVAL_STRATEGY VARCHAR2(50),
|
||||
MINIMUM_AGE_MONTHS NUMBER(3,0),
|
||||
ENCODING VARCHAR2(50) DEFAULT 'UTF8',
|
||||
ARCHIVE_ENABLED CHAR(1) DEFAULT 'Y' NOT NULL,
|
||||
KEEP_IN_TRASH CHAR(1) DEFAULT 'N' NOT NULL,
|
||||
CONSTRAINT A_SOURCE_FILE_CONFIG_PK PRIMARY KEY (A_SOURCE_FILE_CONFIG_KEY),
|
||||
CONSTRAINT CHK_ARCHIVE_ENABLED CHECK (ARCHIVE_ENABLED IN ('Y', 'N')),
|
||||
CONSTRAINT CHK_KEEP_IN_TRASH CHECK (KEEP_IN_TRASH IN ('Y', 'N')),
|
||||
CONSTRAINT SOURCE_FILE_TYPE_CHK CHECK (SOURCE_FILE_TYPE IN ('INPUT', 'CONTAINER', 'LOAD_CONFIG')),
|
||||
CONSTRAINT ASFC_A_SOURCE_KEY_FK FOREIGN KEY(A_SOURCE_KEY) REFERENCES CT_MRDS.A_SOURCE(A_SOURCE_KEY),
|
||||
CONSTRAINT ASFC_CONTAINER_FILE_KEY_FK FOREIGN KEY(CONTAINER_FILE_KEY) REFERENCES CT_MRDS.A_SOURCE_FILE_CONFIG(A_SOURCE_FILE_CONFIG_KEY),
|
||||
@@ -40,6 +47,10 @@ ON "CT_MRDS"."A_SOURCE_FILE_CONFIG" ("SOURCE_FILE_TYPE", "SOURCE_FILE_ID", "TABL
|
||||
TABLESPACE "DATA";
|
||||
|
||||
-- Column comments
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.ARCHIVAL_STRATEGY IS 'Archival strategy: THRESHOLD_BASED, CURRENT_MONTH_ONLY, MINIMUM_AGE_MONTHS, HYBRID. Added in MARS-828';
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.MINIMUM_AGE_MONTHS IS 'Minimum age in months before archival (required for MINIMUM_AGE_MONTHS strategy). Added in MARS-828';
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.ENCODING IS 'Oracle character set name for CSV files (e.g., UTF8, WE8MSWIN1252, EE8ISO8859P2). Added in MARS-1049';
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.ARCHIVE_ENABLED IS 'Y=Enable archiving, N=Skip archiving. Controls if table participates in archival process. Added in MARS-828 v3.3.0';
|
||||
COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.KEEP_IN_TRASH IS 'Y=Keep files in TRASH after archiving, N=Delete immediately. Controls TRASH retention policy. Added in MARS-828 v3.3.0';
|
||||
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON CT_MRDS.A_SOURCE_FILE_CONFIG TO MRDS_LOADER_ROLE;
|
||||
@@ -19,7 +19,7 @@ CREATE TABLE CT_MRDS.A_SOURCE_FILE_RECEIVED (
|
||||
ARCH_FILE_NAME VARCHAR2(1000),
|
||||
CONSTRAINT A_SOURCE_FILE_RECEIVED_PK PRIMARY KEY (A_SOURCE_FILE_RECEIVED_KEY),
|
||||
CONSTRAINT ASFR_A_SOURCE_FILE_CONFIG_KEY_FK FOREIGN KEY(A_SOURCE_FILE_CONFIG_KEY) REFERENCES CT_MRDS.A_SOURCE_FILE_CONFIG(A_SOURCE_FILE_CONFIG_KEY),
|
||||
CONSTRAINT A_SOURCE_FILE_RECEIVED_CHK CHECK (PROCESSING_STATUS IN ('RECEIVED', 'VALIDATED', 'READY_FOR_INGESTION', 'INGESTED', 'ARCHIVED'))
|
||||
CONSTRAINT A_SOURCE_FILE_RECEIVED_CHK CHECK (PROCESSING_STATUS IN ('RECEIVED', 'VALIDATED', 'READY_FOR_INGESTION', 'INGESTED', 'ARCHIVED', 'ARCHIVED_AND_TRASHED', 'ARCHIVED_AND_PURGED'))
|
||||
) TABLESPACE "DATA";
|
||||
|
||||
-- Unique index for file identification (workaround for TIMESTAMP WITH TIMEZONE constraint limitation)
|
||||
|
||||
@@ -73,6 +73,12 @@ echo 'yes' | sql "ADMIN/Cloudpass#34@ggmichalski_high" "@rollback_mars1057.sql"
|
||||
7z a -pMojeSuperHaslo#123 -mhe=on M1057_arch.7z MARS-1057
|
||||
|
||||
|
||||
cd .\MARS_Packages\REL01_ADDITIONS\MARS-828
|
||||
echo 'yes' | sql "ADMIN/Cloudpass#34@ggmichalski_high" "@install_mars828.sql"
|
||||
echo 'yes' | sql "ADMIN/Cloudpass#34@ggmichalski_high" "@rollback_mars828.sql"
|
||||
7z a -pMojeSuperHaslo#123 -mhe=on M828_arch.7z MARS-828\
|
||||
|
||||
|
||||
cd .\MARS_Packages\REL02_POST\MARS-956
|
||||
echo 'yes' | sql "ADMIN/Cloudpass#34@ggmichalski_high" "@install_mars956.sql"
|
||||
echo 'yes' | sql "ADMIN/Cloudpass#34@ggmichalski_high" "@rollback_mars956.sql"
|
||||
|
||||
682
confluence/FILE_ARCHIVER_Guide.md
Normal file
682
confluence/FILE_ARCHIVER_Guide.md
Normal file
@@ -0,0 +1,682 @@
|
||||
# FILE_ARCHIVER Configuration Guide
|
||||
|
||||
This document describes the archival strategies available in the FILE_ARCHIVER package for managing data lifecycle across OCI buckets (INBOX → ODS → ARCHIVE).
|
||||
|
||||
## Overview
|
||||
|
||||
The FILE_ARCHIVER package provides flexible archival strategies that accommodate different data retention policies across source systems. It manages the movement of processed data from operational storage (ODS bucket) to long-term archival storage (ARCHIVE bucket) based on configurable strategies.
|
||||
|
||||
### Key Features
|
||||
|
||||
- **Three Archival Strategies**: THRESHOLD_BASED, MINIMUM_AGE_MONTHS (with 0=current month only), HYBRID
|
||||
- **Flexible Configuration**: Per-table archival strategy configuration via A_SOURCE_FILE_CONFIG
|
||||
- **Backward Compatible**: Default THRESHOLD_BASED strategy maintains existing behavior
|
||||
- **Validation**: Automatic validation of strategy-specific configuration requirements
|
||||
- **OCI Integration**: Works seamlessly with DBMS_CLOUD operations via cloud_wrapper
|
||||
|
||||
### Package Information
|
||||
|
||||
- **Schema**: CT_MRDS
|
||||
- **Package**: FILE_ARCHIVER
|
||||
- **Current Version**: 3.2.0
|
||||
- **Dependencies**: ENV_MANAGER, FILE_MANAGER, cloud_wrapper, A_SOURCE_FILE_CONFIG, A_SOURCE_FILE_RECEIVED, A_WORKFLOW_HISTORY
|
||||
|
||||
### Critical Prerequisites
|
||||
|
||||
⚠️ **IMPORTANT**: FILE_ARCHIVER requires data to be registered in `CT_MRDS.A_SOURCE_FILE_RECEIVED` table. This table is automatically populated when files are processed through the modern Airflow + DBT workflow via `FILE_MANAGER.PROCESS_SOURCE_FILE`.
|
||||
|
||||
**For legacy data migrated from Informatica + WLA system:**
|
||||
- Legacy data exported using `DATA_EXPORTER` does NOT automatically create `A_SOURCE_FILE_RECEIVED` records
|
||||
- Without these records, FILE_ARCHIVER **CANNOT** archive the data
|
||||
- See [System Migration Guide](System_Migration_Informatica_to_Airflow_DBT.md) for workaround strategies
|
||||
|
||||
**Recommendation for legacy data**: Export directly to ARCHIVE bucket using `DATA_EXPORTER.EXPORT_TABLE_DATA_BY_DATE` with `pBucketArea => 'ARCHIVE'` to bypass this requirement
|
||||
|
||||
## Archival Strategies
|
||||
|
||||
### Strategy Overview
|
||||
|
||||
| Strategy | WHERE Clause Logic | Configuration Required | Primary Use Case |
|
||||
|----------|-------------------|----------------------|------------------|
|
||||
| `THRESHOLD_BASED` | Days since workflow start > threshold | DAYS_FOR_ARCHIVE_THRESHOLD | Legacy compatibility, simple time-based archival |
|
||||
| `MINIMUM_AGE_MONTHS` | Archive data older than X months (0=current month only) | MINIMUM_AGE_MONTHS (≥0) | All sources - flexible retention (0 for LM, 6 for CSDB) |
|
||||
| `HYBRID` | Combines month boundary + minimum age | MINIMUM_AGE_MONTHS | Advanced retention scenarios |
|
||||
|
||||
### 1. THRESHOLD_BASED (Default)
|
||||
|
||||
Archives data based on number of days since workflow start.
|
||||
|
||||
**WHERE Clause**:
|
||||
```sql
|
||||
extract(day from (systimestamp - workflow_start)) > DAYS_FOR_ARCHIVE_THRESHOLD
|
||||
```
|
||||
|
||||
**Configuration**:
|
||||
```sql
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'THRESHOLD_BASED',
|
||||
DAYS_FOR_ARCHIVE_THRESHOLD = 30,
|
||||
MINIMUM_AGE_MONTHS = NULL
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND SOURCE_FILE_ID = 'C2D_DATA'
|
||||
AND TABLE_ID = 'C2D_TABLE';
|
||||
```
|
||||
|
||||
**Use Case**: Simple time-based archival, backward compatible with FILE_ARCHIVER v2.0.0 behavior.
|
||||
|
||||
### 2. MINIMUM_AGE_MONTHS
|
||||
|
||||
Archives data older than specified number of months. **Special case**: MINIMUM_AGE_MONTHS = 0 archives all data before current month (replaces deprecated CURRENT_MONTH_ONLY strategy).
|
||||
|
||||
**WHERE Clause**:
|
||||
```sql
|
||||
workflow_start < ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -MINIMUM_AGE_MONTHS)
|
||||
-- When MINIMUM_AGE_MONTHS = 0: workflow_start < TRUNC(SYSDATE, 'MM')
|
||||
```
|
||||
|
||||
**Configuration Examples**:
|
||||
```sql
|
||||
-- LM: Keep only current month data (MINIMUM_AGE_MONTHS = 0)
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = 0
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND SOURCE_FILE_ID = 'DistributeStandingFacilities'
|
||||
AND TABLE_ID = 'LM_STANDING_FACILITIES';
|
||||
|
||||
-- CSDB: Retain 6 months of data (MINIMUM_AGE_MONTHS = 6)
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = 6
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND SOURCE_FILE_ID = 'CSDB'
|
||||
AND TABLE_ID IN ('CSDB_DEBT', 'CSDB_DEBT_DAILY');
|
||||
```
|
||||
|
||||
**Use Cases**:
|
||||
- **MINIMUM_AGE_MONTHS = 0**: LM dissemination feeds requiring current month only (daily/intraday updates)
|
||||
- **MINIMUM_AGE_MONTHS = 6**: CSDB securities/ratings data requiring 6-month retention
|
||||
- **MINIMUM_AGE_MONTHS = N**: Regulatory compliance with specific N-month retention periods
|
||||
|
||||
**Behavior Examples**:
|
||||
- **With MINIMUM_AGE_MONTHS = 0**:
|
||||
- January data: Archived on February 1st
|
||||
- February data: Remains in ODS bucket during February
|
||||
- March 1st: February data archived, March data active
|
||||
|
||||
- **With MINIMUM_AGE_MONTHS = 6**:
|
||||
- February 2026: Archives data from July 2025 and earlier
|
||||
- March 2026: Archives data from August 2025 and earlier
|
||||
- Keeps current month + 6 previous months (7 months total) in ODS bucket
|
||||
|
||||
### 3. HYBRID
|
||||
|
||||
Combines month boundary check with minimum age threshold - archives data from previous months AND older than minimum age.
|
||||
|
||||
**WHERE Clause**:
|
||||
```sql
|
||||
TRUNC(workflow_start, 'MM') < TRUNC(SYSDATE, 'MM')
|
||||
AND workflow_start < ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -MINIMUM_AGE_MONTHS)
|
||||
```
|
||||
|
||||
**Configuration**:
|
||||
```sql
|
||||
-- Advanced: Current month + 3 months minimum
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'HYBRID',
|
||||
MINIMUM_AGE_MONTHS = 3
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND SOURCE_FILE_ID = 'SPECIAL_SOURCE'
|
||||
AND TABLE_ID = 'SPECIAL_TABLE';
|
||||
```
|
||||
|
||||
**Use Case**: Advanced scenarios requiring both current month retention AND minimum age threshold.
|
||||
|
||||
## Configuration Validation
|
||||
|
||||
### Validation Trigger
|
||||
|
||||
**Trigger**: `TRG_BI_A_SRC_FILE_CFG_ARCH_VAL`
|
||||
|
||||
Automatically validates archival configuration on INSERT/UPDATE to A_SOURCE_FILE_CONFIG:
|
||||
|
||||
**Validation Rules**:
|
||||
1. **MINIMUM_AGE_MONTHS**: Requires `MINIMUM_AGE_MONTHS IS NOT NULL AND MINIMUM_AGE_MONTHS >= 0`
|
||||
- Error: "Strategy MINIMUM_AGE_MONTHS requires MINIMUM_AGE_MONTHS to be set (≥0)"
|
||||
|
||||
2. **HYBRID**: Requires `MINIMUM_AGE_MONTHS IS NOT NULL`
|
||||
- Error: "Strategy HYBRID requires MINIMUM_AGE_MONTHS to be set"
|
||||
|
||||
**Example Validation Error**:
|
||||
```sql
|
||||
-- This will fail validation
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = NULL -- ERROR: Required for this strategy
|
||||
WHERE ...;
|
||||
|
||||
-- Error: ORA-20001: Strategy MINIMUM_AGE_MONTHS requires MINIMUM_AGE_MONTHS to be set
|
||||
```
|
||||
|
||||
## Data Lifecycle Workflow
|
||||
|
||||
### Standard File Processing Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ FILE PROCESSING LIFECYCLE │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
1. INBOX Bucket (Validation)
|
||||
├─ File arrives from source system
|
||||
├─ FILE_MANAGER.PROCESS_SOURCE_FILE validates structure
|
||||
├─ Status: RECEIVED → VALIDATED → READY_FOR_INGESTION
|
||||
└─ FILE_MANAGER.MOVE_FILE relocates to ODS bucket
|
||||
|
||||
2. ODS Bucket (Operational Data)
|
||||
├─ Active data processing (Airflow + DBT)
|
||||
├─ External tables read data from bucket
|
||||
├─ Status: INGESTED
|
||||
├─ FILE_ARCHIVER.ARCHIVE_TABLE_DATA archives based on strategy
|
||||
└─ CSV files moved to TRASH subfolder (ODS → TRASH/)
|
||||
|
||||
2.1 TRASH Subfolder (DATA Bucket - File Retention)
|
||||
├─ Located in DATA bucket (e.g., TRASH/LM/TABLE_NAME)
|
||||
├─ Stores CSV files after archival to Parquet
|
||||
├─ Status: ARCHIVED_AND_TRASHED (default retention)
|
||||
├─ Enables rollback if archival issues occur
|
||||
└─ Optional cleanup: ARCHIVED_AND_PURGED (pKeepInTrash=FALSE)
|
||||
|
||||
3. ARCHIVE Bucket (Long-term Storage)
|
||||
├─ Historical data in Parquet format
|
||||
├─ Hive-style partitioning: PARTITION_YEAR=/PARTITION_MONTH=
|
||||
├─ Status: ARCHIVED_AND_TRASHED or ARCHIVED_AND_PURGED
|
||||
└─ Optimized for big data analytics (Spark, Hive)
|
||||
|
||||
**Key Procedures**:
|
||||
- `ARCHIVE_TABLE_DATA(pSourceFileConfigKey, pKeepInTrash)` - Main archival procedure using strategy-specific WHERE clause
|
||||
- `pKeepInTrash` (BOOLEAN, DEFAULT TRUE) - Controls TRASH folder retention
|
||||
- TRUE: Files kept in TRASH folder for safety and rollback capability (default)
|
||||
- FALSE: Files deleted from TRASH folder after successful archival
|
||||
- `GET_ARCHIVAL_WHERE_CLAUSE` - Returns WHERE clause based on configured strategy
|
||||
- `GATHER_TABLE_STAT` - Calculates archival statistics using strategy logic
|
||||
|
||||
**Archival Execution**:
|
||||
```sql
|
||||
-- Default behavior: Keep files in TRASH folder (ARCHIVED_AND_TRASHED status)
|
||||
BEGIN
|
||||
CT_MRDS.FILE_ARCHIVER.ARCHIVE_TABLE_DATA(
|
||||
pSourceFileConfigKey => vSourceFileConfigKey,
|
||||
pKeepInTrash => TRUE -- DEFAULT value
|
||||
);
|
||||
END;
|
||||
/
|
||||
|
||||
-- Optional: Delete files from TRASH after archival (ARCHIVED_AND_PURGED status)
|
||||
BEGIN
|
||||
CT_MRDS.FILE_ARCHIVER.ARCHIVE_TABLE_DATA(
|
||||
pSourceFileConfigKey => vSourceFileConfigKey,
|
||||
pKeepInTrash => FALSE -- Cleanup TRASH folder
|
||||
);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
**Strategy-Based Filtering**:
|
||||
- Package retrieves ARCHIVAL_STRATEGY from A_SOURCE_FILE_CONFIG
|
||||
- GET_ARCHIVAL_WHERE_CLAUSE generates appropriate WHERE clause
|
||||
- Data matching criteria moved from ODS to ARCHIVE bucket
|
||||
- CSV files moved to TRASH subfolder in DATA bucket (ODS/ → TRASH/)
|
||||
- Parquet format with Hive-style partitioning applied to ARCHIVE bucket
|
||||
- TRASH retention controlled by pKeepInTrash parameter
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
### Example 1: Configure LM Standing Facilities (Current Month Only)
|
||||
|
||||
```sql
|
||||
-- Keep only current month data in ODS bucket (MINIMUM_AGE_MONTHS = 0)
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = 0 -- 0 = archives all data before current month
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND SOURCE_FILE_ID = 'DistributeStandingFacilities'
|
||||
AND TABLE_ID = 'LM_STANDING_FACILITIES';
|
||||
COMMIT;
|
||||
|
||||
-- Verify configuration
|
||||
SELECT
|
||||
SOURCE_FILE_ID,
|
||||
TABLE_ID,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_ID = 'DistributeStandingFacilities';
|
||||
```
|
||||
|
||||
### Example 2: Configure CSDB Debt (MINIMUM_AGE_MONTHS)
|
||||
|
||||
```sql
|
||||
-- Retain 6 months of data in ODS bucket
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = 6
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND SOURCE_FILE_ID = 'CSDB'
|
||||
AND TABLE_ID = 'CSDB_DEBT';
|
||||
COMMIT;
|
||||
|
||||
-- Verify configuration
|
||||
SELECT
|
||||
SOURCE_FILE_ID,
|
||||
TABLE_ID,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE TABLE_ID = 'CSDB_DEBT';
|
||||
```
|
||||
|
||||
### Example 3: Bulk Configuration for LM Source
|
||||
|
||||
```sql
|
||||
-- Configure all 19 LM tables with MINIMUM_AGE_MONTHS = 0 (current month only)
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = 0 -- 0 = keep only current month
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND SOURCE_FILE_ID IN (
|
||||
'DistributeStandingFacilities',
|
||||
'DistributeTTS',
|
||||
'DistributeAdHocAdjustments',
|
||||
'DistributeBalanceSheet',
|
||||
'DistributeCSMAdjustments',
|
||||
'DistributeCurrentAccounts',
|
||||
'DistributeForecast',
|
||||
'DistributeQREAdjustments'
|
||||
);
|
||||
COMMIT;
|
||||
|
||||
-- Verify bulk configuration
|
||||
SELECT
|
||||
SOURCE_FILE_ID,
|
||||
COUNT(*) AS TABLE_COUNT,
|
||||
MAX(ARCHIVAL_STRATEGY) AS STRATEGY,
|
||||
MAX(MINIMUM_AGE_MONTHS) AS MIN_AGE
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_ID LIKE 'Distribute%'
|
||||
GROUP BY SOURCE_FILE_ID
|
||||
ORDER BY SOURCE_FILE_ID;
|
||||
```
|
||||
|
||||
### Example 4: View Current Archival Configuration
|
||||
|
||||
```sql
|
||||
-- All configured tables with their archival strategies
|
||||
SELECT
|
||||
A_SOURCE_KEY,
|
||||
SOURCE_FILE_ID,
|
||||
TABLE_ID,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS,
|
||||
DAYS_FOR_ARCHIVE_THRESHOLD
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
ORDER BY A_SOURCE_KEY, SOURCE_FILE_ID, TABLE_ID;
|
||||
|
||||
-- Summary by strategy
|
||||
SELECT
|
||||
ARCHIVAL_STRATEGY,
|
||||
COUNT(*) AS TABLE_COUNT,
|
||||
MIN(MINIMUM_AGE_MONTHS) AS MIN_AGE_MIN,
|
||||
MAX(MINIMUM_AGE_MONTHS) AS MIN_AGE_MAX
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
GROUP BY ARCHIVAL_STRATEGY
|
||||
ORDER BY ARCHIVAL_STRATEGY;
|
||||
```
|
||||
|
||||
## Release 01 Configuration
|
||||
|
||||
### Configured Tables (MARS-828)
|
||||
|
||||
The following 25 Release 01 tables were configured with archival strategies:
|
||||
|
||||
**LM Tables (19 total) - MINIMUM_AGE_MONTHS = 0 (current month only)**:
|
||||
- LM_STANDING_FACILITIES
|
||||
- LM_STANDING_FACILITIES_HEADER
|
||||
- LM_TTS_HEADER
|
||||
- LM_TTS_ITEM
|
||||
- LM_ADHOC_ADJUSTMENTS_HEADER
|
||||
- LM_ADHOC_ADJUSTMENTS_ITEM
|
||||
- LM_ADHOC_ADJUSTMENTS_ITEM_HEADER
|
||||
- LM_BALANCESHEET_HEADER
|
||||
- LM_BALANCESHEET_ITEM
|
||||
- LM_CSM_ADJUSTMENTS_HEADER
|
||||
- LM_CSM_ADJUSTMENTS_ITEM
|
||||
- LM_CSM_ADJUSTMENTS_ITEM_HEADER
|
||||
- LM_CURRENT_ACCOUNTS_HEADER
|
||||
- LM_CURRENT_ACCOUNTS_ITEM
|
||||
- LM_FORECAST_HEADER
|
||||
- LM_FORECAST_ITEM
|
||||
- LM_QRE_ADJUSTMENTS_HEADER
|
||||
- LM_QRE_ADJUSTMENTS_ITEM
|
||||
- LM_QRE_ADJUSTMENTS_ITEM_HEADER
|
||||
|
||||
**CSDB Tables (6 total)**:
|
||||
|
||||
*MINIMUM_AGE_MONTHS = 6 (6-month retention)*:
|
||||
- CSDB_DEBT
|
||||
- CSDB_DEBT_DAILY
|
||||
|
||||
*MINIMUM_AGE_MONTHS = 0 (current month only)*:
|
||||
- CSDB_INSTR_RAT_FULL
|
||||
- CSDB_INSTR_DESC_FULL
|
||||
- CSDB_ISSUER_RAT_FULL
|
||||
- CSDB_ISSUER_DESC_FULL
|
||||
|
||||
**Verification Query**:
|
||||
```sql
|
||||
-- Check Release 01 configuration
|
||||
SELECT
|
||||
CASE
|
||||
WHEN TABLE_ID LIKE 'LM_%' THEN 'LM'
|
||||
WHEN TABLE_ID LIKE 'CSDB_%' THEN 'CSDB'
|
||||
END AS SOURCE_GROUP,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS,
|
||||
COUNT(*) AS TABLE_COUNT
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_TYPE = 'INPUT'
|
||||
AND TABLE_ID IN (
|
||||
-- 25 Release 01 tables
|
||||
'LM_STANDING_FACILITIES', 'LM_STANDING_FACILITIES_HEADER',
|
||||
'LM_TTS_HEADER', 'LM_TTS_ITEM',
|
||||
-- ... other tables
|
||||
)
|
||||
GROUP BY
|
||||
CASE
|
||||
WHEN TABLE_ID LIKE 'LM_%' THEN 'LM'
|
||||
WHEN TABLE_ID LIKE 'CSDB_%' THEN 'CSDB'
|
||||
END,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS
|
||||
ORDER BY SOURCE_GROUP, ARCHIVAL_STRATEGY;
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Issue 1: Validation Error on Configuration Update
|
||||
|
||||
**Error**:
|
||||
```
|
||||
ORA-20001: Strategy MINIMUM_AGE_MONTHS requires MINIMUM_AGE_MONTHS to be set
|
||||
```
|
||||
|
||||
**Cause**: Trigger validation failed - strategy requires MINIMUM_AGE_MONTHS but value is NULL
|
||||
|
||||
**Solution**:
|
||||
```sql
|
||||
-- Provide required MINIMUM_AGE_MONTHS value
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = 6 -- Required for this strategy
|
||||
WHERE ...;
|
||||
```
|
||||
|
||||
#### Issue 2: Archival Not Working as Expected
|
||||
|
||||
**Symptoms**: Data not being archived according to strategy
|
||||
|
||||
**Diagnostic Steps**:
|
||||
```sql
|
||||
-- 1. Check configuration
|
||||
SELECT
|
||||
SOURCE_FILE_ID,
|
||||
TABLE_ID,
|
||||
ARCHIVAL_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS,
|
||||
DAYS_FOR_ARCHIVE_THRESHOLD
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE TABLE_ID = 'YOUR_TABLE';
|
||||
|
||||
-- 2. Check package version
|
||||
SELECT CT_MRDS.FILE_ARCHIVER.GET_VERSION() FROM DUAL;
|
||||
-- Expected: 3.0.0 or higher
|
||||
|
||||
-- 3. Check process logs
|
||||
SELECT
|
||||
PROCESS_LOG_KEY,
|
||||
PROCESS_NAME,
|
||||
LOG_MESSAGE,
|
||||
LOG_LEVEL,
|
||||
LOG_TIMESTAMP
|
||||
FROM CT_MRDS.A_PROCESS_LOG
|
||||
WHERE PROCESS_NAME LIKE '%ARCHIVE%'
|
||||
ORDER BY LOG_TIMESTAMP DESC
|
||||
FETCH FIRST 20 ROWS ONLY;
|
||||
|
||||
-- 4. Test WHERE clause generation
|
||||
DECLARE
|
||||
vConfig CT_MRDS.A_SOURCE_FILE_CONFIG%ROWTYPE;
|
||||
vWhereClause VARCHAR2(4000);
|
||||
BEGIN
|
||||
SELECT * INTO vConfig
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE TABLE_ID = 'YOUR_TABLE'
|
||||
AND ROWNUM = 1;
|
||||
|
||||
vWhereClause := CT_MRDS.FILE_ARCHIVER.GET_ARCHIVAL_WHERE_CLAUSE(vConfig);
|
||||
DBMS_OUTPUT.PUT_LINE('WHERE Clause: ' || vWhereClause);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
#### Issue 3: Package Compilation Errors After Upgrade
|
||||
|
||||
**Symptoms**: FILE_ARCHIVER package shows INVALID status
|
||||
|
||||
**Solution**:
|
||||
```sql
|
||||
-- Check compilation errors
|
||||
SELECT * FROM USER_ERRORS
|
||||
WHERE NAME = 'FILE_ARCHIVER'
|
||||
AND TYPE IN ('PACKAGE', 'PACKAGE BODY')
|
||||
ORDER BY SEQUENCE;
|
||||
|
||||
-- Recompile package
|
||||
ALTER PACKAGE CT_MRDS.FILE_ARCHIVER COMPILE SPECIFICATION;
|
||||
ALTER PACKAGE CT_MRDS.FILE_ARCHIVER COMPILE BODY;
|
||||
|
||||
-- Verify status
|
||||
SELECT object_name, object_type, status
|
||||
FROM user_objects
|
||||
WHERE object_name = 'FILE_ARCHIVER';
|
||||
```
|
||||
|
||||
## Version History
|
||||
|
||||
### v3.1.0 (Current - 2026-02-05)
|
||||
- **BREAKING CHANGE**: Removed CURRENT_MONTH_ONLY strategy (replaced by MINIMUM_AGE_MONTHS = 0)
|
||||
- Mathematical equivalence: CURRENT_MONTH_ONLY ≡ MINIMUM_AGE_MONTHS = 0
|
||||
- Updated trigger validation to allow MINIMUM_AGE_MONTHS >= 0 (previously >= 1)
|
||||
- Simplified architecture from 4 strategies to 3
|
||||
- Enhanced error handling
|
||||
- All 25 Release 01 tables migrated to MINIMUM_AGE_MONTHS (23 with value 0, 2 with value 6)
|
||||
|
||||
### v3.0.0 (MARS-828 - 2026-02-04)
|
||||
- Added ARCHIVAL_STRATEGY configuration column
|
||||
- Implemented four archival strategies (later reduced to three in v3.1.0):
|
||||
- THRESHOLD_BASED (backward compatible)
|
||||
- CURRENT_MONTH_ONLY (deprecated in v3.1.0, use MINIMUM_AGE_MONTHS = 0)
|
||||
- MINIMUM_AGE_MONTHS
|
||||
- HYBRID
|
||||
- Added GET_ARCHIVAL_WHERE_CLAUSE function
|
||||
- Created validation trigger TRG_BI_A_SRC_FILE_CFG_ARCH_VAL
|
||||
- Configured 25 Release 01 tables with appropriate strategies
|
||||
|
||||
### v2.0.0 (Legacy)
|
||||
- Initial FILE_ARCHIVER package
|
||||
- THRESHOLD_BASED archival only
|
||||
- Fixed DAYS_FOR_ARCHIVE_THRESHOLD configuration
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [FILE_MANAGER Configuration Guide](FILE_MANAGER_Configuration_Guide.md) - File processing and validation
|
||||
- [Package Deployment Guide](Package_Deployment_Guide.md) - Package deployment standards
|
||||
- [Universal Package Tracking System](Universal_Package_Tracking_System.md) - Version tracking
|
||||
- [MARS-828 README](../MARS_Packages/REL01_ADDITIONS/MARS-828/README.md) - Detailed implementation notes
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Required Packages
|
||||
- **CT_MRDS.ENV_MANAGER** v3.x - Error handling, logging, version tracking
|
||||
- **CT_MRDS.FILE_MANAGER** v3.x - Bucket URI resolution, file processing
|
||||
- **MRDS_LOADER.cloud_wrapper** - DBMS_CLOUD operations wrapper
|
||||
|
||||
### Database Objects
|
||||
- **Table**: CT_MRDS.A_SOURCE_FILE_CONFIG - Configuration storage
|
||||
- **Table**: CT_MRDS.A_SOURCE_FILE_RECEIVED - File processing tracking
|
||||
- **Table**: CT_MRDS.A_WORKFLOW_HISTORY - Workflow execution tracking (Airflow + DBT)
|
||||
- **Trigger**: TRG_BI_A_SRC_FILE_CFG_ARCH_VAL - Configuration validation
|
||||
- **Credential**: DEF_CRED_ARN - OCI bucket access
|
||||
|
||||
### OCI Buckets
|
||||
- **INBOX**: Incoming file validation (`'INBOX/{SOURCE}/{SOURCE_FILE_ID}/{TABLE_NAME}/'`)
|
||||
- **ODS/DATA**: Operational data processing (`'ODS/{SOURCE}/{TABLE_NAME}/'`)
|
||||
- **TRASH**: File retention subfolder in DATA bucket (`'TRASH/{SOURCE}/{TABLE_NAME}/'`) - CSV files after archival
|
||||
- **ARCHIVE**: Historical data storage (`'ARCHIVE/{SOURCE}/{TABLE_NAME}/PARTITION_YEAR=/PARTITION_MONTH=/'`)
|
||||
|
||||
**Note**: TRASH is NOT a separate bucket - it's a subfolder within the DATA bucket for file retention and rollback capability.
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Strategy Selection Guidelines
|
||||
|
||||
1. **Use MINIMUM_AGE_MONTHS when**:
|
||||
- **MINIMUM_AGE_MONTHS = 0**: Current month only retention
|
||||
- Data updated frequently (daily/intraday)
|
||||
- Historical data access is rare
|
||||
- ODS bucket space is limited
|
||||
- Example: LM dissemination feeds
|
||||
- **MINIMUM_AGE_MONTHS = N (N > 0)**: Multi-month retention
|
||||
- Regulatory compliance requires specific retention period
|
||||
- Analytical workloads need N-month access
|
||||
- Data updates are infrequent
|
||||
- Example: CSDB securities data (MINIMUM_AGE_MONTHS = 6)
|
||||
|
||||
2. **Use THRESHOLD_BASED when**:
|
||||
- Maintaining backward compatibility with legacy behavior
|
||||
- Simple time-based archival is sufficient
|
||||
- Migration from FILE_ARCHIVER v2.0.0
|
||||
|
||||
3. **Use HYBRID when**:
|
||||
- Complex retention requirements
|
||||
- Combining month boundary check with minimum age threshold
|
||||
- Advanced scenarios not covered by other strategies
|
||||
|
||||
### Configuration Best Practices
|
||||
|
||||
1. **Test Configuration Changes**:
|
||||
```sql
|
||||
-- Test on single table first
|
||||
UPDATE CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
SET ARCHIVAL_STRATEGY = 'MINIMUM_AGE_MONTHS',
|
||||
MINIMUM_AGE_MONTHS = 0 -- 0 = current month only
|
||||
WHERE SOURCE_FILE_ID = 'TEST_FILE'
|
||||
AND TABLE_ID = 'TEST_TABLE';
|
||||
|
||||
-- Monitor archival behavior
|
||||
-- Expand to other tables after validation
|
||||
```
|
||||
|
||||
2. **Verify Before Bulk Updates**:
|
||||
```sql
|
||||
-- Preview changes with SELECT
|
||||
SELECT
|
||||
SOURCE_FILE_ID,
|
||||
TABLE_ID,
|
||||
'MINIMUM_AGE_MONTHS' AS NEW_STRATEGY,
|
||||
0 AS NEW_MIN_AGE, -- 0 = current month only
|
||||
ARCHIVAL_STRATEGY AS OLD_STRATEGY,
|
||||
MINIMUM_AGE_MONTHS AS OLD_MIN_AGE
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_ID LIKE 'Distribute%';
|
||||
|
||||
-- Then execute UPDATE
|
||||
```
|
||||
|
||||
3. **Document Configuration Decisions**:
|
||||
- Record why specific strategy was chosen
|
||||
- Note business requirements driving retention policy
|
||||
- Track configuration changes in version control
|
||||
|
||||
4. **Monitor Archival Performance**:
|
||||
```sql
|
||||
-- Check archival execution logs
|
||||
SELECT
|
||||
PROCESS_NAME,
|
||||
LOG_MESSAGE,
|
||||
LOG_TIMESTAMP
|
||||
FROM CT_MRDS.A_PROCESS_LOG
|
||||
WHERE PROCESS_NAME LIKE '%ARCHIVE%'
|
||||
AND LOG_TIMESTAMP > SYSDATE - 7
|
||||
ORDER BY LOG_TIMESTAMP DESC;
|
||||
```
|
||||
|
||||
5. **Regular Configuration Reviews**:
|
||||
- Verify strategies still match business requirements
|
||||
- Check for tables without archival configuration
|
||||
- Optimize MINIMUM_AGE_MONTHS based on actual usage patterns
|
||||
|
||||
### TRASH Folder Retention Best Practices
|
||||
|
||||
1. **Default Behavior (pKeepInTrash = TRUE - Recommended)**:
|
||||
- Keeps CSV files in TRASH folder after archival
|
||||
- Provides safety net for rollback if archival issues occur
|
||||
- Supports compliance and audit requirements
|
||||
- Status: ARCHIVED_AND_TRASHED
|
||||
- Use for: Production environments, regulatory compliance, critical data
|
||||
|
||||
2. **TRASH Cleanup (pKeepInTrash = FALSE)**:
|
||||
- Deletes CSV files from TRASH folder after successful archival
|
||||
- Reduces storage costs in DATA bucket
|
||||
- Status: ARCHIVED_AND_PURGED
|
||||
- Use for: Non-critical data, storage optimization, test environments
|
||||
|
||||
3. **Monitoring TRASH Folder**:
|
||||
```sql
|
||||
-- Check files in TRASH retention
|
||||
SELECT
|
||||
SOURCE_FILE_NAME,
|
||||
PROCESSING_STATUS,
|
||||
ARCH_FILE_NAME,
|
||||
PARTITION_YEAR,
|
||||
PARTITION_MONTH
|
||||
FROM CT_MRDS.A_SOURCE_FILE_RECEIVED
|
||||
WHERE PROCESSING_STATUS IN ('ARCHIVED_AND_TRASHED', 'ARCHIVED_AND_PURGED')
|
||||
AND RECEPTION_DATE > SYSDATE - 30
|
||||
ORDER BY PROCESSING_STATUS, RECEPTION_DATE DESC;
|
||||
```
|
||||
|
||||
4. **TRASH Folder Structure**:
|
||||
```
|
||||
DATA Bucket:
|
||||
├── ODS/LM/STANDING_FACILITIES/file.csv -- Active operational data
|
||||
└── TRASH/LM/STANDING_FACILITIES/file.csv -- Retained after archival
|
||||
|
||||
ARCHIVE Bucket:
|
||||
└── ARCHIVE/LM/STANDING_FACILITIES/
|
||||
└── PARTITION_YEAR=2026/
|
||||
└── PARTITION_MONTH=02/
|
||||
└── *.parquet -- Archived data
|
||||
```
|
||||
|
||||
## Author
|
||||
|
||||
Created by: Grzegorz Michalski
|
||||
Date: 2026-02-06
|
||||
Schema: CT_MRDS
|
||||
Package: FILE_ARCHIVER
|
||||
Version: 3.2.0
|
||||
@@ -371,11 +371,14 @@ INBOX Bucket - Pattern: 'INBOX/{SOURCE}/{SOURCE_FILE_ID}/{TABLE_NAME}/'
|
||||
└── {pTableId}/ -- e.g., "A_UC_DISSEM_METADATA_LOADS", "STANDING_FACILITIES"
|
||||
└── files matching {pSourceFileNamePattern}
|
||||
|
||||
ODS Bucket - Pattern: 'ODS/{SOURCE}/{TABLE_NAME}/'
|
||||
└── ODS/
|
||||
DATA Bucket - Patterns: 'ODS/{SOURCE}/{TABLE_NAME}/' and 'TRASH/{SOURCE}/{TABLE_NAME}/'
|
||||
├── ODS/
|
||||
│ └── {pSourceKey}/ -- e.g., "C2D", "LM"
|
||||
│ └── {pTableId}/ -- e.g., "A_UC_DISSEM_METADATA_LOADS", "STANDING_FACILITIES"
|
||||
│ └── processed files
|
||||
└── TRASH/ -- File retention subfolder (not a separate bucket)
|
||||
└── {pSourceKey}/ -- e.g., "C2D", "LM"
|
||||
└── {pTableId}/ -- e.g., "A_UC_DISSEM_METADATA_LOADS", "STANDING_FACILITIES"
|
||||
└── processed files
|
||||
└── {pTableId}/ -- CSV files after archival (ARCHIVED_AND_TRASHED status)
|
||||
|
||||
ARCHIVE Bucket - Pattern: 'ARCHIVE/{SOURCE}/{TABLE_NAME}/'
|
||||
└── ARCHIVE/
|
||||
@@ -389,9 +392,11 @@ ARCHIVE Bucket - Pattern: 'ARCHIVE/{SOURCE}/{TABLE_NAME}/'
|
||||
**Critical Path Pattern Requirements:**
|
||||
- **INBOX** requires full 3-level path: `INBOX/{SOURCE}/{SOURCE_FILE_ID}/{TABLE_NAME}/`
|
||||
- **ODS** uses simplified 2-level path: `ODS/{SOURCE}/{TABLE_NAME}/` (no SOURCE_FILE_ID)
|
||||
- **TRASH** uses simplified 2-level path: `TRASH/{SOURCE}/{TABLE_NAME}/` (subfolder in DATA bucket)
|
||||
- **ARCHIVE** uses simplified 2-level path: `ARCHIVE/{SOURCE}/{TABLE_NAME}/` (no SOURCE_FILE_ID)
|
||||
- **All patterns are mandatory** - no simplified versions allowed
|
||||
- File names must match `pSourceFileNamePattern` for automatic processing
|
||||
- **Note**: TRASH is NOT a separate bucket - it's a subfolder within the DATA bucket
|
||||
|
||||
## Configuration Management Best Practices
|
||||
|
||||
@@ -693,7 +698,10 @@ SELECT FILE_MANAGER.PROCESS_SOURCE_FILE(
|
||||
|
||||
1. **File Arrival**: File is uploaded to Oracle Cloud Storage bucket
|
||||
2. **Registration**: FILE_MANAGER.REGISTER_SOURCE_FILE_RECEIVED() creates record
|
||||
3. **Status**: RECEIVED → VALIDATED → READY_FOR_INGESTION → INGESTED → ARCHIVED
|
||||
3. **Status**: RECEIVED → VALIDATED → READY_FOR_INGESTION → INGESTED → ARCHIVED_AND_TRASHED → ARCHIVED_AND_PURGED (optional)
|
||||
- Legacy ARCHIVED status maintained for backward compatibility
|
||||
- ARCHIVED_AND_TRASHED: Files archived to Parquet and kept in TRASH folder (default)
|
||||
- ARCHIVED_AND_PURGED: Files archived to Parquet and deleted from TRASH folder
|
||||
4. **External Table**: Created automatically based on template table
|
||||
5. **Data Loading**: Data is loaded into target ODS schema
|
||||
6. **Archival**: File is moved to archive bucket after processing
|
||||
|
||||
@@ -15,6 +15,11 @@ This document provides comprehensive documentation for the `FILE_MANAGER.PROCESS
|
||||
- **Error Resilient**: Comprehensive error handling and logging for validation and file operations
|
||||
- **Status Tracking**: Updates file processing status throughout validation and preparation workflow
|
||||
|
||||
**Migration Context:**
|
||||
- This procedure is part of the **modern Airflow + DBT system** architecture
|
||||
- Creates records in `CT_MRDS.A_SOURCE_FILE_RECEIVED` (modern control table)
|
||||
- For legacy Informatica + WLA data migration, see [System Migration Guide](System_Migration_Informatica_to_Airflow_DBT.md)
|
||||
|
||||
## Procedure Signatures
|
||||
|
||||
The procedure is available in two variants:
|
||||
@@ -159,7 +164,9 @@ ORDER BY RECEPTION_DATE DESC;
|
||||
| `VALIDATED` | File validation completed successfully | After successful validation |
|
||||
| `READY_FOR_INGESTION` | File validated and prepared for Airflow+DBT processing | After successful validation and preparation |
|
||||
| `INGESTED` | Data has been consumed/ingested by target system | After data consumption |
|
||||
| `ARCHIVED` | Data exported to PARQUET format and file moved to archival storage | Final archival state using FILE_ARCHIVER |
|
||||
| `ARCHIVED` | (Legacy) Data exported to PARQUET format and file moved to archival storage | Legacy archival state (backward compatibility) |
|
||||
| `ARCHIVED_AND_TRASHED` | Data archived to Parquet, CSV files kept in TRASH folder (default) | Archival with file retention using FILE_ARCHIVER |
|
||||
| `ARCHIVED_AND_PURGED` | Data archived to Parquet, CSV files deleted from TRASH folder | Archival with TRASH cleanup (pKeepInTrash=FALSE) |
|
||||
| `VALIDATION_FAILED` | File validation failed | After failed validation |
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,122 @@ This guide provides step-by-step instructions for developers on how to properly
|
||||
|
||||
---
|
||||
|
||||
## MANDATORY STANDARDS (NEVER SKIP!)
|
||||
|
||||
### 🔴 Critical: Author Field
|
||||
|
||||
**ALL scripts MUST have:**
|
||||
```sql
|
||||
-- Author: Grzegorz Michalski
|
||||
```
|
||||
|
||||
**❌ WRONG:**
|
||||
```sql
|
||||
-- Author: System
|
||||
-- Author: Developer
|
||||
-- Author: [your name here]
|
||||
```
|
||||
|
||||
**✅ CORRECT:**
|
||||
```sql
|
||||
-- Author: Grzegorz Michalski
|
||||
```
|
||||
|
||||
### 📅 Date Format Standard
|
||||
|
||||
**ISO 8601 format only:**
|
||||
```sql
|
||||
-- Date: 2026-02-03 (YYYY-MM-DD)
|
||||
```
|
||||
|
||||
### 📝 Script Header Template
|
||||
|
||||
**Copy-paste this template for ALL scripts:**
|
||||
```sql
|
||||
-- =====================================================================
|
||||
-- Script: XX_MARS_XXX_description.sql
|
||||
-- MARS Issue: MARS-XXX
|
||||
-- Purpose: Brief description of what this script does
|
||||
-- Author: Grzegorz Michalski
|
||||
-- Date: YYYY-MM-DD
|
||||
-- =====================================================================
|
||||
```
|
||||
|
||||
### 🔐 Database User Requirements
|
||||
|
||||
**Execute installations as ADMIN:**
|
||||
```powershell
|
||||
# ✅ CORRECT
|
||||
Get-Content "install_marsXXX.sql" | sql "ADMIN/password@service"
|
||||
|
||||
# ❌ WRONG
|
||||
Get-Content "install_marsXXX.sql" | sql "CT_MRDS/password@service"
|
||||
```
|
||||
|
||||
### 🔍 Data Dictionary Views
|
||||
|
||||
**Use ALL_* views when installing as ADMIN:**
|
||||
```sql
|
||||
-- ✅ CORRECT (ADMIN user)
|
||||
SELECT * FROM ALL_ERRORS WHERE OWNER = 'CT_MRDS' AND NAME = 'PACKAGE_NAME';
|
||||
|
||||
-- ❌ WRONG (shows ADMIN schema, not CT_MRDS)
|
||||
SELECT * FROM USER_ERRORS WHERE NAME = 'PACKAGE_NAME';
|
||||
```
|
||||
|
||||
### 📂 Log Directory Management
|
||||
|
||||
**MANDATORY in all master scripts:**
|
||||
```sql
|
||||
-- Create log/ directory before SPOOL (prevents failures)
|
||||
host mkdir log 2>nul
|
||||
|
||||
-- Then configure dynamic SPOOL filename
|
||||
var filename VARCHAR2(100)
|
||||
BEGIN
|
||||
:filename := 'log/INSTALL_MARS_XXX_' || SYS_CONTEXT('USERENV', 'CON_NAME') || '_' || TO_CHAR(SYSDATE,'YYYYMMDD_HH24MISS') || '.log';
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
### ✋ User Confirmation
|
||||
|
||||
**MANDATORY ACCEPT validation in master scripts:**
|
||||
```sql
|
||||
ACCEPT continue CHAR PROMPT 'Type YES to continue with installation, or Ctrl+C to abort: '
|
||||
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
||||
BEGIN
|
||||
IF '&continue' IS NULL OR TRIM('&continue') IS NULL OR UPPER(TRIM('&continue')) != 'YES' THEN
|
||||
RAISE_APPLICATION_ERROR(-20001, 'Installation aborted by user');
|
||||
END IF;
|
||||
END;
|
||||
/
|
||||
WHENEVER SQLERROR CONTINUE
|
||||
```
|
||||
|
||||
### 🚪 Clean Exit
|
||||
|
||||
**End all master scripts with:**
|
||||
```sql
|
||||
spool off
|
||||
quit; -- ← MANDATORY for clean SQLcl/SQL*Plus exit
|
||||
```
|
||||
|
||||
### 📋 Quick Compliance Checklist
|
||||
|
||||
Before committing any script, verify:
|
||||
- [ ] `Author: Grzegorz Michalski` in header
|
||||
- [ ] Date in ISO 8601 format (YYYY-MM-DD)
|
||||
- [ ] Master scripts use `host mkdir log 2>nul`
|
||||
- [ ] Master scripts require ACCEPT validation
|
||||
- [ ] Master scripts end with `quit;`
|
||||
- [ ] Verification queries use ALL_* views with OWNER filter
|
||||
- [ ] Installation instructions specify ADMIN user
|
||||
|
||||
**💡 Remember:** These standards prevent common mistakes and ensure consistency across all MARS packages!
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Before You Start](#before-you-start)
|
||||
@@ -1225,7 +1341,12 @@ SET PAUSE OFF
|
||||
PROMPT =========================================================================
|
||||
PROMPT MARS-XXXX: Rollback Package
|
||||
PROMPT =========================================================================
|
||||
PROMPT WARNING: This will reverse all changes from MARS-XXXX installation!
|
||||
PROMPT This will reverse all changes from MARS-XXXX installation
|
||||
PROMPT
|
||||
PROMPT Rollback steps:
|
||||
PROMPT 1. Restore previous package version
|
||||
PROMPT 2. Remove added columns/tables
|
||||
PROMPT 3. Revert configuration changes
|
||||
PROMPT =========================================================================
|
||||
|
||||
-- Confirm rollback with user
|
||||
@@ -1259,6 +1380,32 @@ spool off
|
||||
- Revert configuration changes
|
||||
- Include verification step after rollback (@@verify_packages_version.sql)
|
||||
|
||||
**Rollback Communication Style:**
|
||||
- ✅ **DO**: Use calm, professional tone describing what will be done
|
||||
- ✅ **DO**: List specific rollback steps clearly
|
||||
- ❌ **DON'T**: Use dramatic words like "WARNING", "CRITICAL IMPACT", "DANGER"
|
||||
- ❌ **DON'T**: Create panic - rollback is a normal part of deployment process
|
||||
- **Rationale**: Rollbacks happen when installations fail or need to be reversed. This is a standard procedure, not an emergency.
|
||||
|
||||
**Example - Professional vs. Dramatic:**
|
||||
|
||||
```sql
|
||||
-- ✅ CORRECT - Professional and Clear
|
||||
PROMPT This will reverse all changes from MARS-828 installation
|
||||
PROMPT
|
||||
PROMPT Rollback steps:
|
||||
PROMPT 1. Remove validation trigger
|
||||
PROMPT 2. Drop ARCHIVAL_STRATEGY and MINIMUM_AGE_MONTHS columns
|
||||
PROMPT 3. Restore FILE_ARCHIVER package to v2.0.0
|
||||
|
||||
-- ❌ WRONG - Unnecessarily Dramatic
|
||||
PROMPT WARNING: This will restore FILE_ARCHIVER to v2.0.0
|
||||
PROMPT
|
||||
PROMPT CRITICAL IMPACT:
|
||||
PROMPT 1. All archival strategies revert to THRESHOLD_BASED
|
||||
PROMPT 2. ARCHIVAL_STRATEGY and MINIMUM_AGE_MONTHS columns will be dropped
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Version Tracking Integration
|
||||
|
||||
448
confluence/System_Migration_Informatica_to_Airflow_DBT.md
Normal file
448
confluence/System_Migration_Informatica_to_Airflow_DBT.md
Normal file
@@ -0,0 +1,448 @@
|
||||
# System Migration: Informatica + WLA → Airflow + DBT
|
||||
|
||||
This document describes the migration from the legacy Informatica + WLA data processing system to the modern Airflow + DBT architecture, including control table differences, data export strategies, and known limitations.
|
||||
|
||||
## Migration Overview
|
||||
|
||||
The MRDS (Market Reference Data System) is undergoing a fundamental technology migration:
|
||||
|
||||
**Legacy System (Informatica + WLA):**
|
||||
- ETL Tool: Informatica PowerCenter
|
||||
- Workflow Orchestration: WLA (Workflow Automation)
|
||||
- Control Schema: `CT_ODS` (Operational Data Store Control)
|
||||
- Primary Control Table: `CT_ODS.A_LOAD_HISTORY`
|
||||
- Key Column: `A_ETL_LOAD_SET_KEY`
|
||||
|
||||
**Modern System (Airflow + DBT):**
|
||||
- Orchestration: Apache Airflow
|
||||
- Transformation: DBT (Data Build Tool)
|
||||
- Control Schema: `CT_MRDS` (MRDS Control)
|
||||
- Primary Control Tables: `CT_MRDS.A_SOURCE_FILE_RECEIVED`, `CT_MRDS.A_WORKFLOW_HISTORY`
|
||||
- Key Column: `A_WORKFLOW_HISTORY_KEY`
|
||||
|
||||
## Control Table Architecture
|
||||
|
||||
### Legacy System: CT_ODS.A_LOAD_HISTORY
|
||||
|
||||
**Purpose**: Tracks Informatica PowerCenter workflow executions
|
||||
|
||||
**Structure**:
|
||||
```sql
|
||||
DESC CT_ODS.A_LOAD_HISTORY;
|
||||
|
||||
Name Type
|
||||
______________________ _____________________
|
||||
A_ETL_LOAD_SET_KEY NUMBER(38) -- Primary key
|
||||
WORKFLOW_NAME VARCHAR2(255) -- Informatica workflow name
|
||||
INFA_RUN_ID NUMBER(38) -- Informatica run ID
|
||||
LOAD_START TIMESTAMP(6) -- Workflow start time
|
||||
LOAD_END TIMESTAMP(6) -- Workflow end time
|
||||
EXDI_APPL_REQ_ID VARCHAR2(255)
|
||||
EXDI_CORRELATION_ID VARCHAR2(255)
|
||||
LOAD_SUCCESSFUL CHAR(1) -- Y/N success flag
|
||||
WLA_RUN_ID NUMBER(28) -- WLA run ID
|
||||
DQ_FLAG VARCHAR2(5) -- Data quality flag
|
||||
```
|
||||
|
||||
**Usage Pattern**:
|
||||
- Created by Informatica workflows during ETL execution
|
||||
- Used for temporal partitioning in DATA_EXPORTER
|
||||
- Referenced via `A_ETL_LOAD_SET_KEY_FK` foreign key in data tables
|
||||
|
||||
### Modern System: CT_MRDS Control Tables
|
||||
|
||||
#### 1. A_SOURCE_FILE_RECEIVED
|
||||
|
||||
**Purpose**: Tracks individual file processing through the complete lifecycle
|
||||
|
||||
**Key Columns**:
|
||||
```sql
|
||||
A_SOURCE_FILE_RECEIVED_KEY NUMBER -- Primary key
|
||||
SOURCE_FILE_NAME VARCHAR2 -- Full OCI path
|
||||
PROCESSING_STATUS VARCHAR2 -- Status tracking
|
||||
RECEPTION_DATE DATE -- File arrival timestamp
|
||||
PARTITION_YEAR VARCHAR2(4) -- Archive partition (year)
|
||||
PARTITION_MONTH VARCHAR2(2) -- Archive partition (month)
|
||||
ARCH_FILE_NAME VARCHAR2 -- Parquet archive file path
|
||||
```
|
||||
|
||||
**Status Workflow**:
|
||||
```
|
||||
RECEIVED → VALIDATED → READY_FOR_INGESTION → INGESTED → ARCHIVED_AND_TRASHED → ARCHIVED_AND_PURGED (optional)
|
||||
|
||||
Note: Legacy ARCHIVED status maintained for backward compatibility
|
||||
```
|
||||
|
||||
**Usage Pattern**:
|
||||
- Created by FILE_MANAGER.PROCESS_SOURCE_FILE during file validation
|
||||
- Updated throughout file lifecycle (validation, ingestion, archival)
|
||||
- Required by FILE_ARCHIVER for archival operations
|
||||
- Links to A_WORKFLOW_HISTORY via workflow execution
|
||||
|
||||
#### 2. A_WORKFLOW_HISTORY
|
||||
|
||||
**Purpose**: Tracks Airflow + DBT workflow executions (similar role to A_LOAD_HISTORY)
|
||||
|
||||
**Key Columns**:
|
||||
```sql
|
||||
A_WORKFLOW_HISTORY_KEY NUMBER -- Primary key
|
||||
WORKFLOW_NAME VARCHAR2 -- Airflow DAG name
|
||||
WORKFLOW_START TIMESTAMP -- Workflow start time
|
||||
WORKFLOW_END TIMESTAMP -- Workflow end time
|
||||
WORKFLOW_SUCCESSFUL CHAR(1) -- Y/N success flag
|
||||
```
|
||||
|
||||
**Usage Pattern**:
|
||||
- Created by Airflow + DBT workflows during data processing
|
||||
- Used for temporal partitioning decisions in FILE_ARCHIVER
|
||||
- Referenced via `A_WORKFLOW_HISTORY_KEY_FK` foreign key in data tables
|
||||
|
||||
## Data Export Strategies
|
||||
|
||||
### Scenario 1: Legacy Data Export (Informatica → ODS)
|
||||
|
||||
**Use Case**: One-time migration of historical data loaded by Informatica
|
||||
|
||||
**Package**: `DATA_EXPORTER.EXPORT_TABLE_DATA_TO_CSV_BY_DATE`
|
||||
|
||||
**Control Table**: Uses `CT_ODS.A_LOAD_HISTORY` for temporal partitioning
|
||||
|
||||
**Example**:
|
||||
```sql
|
||||
-- Export historical AGGREGATED_ALLOTMENT data (loaded by Informatica)
|
||||
BEGIN
|
||||
CT_MRDS.DATA_EXPORTER.EXPORT_TABLE_DATA_TO_CSV_BY_DATE(
|
||||
pSchemaName => 'OU_TOP',
|
||||
pTableName => 'AGGREGATED_ALLOTMENT',
|
||||
pKeyColumnName => 'A_ETL_LOAD_SET_KEY_FK', -- Links to A_LOAD_HISTORY
|
||||
pBucketArea => 'DATA',
|
||||
pFolderName => 'legacy_migration',
|
||||
pMinDate => DATE '2020-01-01',
|
||||
pMaxDate => DATE '2024-12-31'
|
||||
);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
**Result**: CSV files in ODS bucket (DATA area), partitioned by LOAD_START from A_LOAD_HISTORY
|
||||
|
||||
### Scenario 2: Modern System Data (Airflow + DBT → ODS → ARCHIVE)
|
||||
|
||||
**Use Case**: Ongoing processing with new Airflow + DBT system
|
||||
|
||||
**Workflow**:
|
||||
1. **File Arrival**: FILES → INBOX bucket
|
||||
2. **Validation**: FILE_MANAGER.PROCESS_SOURCE_FILE → creates A_SOURCE_FILE_RECEIVED
|
||||
3. **Processing**: Airflow + DBT → creates A_WORKFLOW_HISTORY
|
||||
4. **Export**: DATA_EXPORTER → moves to ODS bucket (DATA area)
|
||||
5. **Archival**: FILE_ARCHIVER → moves to ARCHIVE bucket (Parquet with Hive partitioning)
|
||||
|
||||
**Control Tables**: Uses both A_SOURCE_FILE_RECEIVED and A_WORKFLOW_HISTORY
|
||||
|
||||
**Example**:
|
||||
```sql
|
||||
-- Archival of data processed by Airflow + DBT
|
||||
BEGIN
|
||||
CT_MRDS.FILE_ARCHIVER.ARCHIVE_TABLE_DATA(
|
||||
pSourceFileConfig => vConfig -- Requires A_SOURCE_FILE_RECEIVED records
|
||||
);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
## Critical Gap: Legacy Data Archival
|
||||
|
||||
### Problem Statement
|
||||
|
||||
**Scenario**: Historical data exported using DATA_EXPORTER from Informatica-loaded tables
|
||||
|
||||
**Issue**: FILE_ARCHIVER requires records in `A_SOURCE_FILE_RECEIVED`, but legacy exports don't create them
|
||||
|
||||
**Impact**: Legacy data exported to ODS/DATA bucket **CANNOT** be archived to ARCHIVE bucket using FILE_ARCHIVER
|
||||
|
||||
### Technical Analysis
|
||||
|
||||
**DATA_EXPORTER Behavior**:
|
||||
```sql
|
||||
-- Uses A_LOAD_HISTORY for partitioning (Informatica workflows)
|
||||
SELECT DISTINCT TO_CHAR(L.LOAD_START,'YYYY') AS YR,
|
||||
TO_CHAR(L.LOAD_START,'MM') AS MN
|
||||
FROM OU_TOP.AGGREGATED_ALLOTMENT T, CT_ODS.A_LOAD_HISTORY L
|
||||
WHERE T.A_ETL_LOAD_SET_KEY_FK = L.A_ETL_LOAD_SET_KEY
|
||||
AND L.LOAD_START >= :pMinDate
|
||||
AND L.LOAD_START < :pMaxDate;
|
||||
|
||||
-- Creates CSV files: ODS/legacy_migration/AGGREGATED_ALLOTMENT_YYYYMM.csv
|
||||
-- Does NOT create A_SOURCE_FILE_RECEIVED records
|
||||
```
|
||||
|
||||
**FILE_ARCHIVER Requirement**:
|
||||
```sql
|
||||
-- Joins A_SOURCE_FILE_RECEIVED with A_WORKFLOW_HISTORY
|
||||
JOIN CT_MRDS.A_SOURCE_FILE_RECEIVED r
|
||||
ON r.A_SOURCE_FILE_CONFIG_KEY = pSourceFileConfig.A_SOURCE_FILE_CONFIG_KEY
|
||||
AND r.PROCESSING_STATUS = 'INGESTED';
|
||||
|
||||
-- Without A_SOURCE_FILE_RECEIVED records, archival CANNOT proceed
|
||||
```
|
||||
|
||||
### Workaround Strategies
|
||||
|
||||
#### Strategy 1: Manual Registration (Recommended for Small Datasets)
|
||||
|
||||
Manually create `A_SOURCE_FILE_RECEIVED` records for legacy exported files:
|
||||
|
||||
```sql
|
||||
-- Step 1: Export legacy data to ODS/DATA
|
||||
BEGIN
|
||||
DATA_EXPORTER.EXPORT_TABLE_DATA_TO_CSV_BY_DATE(
|
||||
pSchemaName => 'OU_TOP',
|
||||
pTableName => 'AGGREGATED_ALLOTMENT',
|
||||
pKeyColumnName => 'A_ETL_LOAD_SET_KEY_FK',
|
||||
pBucketArea => 'DATA',
|
||||
pFolderName => 'legacy_export',
|
||||
pMinDate => DATE '2024-01-01',
|
||||
pMaxDate => DATE '2024-12-31'
|
||||
);
|
||||
END;
|
||||
/
|
||||
|
||||
-- Step 2: List exported CSV files
|
||||
SELECT object_name, time_created, bytes
|
||||
FROM TABLE(MRDS_LOADER.cloud_wrapper.list_objects(
|
||||
credential_name => 'DEF_CRED_ARN',
|
||||
location_uri => 'https://objectstorage.eu-frankfurt-1.oraclecloud.com/n/frtgjxu7zl7c/b/data/o/'
|
||||
)) WHERE object_name LIKE 'ODS/legacy_export/AGGREGATED_ALLOTMENT_%';
|
||||
|
||||
-- Step 3: Manually register each file in A_SOURCE_FILE_RECEIVED
|
||||
-- (Requires source configuration for AGGREGATED_ALLOTMENT to exist)
|
||||
INSERT INTO CT_MRDS.A_SOURCE_FILE_RECEIVED (
|
||||
A_SOURCE_FILE_RECEIVED_KEY,
|
||||
A_SOURCE_FILE_CONFIG_KEY,
|
||||
SOURCE_FILE_NAME,
|
||||
PROCESSING_STATUS,
|
||||
RECEPTION_DATE,
|
||||
BYTES,
|
||||
CHECKSUM,
|
||||
EXTERNAL_TABLE_NAME
|
||||
) VALUES (
|
||||
A_SOURCE_FILE_RECEIVED_KEY_SEQ.NEXTVAL,
|
||||
(SELECT A_SOURCE_FILE_CONFIG_KEY FROM A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_ID = 'AGGREGATED_ALLOTMENT' AND SOURCE_FILE_TYPE = 'INPUT'),
|
||||
'ODS/legacy_export/AGGREGATED_ALLOTMENT_202401.csv',
|
||||
'INGESTED', -- Skip validation, mark as already ingested
|
||||
DATE '2024-01-15',
|
||||
1048576, -- File size in bytes
|
||||
'manual_registration',
|
||||
NULL -- No external table needed
|
||||
);
|
||||
-- Repeat for all exported CSV files
|
||||
COMMIT;
|
||||
|
||||
-- Step 4: Now FILE_ARCHIVER can process these files
|
||||
BEGIN
|
||||
FILE_ARCHIVER.ARCHIVE_TABLE_DATA(pSourceFileConfig => vConfig);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
#### Strategy 2: Direct Archive Export (Bypass ODS)
|
||||
|
||||
Skip ODS/DATA bucket entirely - export directly to ARCHIVE bucket in Parquet format:
|
||||
|
||||
```sql
|
||||
-- Export legacy data directly to ARCHIVE bucket
|
||||
BEGIN
|
||||
DATA_EXPORTER.EXPORT_TABLE_DATA_BY_DATE(
|
||||
pSchemaName => 'OU_TOP',
|
||||
pTableName => 'AGGREGATED_ALLOTMENT',
|
||||
pKeyColumnName => 'A_ETL_LOAD_SET_KEY_FK',
|
||||
pBucketArea => 'ARCHIVE', -- Direct to archive
|
||||
pFolderName => 'legacy_direct',
|
||||
pMinDate => DATE '2020-01-01',
|
||||
pMaxDate => DATE '2024-12-31'
|
||||
);
|
||||
END;
|
||||
/
|
||||
-- Result: Parquet files with Hive partitioning in ARCHIVE bucket
|
||||
-- Files: ARCHIVE/legacy_direct/PARTITION_YEAR=2024/PARTITION_MONTH=01/*.parquet
|
||||
-- No A_SOURCE_FILE_RECEIVED records needed (archival already complete)
|
||||
```
|
||||
|
||||
**Pros**:
|
||||
- Simple, no manual registration
|
||||
- Data already in final archive format (Parquet)
|
||||
- Hive-style partitioning automatically applied
|
||||
|
||||
**Cons**:
|
||||
- No record in A_SOURCE_FILE_RECEIVED (tracking gap)
|
||||
- Cannot use FILE_ARCHIVER features (archival strategies, status tracking)
|
||||
- Mixed folder structure (legacy_direct vs. standard source/table paths)
|
||||
|
||||
#### Strategy 3: Hybrid Approach (Recommended for Large Datasets)
|
||||
|
||||
Use DATA_EXPORTER for initial export, create minimal A_SOURCE_FILE_RECEIVED records programmatically:
|
||||
|
||||
```sql
|
||||
-- Create helper procedure to register legacy exports
|
||||
CREATE OR REPLACE PROCEDURE REGISTER_LEGACY_EXPORT (
|
||||
pSourceFileId VARCHAR2,
|
||||
pBucketArea VARCHAR2,
|
||||
pFolderName VARCHAR2,
|
||||
pFilePattern VARCHAR2,
|
||||
pReceptionDate DATE DEFAULT SYSDATE
|
||||
) AS
|
||||
vConfigKey NUMBER;
|
||||
vBucketUri VARCHAR2(500);
|
||||
vPrefix VARCHAR2(500);
|
||||
BEGIN
|
||||
-- Get source configuration
|
||||
SELECT A_SOURCE_FILE_CONFIG_KEY
|
||||
INTO vConfigKey
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_ID = pSourceFileId
|
||||
AND SOURCE_FILE_TYPE = 'INPUT';
|
||||
|
||||
-- Get bucket URI
|
||||
vBucketUri := CT_MRDS.ENV_MANAGER.GET_BUCKET_URI(pBucketArea);
|
||||
vPrefix := 'ODS/' || pFolderName || '/';
|
||||
|
||||
-- Register all matching files
|
||||
FOR rec IN (
|
||||
SELECT object_name, bytes, etag
|
||||
FROM TABLE(MRDS_LOADER.cloud_wrapper.list_objects(
|
||||
credential_name => 'DEF_CRED_ARN',
|
||||
location_uri => vBucketUri
|
||||
))
|
||||
WHERE object_name LIKE vPrefix || pFilePattern
|
||||
) LOOP
|
||||
INSERT INTO CT_MRDS.A_SOURCE_FILE_RECEIVED (
|
||||
A_SOURCE_FILE_RECEIVED_KEY,
|
||||
A_SOURCE_FILE_CONFIG_KEY,
|
||||
SOURCE_FILE_NAME,
|
||||
PROCESSING_STATUS,
|
||||
RECEPTION_DATE,
|
||||
BYTES,
|
||||
CHECKSUM
|
||||
) VALUES (
|
||||
A_SOURCE_FILE_RECEIVED_KEY_SEQ.NEXTVAL,
|
||||
vConfigKey,
|
||||
rec.object_name,
|
||||
'INGESTED',
|
||||
pReceptionDate,
|
||||
rec.bytes,
|
||||
rec.etag
|
||||
);
|
||||
END LOOP;
|
||||
|
||||
COMMIT;
|
||||
DBMS_OUTPUT.PUT_LINE('Registered ' || SQL%ROWCOUNT || ' legacy files');
|
||||
END;
|
||||
/
|
||||
|
||||
-- Usage:
|
||||
BEGIN
|
||||
-- After DATA_EXPORTER.EXPORT_TABLE_DATA_TO_CSV_BY_DATE completes
|
||||
REGISTER_LEGACY_EXPORT(
|
||||
pSourceFileId => 'AGGREGATED_ALLOTMENT',
|
||||
pBucketArea => 'DATA',
|
||||
pFolderName => 'legacy_export',
|
||||
pFilePattern => 'AGGREGATED_ALLOTMENT_2024%.csv',
|
||||
pReceptionDate => DATE '2024-12-31'
|
||||
);
|
||||
|
||||
-- Now FILE_ARCHIVER can process
|
||||
FILE_ARCHIVER.ARCHIVE_TABLE_DATA(pSourceFileConfig => vConfig);
|
||||
END;
|
||||
/
|
||||
```
|
||||
|
||||
## Migration Timeline and Coexistence
|
||||
|
||||
### Phase 1: Legacy System Only (Before Migration)
|
||||
- All data loaded via Informatica + WLA
|
||||
- Control table: `CT_ODS.A_LOAD_HISTORY`
|
||||
- No `A_SOURCE_FILE_RECEIVED` records
|
||||
|
||||
### Phase 2: Parallel Operation (During Migration)
|
||||
- **Old data**: Continue using Informatica + WLA → A_LOAD_HISTORY
|
||||
- **New data**: Start using Airflow + DBT → A_SOURCE_FILE_RECEIVED + A_WORKFLOW_HISTORY
|
||||
- **Challenge**: Different control tables for different data vintages
|
||||
|
||||
### Phase 3: New System Only (After Migration)
|
||||
- All new data via Airflow + DBT
|
||||
- Legacy data archived (one-time export using DATA_EXPORTER)
|
||||
- Control tables: `CT_MRDS.A_SOURCE_FILE_RECEIVED`, `CT_MRDS.A_WORKFLOW_HISTORY`
|
||||
|
||||
## Recommendations
|
||||
|
||||
### For New Data (Airflow + DBT)
|
||||
✅ Use standard workflow:
|
||||
1. FILE_MANAGER.PROCESS_SOURCE_FILE (creates A_SOURCE_FILE_RECEIVED)
|
||||
2. Airflow + DBT processing (creates A_WORKFLOW_HISTORY)
|
||||
3. FILE_ARCHIVER.ARCHIVE_TABLE_DATA (uses both control tables)
|
||||
|
||||
### For Legacy Data Migration
|
||||
✅ **Small Datasets (<1000 files)**: Strategy 1 (Manual Registration)
|
||||
✅ **Large Datasets (>1000 files)**: Strategy 2 (Direct to ARCHIVE) or Strategy 3 (Hybrid)
|
||||
❌ **Avoid**: Exporting to ODS/DATA without registration (orphaned files, cannot archive)
|
||||
|
||||
### Configuration Requirements
|
||||
|
||||
Before archiving legacy data, ensure source configuration exists:
|
||||
|
||||
```sql
|
||||
-- Check if configuration exists
|
||||
SELECT A_SOURCE_FILE_CONFIG_KEY, SOURCE_FILE_ID, TABLE_ID, ARCHIVAL_STRATEGY
|
||||
FROM CT_MRDS.A_SOURCE_FILE_CONFIG
|
||||
WHERE SOURCE_FILE_ID = 'YOUR_SOURCE_FILE_ID';
|
||||
|
||||
-- If missing, create configuration
|
||||
CALL FILE_MANAGER.ADD_SOURCE_FILE_CONFIG(
|
||||
pSourceKey => 'YOUR_SOURCE',
|
||||
pSourceFileType => 'INPUT',
|
||||
pSourceFileId => 'YOUR_SOURCE_FILE_ID',
|
||||
pSourceFileDesc => 'Legacy migrated data',
|
||||
pSourceFileNamePattern => 'pattern_*.csv',
|
||||
pTableId => 'YOUR_TABLE_ID',
|
||||
pTemplateTableName => 'CT_ET_TEMPLATES.YOUR_TEMPLATE'
|
||||
);
|
||||
```
|
||||
|
||||
## Known Limitations
|
||||
|
||||
### 1. No Retroactive A_SOURCE_FILE_RECEIVED Creation
|
||||
DATA_EXPORTER does not automatically create A_SOURCE_FILE_RECEIVED records when exporting legacy data. This is by design - it's a one-time export tool, not a file tracking system.
|
||||
|
||||
### 2. FILE_ARCHIVER Requires A_SOURCE_FILE_RECEIVED
|
||||
FILE_ARCHIVER cannot archive data without corresponding A_SOURCE_FILE_RECEIVED records. This prevents archiving of:
|
||||
- Legacy Informatica-loaded data exported via DATA_EXPORTER
|
||||
- Manually uploaded files not processed through FILE_MANAGER.PROCESS_SOURCE_FILE
|
||||
|
||||
### 3. Mixed Control Table References
|
||||
During migration period, some procedures reference A_LOAD_HISTORY (DATA_EXPORTER) while others reference A_WORKFLOW_HISTORY (FILE_ARCHIVER). This is intentional but requires careful understanding of data lineage.
|
||||
|
||||
### 4. A_WORKFLOW_HISTORY vs A_LOAD_HISTORY Column Mismatch
|
||||
The control tables have different schemas:
|
||||
- **A_LOAD_HISTORY**: `LOAD_START`, `A_ETL_LOAD_SET_KEY`
|
||||
- **A_WORKFLOW_HISTORY**: `WORKFLOW_START`, `A_WORKFLOW_HISTORY_KEY`
|
||||
|
||||
Test scripts must be aware of which table is being used.
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [PROCESS_SOURCE_FILE Guide](PROCESS_SOURCE_FILE_Guide.md) - File validation and ingestion workflow
|
||||
- [FILE_ARCHIVER Guide](FILE_ARCHIVER_Guide.md) - Archival strategies and configuration
|
||||
- [FILE_MANAGER Configuration Guide](FILE_MANAGER_Configuration_Guide.md) - System configuration
|
||||
- [Package Deployment Guide](Package_Deployment_Guide.md) - Deployment procedures
|
||||
|
||||
## Summary
|
||||
|
||||
The migration from Informatica + WLA to Airflow + DBT introduces new control tables (`A_SOURCE_FILE_RECEIVED`, `A_WORKFLOW_HISTORY`) while maintaining compatibility with legacy control tables (`A_LOAD_HISTORY`). Understanding the relationship between these tables is critical for:
|
||||
|
||||
- **Data Lineage**: Tracking which system processed which data
|
||||
- **Export Operations**: Choosing appropriate DATA_EXPORTER procedures
|
||||
- **Archival Operations**: Ensuring FILE_ARCHIVER has required metadata
|
||||
- **Testing**: Using correct control tables in test scenarios
|
||||
|
||||
The recommended approach for legacy data migration is **Strategy 2 (Direct to ARCHIVE)** for large datasets, as it avoids the complexity of manual A_SOURCE_FILE_RECEIVED registration while achieving the goal of moving historical data to long-term archival storage.
|
||||
@@ -394,6 +394,9 @@ DATA Bucket:
|
||||
├── ODS/
|
||||
│ └── {SOURCE}/
|
||||
│ └── {TABLE_NAME}/
|
||||
└── TRASH/ -- File retention subfolder (not a separate bucket)
|
||||
└── {SOURCE}/
|
||||
└── {TABLE_NAME}/ -- CSV files after archival (ARCHIVED_AND_TRASHED status)
|
||||
|
||||
ARCHIVE Bucket:
|
||||
└── ARCHIVE/
|
||||
@@ -402,6 +405,8 @@ ARCHIVE Bucket:
|
||||
└── PARTITION_YEAR=*/
|
||||
└── PARTITION_MONTH=*/
|
||||
└── *.parquet
|
||||
|
||||
Note: TRASH is a subfolder within the DATA bucket for file retention and rollback capability.
|
||||
```
|
||||
|
||||
### 4. Migration Checklist
|
||||
|
||||
@@ -123,7 +123,8 @@ WHEN OTHERS THEN
|
||||
```sql
|
||||
-- Dodano 'VALIDATION_FAILED' do dozwolonych statusów
|
||||
PROCESSING_STATUS IN ('RECEIVED', 'VALIDATED', 'READY_FOR_INGESTION',
|
||||
'INGESTED', 'ARCHIVED', 'VALIDATION_FAILED')
|
||||
'INGESTED', 'ARCHIVED', 'ARCHIVED_AND_TRASHED',
|
||||
'ARCHIVED_AND_PURGED', 'VALIDATION_FAILED')
|
||||
```
|
||||
|
||||
## 📊 Testowanie
|
||||
|
||||
Reference in New Issue
Block a user