# Package Deployment Guide - Developer Instructions ## Overview This guide provides step-by-step instructions for developers on how to properly deploy new package versions using the integrated version tracking and hash-based change detection system. **Target Audience:** Database developers working with CT_MRDS packages **System:** Oracle Database 23ai with ENV_MANAGER v3.1.0+ **Last Updated:** 2025-10-22 --- ## 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) 2. [Standard Deployment Workflow](#standard-deployment-workflow) 3. [Version Update Guidelines](#version-update-guidelines) 4. [Deployment Scenarios](#deployment-scenarios) 5. [Creating MARS Installation Packages](#creating-mars-installation-packages) 6. [Troubleshooting](#troubleshooting) 7. [Best Practices](#best-practices) 8. [Quick Reference](#quick-reference) --- ## Before You Start ### Step 0: Prepare Dedicated Working Directory and Git Branch **CRITICAL:** Before starting work on any MARS package, create a dedicated working directory with its own feature branch: ```powershell # Navigate to your Git repository parent directory cd c:\_git\_local_rep # Clone main repository to new working directory for MARS issue # This creates complete isolation for the feature branch git clone working_dir_02 working_dir_02_MARS-XXXX # Navigate to new working directory cd working_dir_02_MARS-XXXX # Ensure you're on main branch and it's up to date git checkout main git pull origin main # Create new feature branch for MARS issue git checkout -b feature/MARS-XXXX # Verify you're on the new branch git branch # You should see: * feature/MARS-XXXX (asterisk indicates current branch) ``` **Alternative: Git Worktree (Recommended for Advanced Users):** ```powershell # Navigate to your main Git repository cd c:\_git\_local_rep\working_dir_02 # Create new worktree with dedicated directory for feature branch git worktree add ..\working_dir_02_MARS-XXXX feature/MARS-XXXX # Navigate to new working directory cd ..\working_dir_02_MARS-XXXX # Verify you're on the new branch git branch ``` **Branch and Directory Naming Convention:** - **Branch Format**: `feature/MARS-XXXX` (e.g., `feature/MARS-1057`) - **Directory Format**: `working_dir_02_MARS-XXXX` (e.g., `working_dir_02_MARS-1057`) - Always branch from `main` to ensure clean starting point - One working directory per MARS issue for complete isolation **Working Directory Structure (isolated per MARS issue):** ``` c:\_git\_local_rep\ ├── working_dir_02\ # Main working directory (main branch) │ ├── MARS_Packages\ │ ├── database\ │ └── .git\ ├── working_dir_02_MARS-1057\ # Dedicated directory for MARS-1057 │ ├── MARS_Packages\ │ │ └── REL01\ │ │ └── MARS-1057\ # New package folder │ │ ├── rollback_version\ │ │ ├── new_version\ │ │ └── *.sql files │ ├── database\ │ └── .git\ # Tracks feature/MARS-1057 branch └── working_dir_02_MARS-1058\ # Dedicated directory for MARS-1058 (parallel work) └── ... ``` **Git Status Check:** ```powershell # Always verify which branch and directory you're working in pwd # Output should show: c:\_git\_local_rep\working_dir_02_MARS-XXXX git status # Output should show: On branch feature/MARS-XXXX # View all changes in current branch git status --short ``` **Why dedicated working directories are mandatory:** - **Complete Isolation**: Each MARS issue has its own physical directory - **Parallel Work**: Work on multiple MARS issues simultaneously without conflicts - **Clean Separation**: No risk of mixing changes from different features - **Testing Safety**: Test different features independently in separate environments - **Rollback Simplicity**: Delete entire directory to abandon feature - **Code Review**: Clear separation for pull request workflow - **Deployment Control**: Deploy from specific working directory with confidence **Git Worktree Benefits:** - Shares `.git` repository (saves disk space) - Faster than full clone - Automatic branch tracking - Recommended for experienced Git users **Cleanup After Merge:** ```powershell # After feature branch is merged to main, clean up working directory cd c:\_git\_local_rep # If using git worktree git worktree remove working_dir_02_MARS-XXXX # If using clone, simply delete directory Remove-Item -Recurse -Force working_dir_02_MARS-XXXX ``` --- ### Prerequisites - **ADMIN user access** - MARS package installations require ADMIN privileges for schema operations - Access to CT_MRDS schema (or appropriate schema) - SQLcl or SQL*Plus installed - Understanding of Semantic Versioning (MAJOR.MINOR.PATCH) - Package source files available locally - **Git installed and configured** - Required for version control workflow **CRITICAL - Data Dictionary Views:** When installing as ADMIN user, you MUST use `ALL_*` views instead of `USER_*` views for verification queries: | ❌ WRONG (USER_*) | ✅ CORRECT (ALL_* with OWNER filter) | |-------------------|--------------------------------------| | `SELECT * FROM USER_ERRORS WHERE NAME = 'PKG'` | `SELECT * FROM ALL_ERRORS WHERE OWNER = 'CT_MRDS' AND NAME = 'PKG'` | | `SELECT * FROM USER_OBJECTS WHERE OBJECT_NAME = 'X'` | `SELECT * FROM ALL_OBJECTS WHERE OWNER = 'CT_MRDS' AND OBJECT_NAME = 'X'` | | `SELECT * FROM USER_TAB_COLUMNS WHERE TABLE_NAME = 'T'` | `SELECT * FROM ALL_TAB_COLUMNS WHERE OWNER = 'CT_MRDS' AND TABLE_NAME = 'T'` | | `SELECT * FROM USER_TABLES WHERE TABLE_NAME = 'T'` | `SELECT * FROM ALL_TABLES WHERE OWNER = 'CT_MRDS' AND TABLE_NAME = 'T'` | **Why this matters:** `USER_*` views show objects in the **current schema** (ADMIN). When creating objects in other schemas (ODS, CT_MRDS), you must query `ALL_*` views with explicit OWNER filter to verify the changes. ### System Components The deployment system uses these key components: - **ENV_MANAGER** - Centralized version management and hash tracking - **A_PACKAGE_VERSION_TRACKING** - History table for all package versions - **CALCULATE_PACKAGE_HASH** - SHA256 hash calculation for change detection - **TRACK_PACKAGE_VERSION** - Records package versions with automatic change detection - **CHECK_PACKAGE_CHANGES** - Validates if package was modified --- ## Universal Tracking and Verification Scripts ### MANDATORY: Use Standard Template Files **CRITICAL:** Every MARS package MUST include two universal scripts for tracking and verification. These scripts are reusable across all MARS issues and provide consistent version management. #### Required Files Structure ``` MARS_Packages/ └── REL0X/ └── MARS-XXXX/ ├── 01_MARS_XXXX_install_*.sql ├── 02_MARS_XXXX_install_*.sql ├── track_package_versions.sql # ✅ MANDATORY - Universal tracking ├── verify_packages_version.sql # ✅ MANDATORY - Universal verification ├── install_marsXXXX.sql # Master script └── rollback_marsXXXX.sql ``` ### track_package_versions.sql **Purpose:** Universal script for tracking multiple package versions with editable package list. **Key Features:** - ✅ **Reusable** - Same file for all MARS issues - ✅ **Configurable** - Edit package list array to specify which packages to track - ✅ **Automatic** - Calls ENV_MANAGER.TRACK_PACKAGE_VERSION for each package - ✅ **Summary Output** - Shows tracked packages count and versions **Template:** ```sql -- =================================================================== -- PACKAGE LIST - Edit this array to specify packages to track -- =================================================================== vPackageList t_string_array := t_string_array( 'CT_MRDS.DATA_EXPORTER', 'CT_MRDS.FILE_MANAGER', 'ODS.FILE_MANAGER_ODS' ); -- =================================================================== ``` **Usage in Install Script:** ```sql PROMPT Step 4: Track Package Versions PROMPT ========================================================================= @@track_package_versions.sql ``` **Benefits over custom tracking scripts:** - No hardcoded package names in multiple places - Single point of configuration - Consistent error handling - Standardized output format - Copy-paste ready for new MARS issues ### verify_packages_version.sql **Purpose:** Universal script for verifying ALL tracked packages for code changes. **Key Features:** - ✅ **Automatic Discovery** - Queries A_PACKAGE_VERSION_TRACKING to find all tracked packages - ✅ **Hash Validation** - Calls CHECK_PACKAGE_CHANGES for each package - ✅ **Status Report** - Shows OK or WARNING for each package - ✅ **Zero Configuration** - No editing needed, works automatically **Usage in Install Script:** ```sql PROMPT Final Step: Verify All Package Versions PROMPT ========================================================================= @@verify_packages_version.sql ``` **Output Example:** ``` PACKAGE_OWNER PACKAGE_NAME VERSION STATUS --------------- ------------------- ---------- ------------------------------- CT_MRDS DATA_EXPORTER 2.2.0 OK: Package has not changed CT_MRDS FILE_MANAGER 3.3.0 OK: Package has not changed ODS FILE_MANAGER_ODS 2.1.0 OK: Package has not changed ``` ### Master Install Script Structure (MANDATORY) Every `install_marsXXXX.sql` MUST follow this exact structure: ```sql -- =================================================================== -- MARS-XXXX INSTALL SCRIPT -- =================================================================== -- Dynamic spool file generation host mkdir log 2>nul -- ... spool setup ... PROMPT Step 1: Deploy Package Specification @@01_MARS_XXXX_install_PACKAGE_SPEC.sql PROMPT Step 2: Deploy Package Body @@02_MARS_XXXX_install_PACKAGE_BODY.sql PROMPT Step 3: Track Package Versions @@track_package_versions.sql -- ✅ MANDATORY universal script PROMPT Step 4: Verify Package Versions @@verify_packages_version.sql -- ✅ MANDATORY universal script spool off quit; ``` ### DO NOT Create Custom Track/Verify Scripts **❌ WRONG (Custom tracking per MARS issue):** ```sql @@04_MARS_XXXX_track_version.sql -- DON'T DO THIS @@05_MARS_XXXX_verify_installation.sql -- DON'T DO THIS ``` **✅ CORRECT (Universal scripts):** ```sql @@track_package_versions.sql -- Always use this @@verify_packages_version.sql -- Always use this ``` **Why universal scripts are mandatory:** - **Consistency** - Same behavior across all MARS packages - **Maintainability** - Bug fixes propagate to all packages - **Simplicity** - No need to create custom scripts for each issue - **Compliance** - Ensures all packages follow same standard - **Code Review** - Easier to review when structure is identical ### Copying Template Files **For each new MARS package, copy from reference implementation:** ```powershell # Copy universal scripts from MARS-826-PREHOOK (reference implementation) Copy-Item "MARS_Packages\REL01_POST_DEACTIVATION\MARS-826-PREHOOK\track_package_versions.sql" ` "MARS_Packages\RELXX\MARS-YYYY\track_package_versions.sql" Copy-Item "MARS_Packages\REL01_POST_DEACTIVATION\MARS-826-PREHOOK\verify_packages_version.sql" ` "MARS_Packages\RELXX\MARS-YYYY\verify_packages_version.sql" # Edit package list in track_package_versions.sql # No changes needed to verify_packages_version.sql (works automatically) ``` --- ## Standard Deployment Workflow ### Step 1: Check Current Package Status Before making any changes, verify the current state: ```sql -- Connect to database sql CT_MRDS/password@service_name -- Check current version SELECT FILE_MANAGER.GET_VERSION() FROM DUAL; -- Check for any untracked changes SELECT ENV_MANAGER.CHECK_PACKAGE_CHANGES('CT_MRDS', 'FILE_MANAGER') FROM DUAL; ``` **Expected Output:** `OK: Package CT_MRDS.FILE_MANAGER has not changed.` If you see **WARNING**, it means there are untracked modifications. See [Handling Untracked Changes](#handling-untracked-changes). --- ### Step 2: Make Your Code Changes Edit the package SPEC and/or BODY files in your local workspace: ``` database/CT_MRDS/packages/FILE_MANAGER.pkg database/CT_MRDS/packages/FILE_MANAGER.pkb ``` **Important:** Do not modify version constants yet. --- ### Step 3: Update Version Information Based on the type of changes, update version constants in the **SPEC** file: #### A. Determine Version Increment Follow Semantic Versioning rules: - **MAJOR (X.0.0)** - Breaking changes, incompatible API modifications - **MINOR (x.Y.0)** - New features, backward-compatible additions - **PATCH (x.y.Z)** - Bug fixes, backward-compatible corrections #### B. Update Package Constants Edit the package SPEC file and update three constants: ```sql -- Package Version Information (Semantic Versioning: MAJOR.MINOR.PATCH) PACKAGE_VERSION CONSTANT VARCHAR2(10) := '3.3.0'; -- INCREMENT THIS PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := '2025-10-22 21:00:00'; -- UPDATE THIS PACKAGE_AUTHOR CONSTANT VARCHAR2(100) := 'Your Name'; -- YOUR NAME -- Version History (Latest changes first) VERSION_HISTORY CONSTANT VARCHAR2(4000) := '3.3.0 (2025-10-22): Added new export procedure for historical data' || CHR(13)||CHR(10) || -- ADD THIS LINE '3.2.0 (2025-10-15): Enhanced validation with column mismatch detection' || CHR(13)||CHR(10) || '3.1.0 (2025-10-01): Initial release with file processing capabilities'; ``` **Version History Format:** ``` 'VERSION (DATE): Brief description of changes' || CHR(13)||CHR(10) || ``` --- ### Step 4: Deploy to Database Deploy SPEC first, then BODY: ```powershell # Using PowerShell and SQLcl Get-Content "database\CT_MRDS\packages\FILE_MANAGER.pkg" | sql "CT_MRDS/password@service_name" Get-Content "database\CT_MRDS\packages\FILE_MANAGER.pkb" | sql "CT_MRDS/password@service_name" ``` Or using SQL*Plus: ```sql @database/CT_MRDS/packages/FILE_MANAGER.pkg @database/CT_MRDS/packages/FILE_MANAGER.pkb ``` **Check for compilation errors:** ```sql -- When installing as ADMIN, check specific schema SELECT * FROM ALL_ERRORS WHERE OWNER = 'CT_MRDS' AND TYPE IN ('PACKAGE', 'PACKAGE BODY') AND NAME = 'FILE_MANAGER' ORDER BY SEQUENCE; ``` --- ### Step 5: Track the New Version After successful deployment, register the new version in the tracking system: ```sql BEGIN ENV_MANAGER.TRACK_PACKAGE_VERSION( pPackageOwner => 'CT_MRDS', pPackageName => 'FILE_MANAGER', pPackageVersion => FILE_MANAGER.PACKAGE_VERSION, pPackageBuildDate => FILE_MANAGER.PACKAGE_BUILD_DATE, pPackageAuthor => FILE_MANAGER.PACKAGE_AUTHOR ); END; / ``` **System Response:** - If version updated correctly: `First tracking record` or `End TRACK_PACKAGE_VERSION - Record inserted` - If version NOT updated: `WARNING: Source code changed without version update!` --- ### Step 6: Verify Deployment Confirm the deployment was successful: ```sql -- 1. Check deployed version SELECT FILE_MANAGER.GET_BUILD_INFO() FROM DUAL; -- 2. Verify no untracked changes SELECT ENV_MANAGER.CHECK_PACKAGE_CHANGES('CT_MRDS', 'FILE_MANAGER') FROM DUAL; -- 3. Review tracking history SELECT PACKAGE_VERSION, PACKAGE_BUILD_DATE, DETECTED_CHANGE_WITHOUT_VERSION, TO_CHAR(TRACKING_DATE, 'YYYY-MM-DD HH24:MI:SS') AS TRACKED_AT FROM A_PACKAGE_VERSION_TRACKING WHERE PACKAGE_OWNER = 'CT_MRDS' AND PACKAGE_NAME = 'FILE_MANAGER' ORDER BY TRACKING_DATE DESC FETCH FIRST 5 ROWS ONLY; ``` --- ### Step 7: Update Source Repository (CODE-FIRST Compliance) **CRITICAL:** After successful database deployment, updated packages MUST be copied back to the main source repository to maintain version control integrity. ```powershell # Copy updated packages to source repository # Replace PACKAGE_NAME with actual package name (e.g., FILE_MANAGER) Copy-Item "database\CT_MRDS\packages\PACKAGE_NAME.pkg" ` "MARS_Packages\mrds_elt-dev-database\mrds_elt-dev-database\database\CT_MRDS\SCHEMA\packages\PACKAGE_NAME.pkg" Copy-Item "database\CT_MRDS\packages\PACKAGE_NAME.pkb" ` "MARS_Packages\mrds_elt-dev-database\mrds_elt-dev-database\database\CT_MRDS\SCHEMA\packages\PACKAGE_NAME.pkb" ``` **Why this is mandatory:** - **CODE-FIRST PRINCIPLE**: Source files are the single source of truth - **Version Control**: Git tracks changes in source repository - **Team Collaboration**: Other developers need access to latest code - **Deployment Reproducibility**: Enables clean deployments to other environments - **Rollback Capability**: Source repository serves as backup **Directory Structure:** ``` MARS_Packages/ └── mrds_elt-dev-database/ └── mrds_elt-dev-database/ └── database/ ├── CT_MRDS/ │ └── SCHEMA/ │ ├── packages/ │ │ ├── FILE_MANAGER.pkg # ← Specification │ │ ├── FILE_MANAGER.pkb # ← Body │ │ ├── DATA_EXPORTER.pkg │ │ ├── DATA_EXPORTER.pkb │ │ ├── ENV_MANAGER.pkg │ │ └── ENV_MANAGER.pkb │ ├── tables/ │ ├── views/ │ └── triggers/ ├── ODS/ │ └── SCHEMA/ │ └── packages/ │ ├── FILE_MANAGER_ODS.pkg # ← Specification │ └── FILE_MANAGER_ODS.pkb # ← Body └── CT_ET_TEMPLATES/ └── SCHEMA/ └── tables/ ``` **Verification:** ```powershell # Verify files were updated Get-ChildItem "MARS_Packages\mrds_elt-dev-database\mrds_elt-dev-database\database\CT_MRDS\SCHEMA\packages\*.pkg", ` "MARS_Packages\mrds_elt-dev-database\mrds_elt-dev-database\database\CT_MRDS\SCHEMA\packages\*.pkb" | Select-Object Name, LastWriteTime | Sort-Object LastWriteTime -Descending ``` --- ## Version Update Guidelines ### Semantic Versioning Rules | Change Type | Version Impact | Example | Description | |-------------|---------------|---------|-------------| | **Breaking Change** | MAJOR (3.0.0 → 4.0.0) | Changed procedure signature, removed parameter | Requires code changes in calling applications | | **New Feature** | MINOR (3.2.0 → 3.3.0) | Added new procedure, new optional parameter | Backward compatible, adds functionality | | **Bug Fix** | PATCH (3.2.1 → 3.2.2) | Fixed calculation error, corrected validation | No API changes, fixes existing functionality | | **Refactoring** | PATCH (3.2.1 → 3.2.2) | Code cleanup, performance optimization | Internal changes only, no behavior change | ### Build Date Format Always use ISO 8601 format with time: ```sql PACKAGE_BUILD_DATE CONSTANT VARCHAR2(20) := 'YYYY-MM-DD HH24:MI:SS'; ``` **Example:** `'2025-10-22 21:00:00'` --- ## Deployment Scenarios ### Scenario 1: New Feature Addition (MINOR Version) **Example:** Adding new export procedure to FILE_MANAGER 1. **Current Version:** 3.2.0 2. **New Version:** 3.3.0 3. **Changes:** - Add new procedure `EXPORT_HISTORICAL_DATA` to SPEC - Implement procedure in BODY - Update `PACKAGE_VERSION` from `'3.2.0'` to `'3.3.0'` - Update `PACKAGE_BUILD_DATE` to current timestamp - Add entry to `VERSION_HISTORY` 4. **Deploy & Track:** ```sql -- Deploy files @database/CT_MRDS/packages/FILE_MANAGER.pkg @database/CT_MRDS/packages/FILE_MANAGER.pkb -- Track new version BEGIN ENV_MANAGER.TRACK_PACKAGE_VERSION( pPackageOwner => 'CT_MRDS', pPackageName => 'FILE_MANAGER', pPackageVersion => FILE_MANAGER.PACKAGE_VERSION, pPackageBuildDate => FILE_MANAGER.PACKAGE_BUILD_DATE, pPackageAuthor => FILE_MANAGER.PACKAGE_AUTHOR ); END; / ``` --- ### Scenario 2: Bug Fix (PATCH Version) **Example:** Fixing date format validation in DATA_EXPORTER 1. **Current Version:** 2.1.0 2. **New Version:** 2.1.1 3. **Changes:** - Fix validation logic in BODY (no SPEC changes) - Update `PACKAGE_VERSION` from `'2.1.0'` to `'2.1.1'` - Update `PACKAGE_BUILD_DATE` - Add entry to `VERSION_HISTORY` 4. **Deploy & Track:** Same as Scenario 1 --- ### Scenario 3: Breaking Change (MAJOR Version) **Example:** Removing deprecated parameter from FILE_ARCHIVER 1. **Current Version:** 2.5.3 2. **New Version:** 3.0.0 3. **Changes:** - Remove old parameter from procedure signature in SPEC - Update BODY implementation - Update `PACKAGE_VERSION` from `'2.5.3'` to `'3.0.0'` - Update `PACKAGE_BUILD_DATE` - Add detailed migration notes to `VERSION_HISTORY` 4. **Additional Steps:** - Document breaking changes - Notify dependent application teams - Update API documentation --- ### Scenario 4: Emergency Hotfix When urgent fix is needed in production: 1. **Identify Issue:** Document the problem clearly 2. **Create Fix:** Make minimal changes to address the issue 3. **Increment PATCH:** Update to next patch version (e.g., 3.2.5 → 3.2.6) 4. **Fast Track Deployment:** ```powershell # Quick deployment script Get-Content "database\CT_MRDS\packages\PACKAGE_NAME.pkg" | sql "CT_MRDS/password@service_name" Get-Content "database\CT_MRDS\packages\PACKAGE_NAME.pkb" | sql "CT_MRDS/password@service_name" # Track immediately echo "BEGIN ENV_MANAGER.TRACK_PACKAGE_VERSION('CT_MRDS', 'PACKAGE_NAME', 'VERSION', 'BUILD_DATE', 'AUTHOR'); END;" | sql "CT_MRDS/password@service_name" ``` 5. **Verify & Document:** Record hotfix details in change log --- ## Troubleshooting ### Issue 1: Warning - Untracked Changes Detected **Symptom:** ``` WARNING: Source code changed without version update! Last Version: 3.2.0 Current Version: 3.2.0 SPECIFICATION Changed: Hash mismatch detected ``` **Cause:** Code was modified but version constants were not updated. **Solution:** 1. Update `PACKAGE_VERSION` to next appropriate version 2. Update `PACKAGE_BUILD_DATE` to current timestamp 3. Add entry to `VERSION_HISTORY` 4. Redeploy package 5. Call `TRACK_PACKAGE_VERSION` again --- ### Issue 2: Compilation Errors After Deployment **Symptom:** ``` Package Body compiled with errors LINE/COL ERROR -------- ------------- 42/10 PLS-00201: identifier 'PROCEDURE_NAME' must be declared ``` **Solution:** 1. Check `ALL_ERRORS` for detailed error information: ```sql -- Check specific schema when installing as ADMIN SELECT LINE, POSITION, TEXT FROM ALL_ERRORS WHERE OWNER = 'CT_MRDS' -- Replace with target schema AND NAME = 'PACKAGE_NAME' AND TYPE = 'PACKAGE BODY' ORDER BY SEQUENCE; ``` 2. Fix errors in source file 3. Redeploy package 4. Verify compilation: `SELECT * FROM ALL_ERRORS WHERE OWNER = 'CT_MRDS' AND NAME = 'PACKAGE_NAME';` --- ### Issue 3: Package State Discarded Error **Symptom:** ``` ORA-04068: existing state of packages has been discarded ORA-04061: existing state of package body has been invalidated ``` **Cause:** Package was recently recompiled, session state needs refresh. **Solution:** Simply retry the command. This is a transient error that resolves after first execution. --- ### Issue 4: Cannot Track Package - Not Found **Symptom:** ``` ERROR tracking PACKAGE_NAME: Package not found in database ``` **Solution:** 1. Verify package exists: ```sql -- Check specific schema when installing as ADMIN SELECT OBJECT_NAME, OBJECT_TYPE, STATUS FROM ALL_OBJECTS WHERE OWNER = 'CT_MRDS' -- Replace with target schema AND OBJECT_NAME = 'PACKAGE_NAME'; ``` 2. If not found, deploy package first 3. If status = INVALID, recompile package 4. Retry tracking --- ## Creating MARS Installation Packages ### Overview MARS packages (e.g., MARS-1049, MARS-1011) are deployment packages that bundle database changes for specific features or fixes. They follow a standardized structure with logging, version tracking, and rollback capabilities. **CRITICAL:** All MARS package installations MUST be executed as **ADMIN user** to ensure proper schema creation, privilege management, and cross-schema operations. **Installation User Requirements:** - **User:** ADMIN (required for all MARS installations) - **Privileges:** Full DBA privileges, CREATE ANY TABLE, ALTER ANY TABLE, EXECUTE on DBMS_CLOUD - **Connection:** `sql ADMIN/password@service_name` ### Package Structure **IMPORTANT:** Currently, all new MARS packages are being created in the **REL01** directory. This is the active release folder for ongoing development. **CRITICAL - .gitignore Configuration:** Before starting MARS package development, create `.gitignore` file in package root directory to exclude temporary folders from version control: **File Location:** `MARS_Packages/REL01/MARS-XXXX/.gitignore` **Required Content:** ```gitignore # Exclude temporary folders from version control confluence/ log/ test/ mock_data/ ``` **Why exclude these folders:** - **confluence/**: Working documentation files (may contain drafts, not final versions) - **log/**: SPOOL log files (generated during installation, environment-specific) - **test/**: Test artifacts, temporary test data, and test execution logs - **mock_data/**: Test data files for development and validation (environment-specific) **What SHOULD be committed:** - Installation scripts (01_*, 02_*, 91_*, 92_*) - Master scripts (install_*.sql, rollback_*.sql) - track_package_versions.sql and verify_packages_version.sql - README.md - .gitignore (with standardized exclusions) - rollback_version/ and new_version/ folders (if package modifications) - Core deployment files only Standard MARS package directory structure: ``` MARS_Packages/REL01/MARS-XXXX/ ├── .gitignore # Git exclusions (REQUIRED) ├── install_marsXXXX.sql # Master installation script (with SPOOL to log/) ├── rollback_marsXXXX.sql # Master rollback script (with SPOOL to log/) ├── 01_MARS_XXXX_install_*.sql # Individual installation scripts ├── 02_MARS_XXXX_install_*.sql ├── ... ├── 91_MARS_XXXX_rollback_*.sql # Individual rollback scripts (91-99 range) ├── 92_MARS_XXXX_rollback_*.sql ├── track_package_versions.sql # Version tracking script ├── verify_packages_version.sql # Package verification script ├── ... ├── README.md # Package documentation ├── rollback_version/ # Backup of objects BEFORE changes (for rollback) │ ├── PACKAGE_NAME.pkg # Previous package specification │ └── PACKAGE_NAME.pkb # Previous package body ├── new_version/ # Updated objects AFTER changes (for installation) │ ├── PACKAGE_NAME.pkg # New package specification │ └── PACKAGE_NAME.pkb # New package body ├── test/ # Test files and verification scripts │ ├── test_marsXXXX.sql # Unit tests │ ├── TEST_RESULTS.md # Test documentation │ └── test_data_*.csv # Test data files ├── log/ # SPOOL log files (REQUIRED - auto-created) │ ├── INSTALL_MARS_XXXX_*.log # Installation logs from SPOOL │ └── ROLLBACK_MARS_XXXX_*.log # Rollback logs from SPOOL └── mock_data/ # Mock data for testing (optional) ├── 00_LOAD_ALL_MOCK_DATA.sql # Master data loader ├── 01_load_*.sql # Individual table loaders └── README.md # Mock data documentation ``` **Naming Conventions:** - **Installation scripts**: `01-89` range, executed in numerical order - **Rollback scripts**: `91-99` range, executed in reverse order - **Verification scripts**: Any number, typically after main scripts - **Master scripts**: `install_marsXXXX.sql` and `rollback_marsXXXX.sql` **Version Management Folders (for Database Object Modifications):** - **`rollback_version/`** - Contains backup of database objects BEFORE changes (for rollback) - **`new_version/`** - Contains updated database objects AFTER changes (for installation) **When to use version folders:** - Required when MARS package modifies ANY existing database objects (packages, tables, views, indexes, triggers, etc.) - Copy original object definitions to `rollback_version/` before making changes - Place modified object definitions in `new_version/` after changes - Examples: FILE_MANAGER.pkg/pkb, A_SOURCE_FILE_CONFIG.sql (table), V_STATUS.sql (view), IDX_CONFIG.sql (index) **Test Files Organization:** - **`test/`** - Contains ALL test-related files (unit tests, test data, verification scripts) - **`log/`** - Contains ALL SPOOL log files from installation/rollback executions (REQUIRED directory) - **`mock_data/`** - Contains mock data files for development and testing (optional) - Keep deployment scripts clean - move test artifacts to test/ subfolder after validation - Include track_package_versions.sql and verify_packages_version.sql in test/ subfolder - SPOOL log files automatically created in log/ directory by master scripts - Benefits: Clean deployment structure, easy test replication, organized documentation --- ### Master Install Script Template All MARS packages MUST include SPOOL logging for audit trail and debugging: ```sql -- =================================================================== -- MARS-XXXX INSTALL SCRIPT: Brief Description -- =================================================================== -- Purpose: Detailed description of what this package does -- Author: Grzegorz Michalski -- Date: YYYY-MM-DD -- Version: X.Y.Z -- Dynamic spool file generation (using SYS_CONTEXT - no DBA privileges required) -- Log files are automatically created in log/ subdirectory -- IMPORTANT: Ensure log/ directory exists before SPOOL (use host mkdir) host mkdir log 2>nul var filename VARCHAR2(100) BEGIN :filename := 'log/INSTALL_MARS_XXXX_' || SYS_CONTEXT('USERENV', 'CON_NAME') || '_' || TO_CHAR(SYSDATE,'YYYYMMDD_HH24MISS') || '.log'; END; / column filename new_value _filename select :filename filename from dual; spool &_filename SET ECHO OFF SET TIMING ON SET SERVEROUTPUT ON SIZE UNLIMITED SET PAUSE OFF -- Set current schema context (optional - use when modifying packages in specific schema) -- ALTER SESSION SET CURRENT_SCHEMA = CT_MRDS; PROMPT ========================================================================= PROMPT MARS-XXXX: Package Description PROMPT ========================================================================= PROMPT PROMPT This script will: PROMPT - Change 1 PROMPT - Change 2 PROMPT - Change 3 PROMPT PROMPT Expected Duration: X-Y minutes PROMPT ========================================================================= -- Confirm installation with user 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 PROMPT PROMPT ========================================================================= PROMPT Step 1: First Installation Step PROMPT ========================================================================= @@01_MARS_XXXX_install_step1.sql PROMPT PROMPT ========================================================================= PROMPT Step 2: Second Installation Step PROMPT ========================================================================= @@02_MARS_XXXX_install_step2.sql -- ... more deployment steps ... PROMPT PROMPT ========================================================================= PROMPT Step N: Track Package Versions PROMPT ========================================================================= @@track_package_versions.sql PROMPT PROMPT ========================================================================= PROMPT Final Step: Verify Package Versions PROMPT ========================================================================= @@verify_packages_version.sql PROMPT PROMPT ========================================================================= PROMPT MARS-XXXX Installation - COMPLETED PROMPT ========================================================================= PROMPT Check the log file for complete installation details. PROMPT ========================================================================= spool off quit; ``` **Key Elements:** 1. **Log Directory Creation**: `host mkdir log 2>nul` - Creates log/ directory before SPOOL (suppresses error if exists) 2. **Dynamic Log Name**: `log/INSTALL_MARS_XXXX__YYYYMMDD_HH24MISS.log` (stored in log/ subdirectory) 3. **SYS_CONTEXT Usage**: Uses `SYS_CONTEXT('USERENV', 'CON_NAME')` instead of `DBA_PDBS` - no DBA privileges required 4. **SPOOL START**: After filename generation, before first PROMPT 5. **SPOOL OFF**: At the very end of the script 6. **SET ECHO OFF**: Prevents double output of PROMPT commands (shows only results, not the SQL commands themselves) 7. **ACCEPT Validation**: User confirmation required before execution (safety feature) 8. **ALTER SESSION SET CURRENT_SCHEMA** (optional): Sets working schema for package operations 9. **@@ Includes**: All sub-scripts executed via `@@` command 10. **track_package_versions.sql**: MANDATORY universal tracking script (must be included before verify) 11. **verify_packages_version.sql**: MANDATORY universal verification script (must be last step before completion) 12. **quit;**: Exits SQLcl/SQL*Plus after completion (important for automated deployments) **SET ECHO OFF Benefits:** - **Clean Output**: PROMPT messages appear only once in console and log files - **Readability**: Log files are easier to read without SQL command echo - **Professional**: Produces cleaner, more professional-looking installation logs - **Consistency**: Works the same in both SQLcl and SQL*Plus - **Sub-Scripts**: Must NOT include `SET ECHO ON` - they inherit setting from master script **ACCEPT Validation Benefits:** - **Safety Check**: Prevents accidental execution - requires explicit "YES" confirmation - **User Control**: User must type YES (case-insensitive) to proceed with changes - **Abort Capability**: Any other input or Ctrl+C safely aborts before database modifications - **SQLcl & SQL*Plus Compatible**: Works identically in both tools, unlike PAUSE - **Best Practice**: Mandatory for both installation and rollback master scripts **Log File Storage:** - **Directory**: All SPOOL logs automatically created in `log/` subdirectory - **Naming Convention**: `log/INSTALL_MARS_XXXX__.log` or `log/ROLLBACK_MARS_XXXX__.log` - **Auto-Creation**: Directory created by `host mkdir log 2>nul` command before SPOOL (MANDATORY) - **Error Suppression**: `2>nul` suppresses "directory already exists" errors in PowerShell/Windows - **Version Control**: Excluded via .gitignore (environment-specific files) - **Importance**: Without `host mkdir`, SPOOL may fail if log/ directory doesn't exist **Why `host mkdir log 2>nul` is mandatory:** - **Reliability**: Ensures log/ directory exists before SPOOL attempts to write - **Cross-Environment**: Works on fresh Git clones where log/ doesn't exist yet - **No Errors**: Silently succeeds whether directory exists or not - **Best Practice**: Prevents installation failures due to missing log directory - **PowerShell Compatible**: Works in both PowerShell (pwsh.exe) and Windows CMD --- 9. **quit;**: Exits SQLcl/SQL*Plus after completion (important for automated deployments) **SET ECHO OFF Benefits:** - **Clean Output**: PROMPT messages appear only once in console and log files - **Readability**: Log files are easier to read without SQL command echo - **Professional**: Produces cleaner, more professional-looking installation logs - **Consistency**: Works the same in both SQLcl and SQL*Plus - **Sub-Scripts**: Must NOT include `SET ECHO ON` - they inherit setting from master script **ACCEPT Validation Benefits:** - **Safety Check**: Prevents accidental execution - requires explicit "YES" confirmation - **User Control**: User must type YES (case-insensitive) to proceed with changes - **Abort Capability**: Any other input or Ctrl+C safely aborts before database modifications - **SQLcl & SQL*Plus Compatible**: Works identically in both tools, unlike PAUSE - **Best Practice**: Mandatory for both installation and rollback master scripts --- ### Complete MARS Package Example **MARS-835-PREHOOK** - Real-world example following all standards: **File Structure:** ``` MARS_Packages/REL01_POST_DEACTIVATION/MARS-835-PREHOOK/ ├── .gitignore ├── install_mars835_prehook.sql # Master install (uses universal scripts) ├── rollback_mars835_prehook.sql # Master rollback ├── 01_MARS_835_install_DATA_EXPORTER_SPEC.sql ├── 02_MARS_835_install_DATA_EXPORTER_BODY.sql ├── 91_MARS_835_rollback_DATA_EXPORTER_BODY.sql ├── 92_MARS_835_rollback_DATA_EXPORTER_SPEC.sql ├── track_package_versions.sql # ✅ Universal tracking ├── verify_packages_version.sql # ✅ Universal verification ├── README.md ├── rollback_version/ │ ├── DATA_EXPORTER.pkg # v2.1.1 (before changes) │ └── DATA_EXPORTER.pkb ├── new_version/ │ ├── DATA_EXPORTER.pkg # v2.2.0 (after changes) │ └── DATA_EXPORTER.pkb └── log/ # Auto-created by install script ``` **track_package_versions.sql** (edited for this MARS issue): ```sql -- =================================================================== -- PACKAGE LIST - Edit this array to specify packages to track -- =================================================================== vPackageList t_string_array := t_string_array( 'CT_MRDS.DATA_EXPORTER' -- Only package modified in MARS-835 ); -- =================================================================== ``` **install_mars835_prehook.sql** (master script): ```sql -- =================================================================== -- MARS-835-PREHOOK INSTALL SCRIPT -- =================================================================== host mkdir log 2>nul var filename VARCHAR2(100) BEGIN :filename := 'log/INSTALL_MARS_835_PREHOOK_' || SYS_CONTEXT('USERENV', 'CON_NAME') || '_' || TO_CHAR(SYSDATE,'YYYYMMDD_HH24MISS') || '.log'; END; / column filename new_value _filename select :filename filename from dual; spool &_filename SET ECHO OFF SET TIMING ON SET SERVEROUTPUT ON SIZE UNLIMITED PROMPT ========================================================================= PROMPT MARS-835-PREHOOK: DRY Refactoring for DATA_EXPORTER PROMPT ========================================================================= ACCEPT continue CHAR PROMPT 'Type YES to continue: ' WHENEVER SQLERROR EXIT SQL.SQLCODE BEGIN IF UPPER(TRIM('&continue')) != 'YES' THEN RAISE_APPLICATION_ERROR(-20001, 'Installation aborted'); END IF; END; / WHENEVER SQLERROR CONTINUE PROMPT PROMPT Step 1: Deploy DATA_EXPORTER Package Specification (v2.2.0) @@01_MARS_835_install_DATA_EXPORTER_SPEC.sql PROMPT PROMPT Step 2: Deploy DATA_EXPORTER Package Body (v2.2.0) @@02_MARS_835_install_DATA_EXPORTER_BODY.sql PROMPT PROMPT Step 3: Track Package Versions @@track_package_versions.sql PROMPT PROMPT Step 4: Verify Package Versions @@verify_packages_version.sql PROMPT PROMPT ========================================================================= PROMPT MARS-835-PREHOOK Installation - COMPLETED PROMPT ========================================================================= spool off quit; ``` **Why this is the correct pattern:** - ✅ Uses universal `track_package_versions.sql` (no custom 04_MARS_835_track_version.sql) - ✅ Uses universal `verify_packages_version.sql` (no custom 03_MARS_835_verify_installation.sql) - ✅ Tracking happens AFTER deployment (Step 3) - ✅ Verification happens LAST (Step 4) to confirm everything is correct - ✅ Single configuration point (edit package list in track_package_versions.sql) - ✅ Consistent with ALL other MARS packages - ✅ Easy to copy/paste for new MARS issues --- ### SPOOL Logging Benefits **Why SPOOL is mandatory:** 1. **Audit Trail** - Complete record of all installation activities 2. **Debugging** - Capture errors, warnings, and execution details 3. **Compliance** - Required for production deployments 4. **Troubleshooting** - Review what actually happened during installation 5. **Documentation** - Proof of successful deployment **Log File Contains:** - All PROMPT messages - SQL execution results - Error messages (ORA-XXXXX) - Timing information - Package compilation status - Version tracking confirmations **Example Log File Name:** ``` log/INSTALL_MARS_1049_ggmichalski_20251126_143052.log ``` **Log Location:** `log/` subdirectory in MARS package root (auto-created by SPOOL) --- ### Creating Individual Installation Scripts Each numbered script should be self-contained and focused: **Example: `01_MARS_1049_install_CT_MRDS_ADD_ENCODING_COLUMN.sql`** ```sql --============================================================================================================================= -- MARS-1049: Add ENCODING Column to A_SOURCE_FILE_CONFIG Table --============================================================================================================================= -- Purpose: Add VARCHAR2(50) ENCODING column with UTF8 default -- Author: Grzegorz Michalski -- Date: 2025-11-24 -- Related: MARS-1049 CSV Encoding Support --============================================================================================================================= SET SERVEROUTPUT ON PROMPT ======================================================================== PROMPT Adding ENCODING column to CT_MRDS.A_SOURCE_FILE_CONFIG PROMPT ======================================================================== -- Add column ALTER TABLE CT_MRDS.A_SOURCE_FILE_CONFIG ADD (ENCODING VARCHAR2(50) DEFAULT 'UTF8'); -- Add comment COMMENT ON COLUMN CT_MRDS.A_SOURCE_FILE_CONFIG.ENCODING IS 'Character encoding for CSV files (e.g., UTF8, WE8MSWIN1252)'; -- Verify change (check specific schema when installing as ADMIN) SELECT COUNT(*) AS ENCODING_COLUMN_EXISTS FROM ALL_TAB_COLUMNS WHERE OWNER = 'CT_MRDS' AND TABLE_NAME = 'A_SOURCE_FILE_CONFIG' AND COLUMN_NAME = 'ENCODING'; PROMPT SUCCESS: ENCODING column added to A_SOURCE_FILE_CONFIG --============================================================================================================================= -- End of Script --============================================================================================================================= ``` **Script Best Practices:** - Clear header with purpose and metadata - `SET SERVEROUTPUT ON` for debugging - Descriptive PROMPT messages - Verification queries after changes - Success confirmation message --- ### Rollback Script Template Always provide rollback capability: ```sql -- =================================================================== -- MARS-XXXX ROLLBACK SCRIPT: Brief Description -- =================================================================== -- Purpose: Rollback all changes from MARS-XXXX installation -- Author: Grzegorz Michalski -- Date: YYYY-MM-DD -- Dynamic spool file generation (using SYS_CONTEXT - no DBA privileges required) -- IMPORTANT: Ensure log/ directory exists before SPOOL (use host mkdir) host mkdir log 2>nul var filename VARCHAR2(100) BEGIN :filename := 'log/ROLLBACK_MARS_XXXX_' || SYS_CONTEXT('USERENV', 'CON_NAME') || '_' || TO_CHAR(SYSDATE,'YYYYMMDD_HH24MISS') || '.log'; END; / column filename new_value _filename select :filename filename from dual; spool &_filename SET ECHO OFF SET TIMING ON SET SERVEROUTPUT ON SIZE UNLIMITED SET PAUSE OFF PROMPT ========================================================================= PROMPT MARS-XXXX: Rollback Package PROMPT ========================================================================= 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 ACCEPT continue CHAR PROMPT 'Type YES to continue with rollback, 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, 'Rollback aborted by user'); END IF; END; / WHENEVER SQLERROR CONTINUE -- Execute rollback scripts in REVERSE order @@92_MARS_XXXX_rollback_step2.sql @@91_MARS_XXXX_rollback_step1.sql PROMPT PROMPT ========================================================================= PROMPT MARS-XXXX Rollback - COMPLETED PROMPT ========================================================================= spool off ``` **Rollback Principles:** - Execute scripts in **REVERSE order** (92, 91, not 91, 92) - Undo changes from newest to oldest - Restore previous package versions - Remove added columns/tables - 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 Every MARS package should track package versions using the universal tracking script: **Recommended Approach: Universal Tracking Script** ```sql -- =================================================================== -- Simple Package Version Tracking Script -- =================================================================== -- Purpose: Track specified Oracle package versions -- Author: Grzegorz Michalski -- Date: 2025-11-26 -- Version: 3.1.0 - List-Based Edition -- -- USAGE: -- 1. Edit package list below (add/remove packages as needed) -- 2. Include in your install/rollback script: @@track_package_versions.sql -- =================================================================== SET SERVEROUTPUT ON; DECLARE TYPE t_package_rec IS RECORD ( owner VARCHAR2(50), package_name VARCHAR2(50), version VARCHAR2(50) ); TYPE t_packages IS TABLE OF t_package_rec; TYPE t_string_array IS TABLE OF VARCHAR2(100); -- =================================================================== -- PACKAGE LIST - Edit this array to specify packages to track -- =================================================================== -- Add or remove entries as needed for your MARS issue -- Format: 'SCHEMA.PACKAGE_NAME' -- =================================================================== vPackageList t_string_array := t_string_array( 'CT_MRDS.FILE_MANAGER', 'ODS.FILE_MANAGER_ODS' ); -- =================================================================== vPackages t_packages := t_packages(); vVersion VARCHAR2(50); vCount NUMBER := 0; vOwner VARCHAR2(50); vPackageName VARCHAR2(50); vDotPos NUMBER; BEGIN DBMS_OUTPUT.PUT_LINE('========================================'); DBMS_OUTPUT.PUT_LINE('Package Version Tracking'); DBMS_OUTPUT.PUT_LINE('========================================'); -- Process each package in the list FOR i IN 1..vPackageList.COUNT LOOP vDotPos := INSTR(vPackageList(i), '.'); IF vDotPos > 0 THEN vOwner := SUBSTR(vPackageList(i), 1, vDotPos - 1); vPackageName := SUBSTR(vPackageList(i), vDotPos + 1); -- Get package version BEGIN EXECUTE IMMEDIATE 'SELECT ' || vOwner || '.' || vPackageName || '.GET_VERSION() FROM DUAL' INTO vVersion; vPackages.EXTEND; vPackages(vPackages.COUNT).owner := vOwner; vPackages(vPackages.COUNT).package_name := vPackageName; vPackages(vPackages.COUNT).version := vVersion; -- Track in ENV_MANAGER BEGIN CT_MRDS.ENV_MANAGER.TRACK_PACKAGE_VERSION( pPackageOwner => vOwner, pPackageName => vPackageName, pPackageVersion => vVersion, pPackageBuildDate => TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'), pPackageAuthor => 'Grzegorz Michalski' ); vCount := vCount + 1; EXCEPTION WHEN OTHERS THEN NULL; -- Continue even if tracking fails END; EXCEPTION WHEN OTHERS THEN NULL; -- Skip packages that fail END; END IF; END LOOP; -- Display results IF vPackages.COUNT > 0 THEN DBMS_OUTPUT.PUT_LINE('Packages tracked: ' || vCount || ' of ' || vPackages.COUNT); DBMS_OUTPUT.PUT_LINE(''); FOR i IN 1..vPackages.COUNT LOOP DBMS_OUTPUT.PUT_LINE(vPackages(i).owner || '.' || vPackages(i).package_name || ' = ' || vPackages(i).version); END LOOP; ELSE DBMS_OUTPUT.PUT_LINE('No packages found in list'); END IF; DBMS_OUTPUT.PUT_LINE('========================================'); END; / ``` **Key Benefits:** - **List-Based**: Simply edit the `vPackageList` array to add/remove packages - **Automatic Version Detection**: Calls `GET_VERSION()` for each package - **Error Tolerant**: Continues even if individual packages fail - **Summary Output**: Shows which packages were successfully tracked - **Reusable**: Same script can be used across all MARS packages --- ### Package Verification Script Every MARS package should include a universal verification script to check all tracked packages for untracked changes: **Recommended: `verify_packages_version.sql`** ```sql -- =================================================================== -- Universal Package Version Verification Script -- =================================================================== -- Purpose: Verify all tracked Oracle packages for code changes -- Author: Grzegorz Michalski -- Date: 2025-11-25 -- Version: 1.0.0 -- -- USAGE: -- Include at the end of install/rollback scripts: @@verify_packages_version.sql -- -- OUTPUT: -- - List of all tracked packages with their current status -- - OK: Package has not changed since last tracking -- - WARNING: Package code changed without version update -- =================================================================== SET LINESIZE 200 SET PAGESIZE 1000 SET FEEDBACK OFF PROMPT PROMPT ======================================== PROMPT Package Version Verification PROMPT ======================================== PROMPT COLUMN PACKAGE_OWNER FORMAT A15 COLUMN PACKAGE_NAME FORMAT A20 COLUMN VERSION FORMAT A10 COLUMN STATUS FORMAT A80 SELECT PACKAGE_OWNER, PACKAGE_NAME, PACKAGE_VERSION AS VERSION, CT_MRDS.ENV_MANAGER.CHECK_PACKAGE_CHANGES(PACKAGE_OWNER, PACKAGE_NAME) AS STATUS FROM ( SELECT PACKAGE_OWNER, PACKAGE_NAME, PACKAGE_VERSION, ROW_NUMBER() OVER (PARTITION BY PACKAGE_OWNER, PACKAGE_NAME ORDER BY TRACKING_DATE DESC) AS RN FROM CT_MRDS.A_PACKAGE_VERSION_TRACKING ) WHERE RN = 1 ORDER BY PACKAGE_OWNER, PACKAGE_NAME; PROMPT PROMPT ======================================== PROMPT Verification Complete PROMPT ======================================== PROMPT PROMPT Legend: PROMPT OK - Package has not changed since last tracking PROMPT WARNING - Package code changed without version update PROMPT PROMPT For detailed hash information, use: PROMPT SELECT ENV_MANAGER.GET_PACKAGE_HASH_INFO('OWNER', 'PACKAGE') FROM DUAL; PROMPT ======================================== SET FEEDBACK ON ``` **Key Features:** - **Universal**: Checks ALL packages in A_PACKAGE_VERSION_TRACKING table - **Latest Version**: Uses ROW_NUMBER() to get most recent tracking record for each package - **Status Display**: Shows OK or WARNING for each package - **Formatted Output**: Clean, readable table format with column alignment - **Reusable**: Same script works for all MARS packages without modification - **Legend**: Includes helpful legend explaining OK vs WARNING status **Usage in Master Scripts:** ```sql PROMPT PROMPT === Step 3: Verify all tracked packages === @@verify_packages_version.sql ``` **Benefits over Package-Specific Verification:** - No need to edit script for each MARS package - Automatically detects all tracked packages - Consistent verification across all installations - Easier to maintain (single script for all packages) --- ### Package README Template Every MARS package MUST include README.md: ```markdown # MARS-XXXX: Brief Description ## Overview Detailed description of what this package does and why it's needed. ## Contents - `install_marsXXXX.sql` - Master installation script with SPOOL logging - `rollback_marsXXXX.sql` - Master rollback script - `01_MARS_XXXX_*.sql` - Individual installation scripts - `91_MARS_XXXX_*.sql` - Individual rollback scripts ## Prerequisites - Oracle Database 23ai - Required package versions (e.g., ENV_MANAGER v3.1.0+) - Schema privileges needed ## Installation ### Option 1: Master Script (Recommended) ```powershell # IMPORTANT: Execute as ADMIN user for proper privilege management Get-Content "MARS_Packages/REL01/MARS-XXXX/install_marsXXXX.sql" | sql "ADMIN/password@service" # Log file created: INSTALL_MARS_XXXX__.log ``` ### Option 2: Individual Scripts ```powershell # IMPORTANT: Execute as ADMIN user Get-Content "01_MARS_XXXX_*.sql" | sql "ADMIN/password@service" Get-Content "02_MARS_XXXX_*.sql" | sql "ADMIN/password@service" # ... etc ``` ## Verification ```sql -- Verify package versions SELECT PACKAGE_NAME.GET_VERSION() FROM DUAL; -- Check for errors (ADMIN user checks specific schema) SELECT * FROM ALL_ERRORS WHERE OWNER = 'CT_MRDS' -- Replace with target schema AND NAME = 'PACKAGE_NAME'; ``` ## Rollback ```powershell # IMPORTANT: Execute as ADMIN user Get-Content "MARS_Packages/REL01/MARS-XXXX/rollback_marsXXXX.sql" | sql "ADMIN/password@service" ``` ## Expected Changes - Package X: v1.0.0 → v1.1.0 - Table Y: Added COLUMN_Z - Configuration: Updated DEFAULT_VALUE ## Testing Describe how to test the changes after installation. ## Known Issues List any known limitations or issues. ## Related - MARS-YYYY: Related package - Confluence: Link to detailed documentation ``` --- ### MARS Package Checklist Before creating a MARS package, ensure: - [ ] **Directory Structure**: Created `log/` and `mock_data/` subdirectories (if needed) - [ ] **.gitignore file**: Created with standardized exclusions (confluence/, log/, test/, mock_data/) - [ ] **Author field**: All scripts have `Author: Grzegorz Michalski` - [ ] **ADMIN user**: All installation instructions specify ADMIN user connection - [ ] All individual scripts numbered correctly (01-89, 91-99) - [ ] Master install script includes SPOOL logging to `log/` directory - [ ] Master rollback script includes SPOOL logging to `log/` directory - [ ] SPOOL filenames use dynamic PDB name and timestamp with `log/` prefix - [ ] **ACCEPT validation**: Master scripts require explicit "YES" confirmation - [ ] **quit; command**: Master scripts end with quit; for clean exit - [ ] All scripts have proper headers with metadata - [ ] Version tracking scripts included (in test/ subfolder) - [ ] Verification scripts confirm changes (in test/ subfolder) - [ ] README.md documents installation process - [ ] Rollback scripts reverse all changes - [ ] Rollback includes verification step (@@test/verify_packages_version.sql) - [ ] **rollback_version/ folder**: Contains backup of objects before changes (if modifying packages) - [ ] **new_version/ folder**: Contains updated objects after changes (if modifying packages) - [ ] **test/ folder**: All test files and verification scripts organized in subfolder - [ ] **log/ folder**: SPOOL log files automatically created by master scripts - [ ] **mock_data/ folder**: Mock data files organized (if applicable) - [ ] Tested in DEV environment - [ ] Log files reviewed for errors (in log/ subdirectory) - [ ] **Source repository updated**: Changed packages copied to `MARS_Packages/mrds_elt-dev-database/mrds_elt-dev-database/database/` - [ ] Git commit with descriptive message (log/, mock_data/ excluded via .gitignore) --- ### Example 1: Complete MARS-1046 Package (Package Modification) Real-world example from MARS-1046 (ISO 8601 Date Format Fix): **Structure:** ``` MARS_Packages/REL01/MARS-1046/ ├── install_mars1046.sql # Master with SPOOL, ACCEPT, quit; ├── rollback_mars1046.sql # Master rollback with ACCEPT, quit; ├── 01_MARS_1046_install_CT_MRDS_FILE_MANAGER_SPEC.sql ├── 02_MARS_1046_install_CT_MRDS_FILE_MANAGER_BODY.sql ├── 91_MARS_1046_rollback_CT_MRDS_FILE_MANAGER_BODY.sql ├── 92_MARS_1046_rollback_CT_MRDS_FILE_MANAGER_SPEC.sql ├── track_package_versions.sql # Version tracking ├── verify_packages_version.sql # Package verification ├── README.md # Comprehensive documentation ├── rollback_version/ # v3.3.0 backup for rollback │ ├── FILE_MANAGER.pkg │ └── FILE_MANAGER.pkb ├── new_version/ # v3.3.1 updated packages │ ├── FILE_MANAGER.pkg │ └── FILE_MANAGER.pkb ├── test/ # All test artifacts │ ├── test_mars1046.sql # Unit tests (7/7 passed) │ ├── TEST_RESULTS.md # Test documentation │ ├── iso8601_test_data.csv # Test data (full format) │ ├── iso8601_test_data_simple.csv # Test data (simple format) │ ├── create_iso8601_test_template.sql # Template table creation │ ├── configure_iso8601_test.sql # Date format configuration │ ├── process_iso8601_test.sql # E2E test │ └── INSTALL_MARS_1046_*.log # Log files (3 iterations) └── log/ # Optional log storage ``` **Key Features:** - SPOOL logging: `INSTALL_MARS_1046__.log` - ACCEPT validation: Requires explicit "YES" to proceed (both install & rollback) - quit; command: Clean SQLcl exit after completion - Version folders: rollback_version/ (v3.3.0) and new_version/ (v3.3.1) - Test subfolder: All test files organized separately - 4-step workflow: Install packages → Track version → Verify packages → quit - Full rollback: Restore to previous version with verification - Comprehensive README: Problem, solution, testing, verification - Track & verify scripts: Universal scripts work for any package --- ### Example 2: Complete MARS-1049-ADHOC Package (Configuration Change) Real-world example from MARS-1049-ADHOC (CSDB External Tables): **Structure:** ``` MARS_Packages/REL01/MARS-1049-ADHOC/ ├── install_mars1049_adhoc.sql # Master with SPOOL ├── 00_MARS_1049_ADHOC_update_encoding.sql # Update config ├── 01_MARS_1049_ADHOC_drop_external_tables.sql # Drop tables ├── 02_MARS_1049_ADHOC_recreate_external_tables.sql # Recreate with encoding ├── 03_MARS_1049_ADHOC_verify_external_tables.sql # Verify creation └── README.md # Documentation ``` **Key Features:** - SPOOL logging: `INSTALL_MARS_1049_ADHOC__.log` - Numbered sequence: 00 → 01 → 02 → 03 - No rollback (external tables are metadata-only) - No version folders (no package modifications) - Verification included - Clear README with installation options --- ## Post-Installation File Organization ### Organizing Test Files and Logs After successful installation and verification, organize files for clean Git commit: **Step 1: Create test/ subfolder** ```powershell # Create test directory if it doesn't exist New-Item -ItemType Directory -Force -Path "test" | Out-Null ``` **Step 2: Move test-related files** ```powershell # Move test scripts and data Move-Item -Path "test_*.sql" -Destination "test" -Force Move-Item -Path "*_test_*.csv" -Destination "test" -Force Move-Item -Path "TEST_RESULTS.md" -Destination "test" -Force ``` **Step 3: Move log files** ```powershell # Option 1: Move to test/ subfolder Move-Item -Path "*.log" -Destination "test" -Force # Option 2: Create dedicated log/ subfolder New-Item -ItemType Directory -Force -Path "log" | Out-Null Move-Item -Path "*.log" -Destination "log" -Force ``` **Step 4: Verify clean structure** ```powershell # Check root directory - should only have deployment scripts and README Get-ChildItem | Where-Object { $_.Name -notmatch "^(01|02|91|92|install|rollback|README|rollback_version|new_version|test|log)" } # Expected: No output (all non-deployment files moved) ``` **Final MARS Package Structure:** ``` MARS_Packages/REL01/MARS-XXXX/ ├── install_marsXXXX.sql # Master installation ├── rollback_marsXXXX.sql # Master rollback ├── 01_MARS_XXXX_*.sql # Installation scripts ├── 02_MARS_XXXX_*.sql ├── 91_MARS_XXXX_*.sql # Rollback scripts ├── 92_MARS_XXXX_*.sql ├── track_package_versions.sql ├── verify_packages_version.sql ├── README.md # Documentation ├── rollback_version/ # Backup packages ├── new_version/ # Updated packages └── test/ # ALL test artifacts ├── test_marsXXXX.sql ├── TEST_RESULTS.md ├── *.csv (test data) ``` **Benefits:** - **Clean Git commits**: Only deployment-relevant files in root - **Easy testing**: All test materials in one place - **Reproducibility**: Test setup can be recreated from test/ folder - **Documentation**: Log files preserved for troubleshooting - **Professional**: Organized structure for code review --- ## Best Practices ### 1. Always Update Version Before Deployment **DO:** ```sql -- Update version first, then deploy PACKAGE_VERSION := '3.3.0'; -- Updated PACKAGE_BUILD_DATE := '2025-10-22 21:00:00'; -- Updated VERSION_HISTORY := '3.3.0 (2025-10-22): New feature...' || CHR(13)||CHR(10) || ... ``` **DON'T:** ```sql -- Deploy changes without updating version -- This triggers "untracked changes" warning ``` --- ### 2. Use Descriptive Version History **DO:** ```sql '3.3.0 (2025-10-22): Added EXPORT_HISTORICAL_DATA procedure for Parquet exports with Hive partitioning' ``` **DON'T:** ```sql '3.3.0 (2025-10-22): Updates' -- Too vague ``` --- ### 3. Deploy SPEC Before BODY **Correct Order:** 1. Deploy PACKAGE.pkg (specification) 2. Deploy PACKAGE.pkb (body) 3. Track version **Rationale:** BODY depends on SPEC, deploying SPEC first ensures clean compilation. --- ### 4. Test Before Production Deployment 1. Deploy to DEV environment first 2. Run unit tests 3. Verify functionality 4. Check for performance issues 5. Deploy to PROD only after validation --- ### 5. Document Breaking Changes For MAJOR version increments, always document: - What changed - Why it changed - Migration path for existing code - Example of old vs new usage --- ### 6. Use Batch Deployment Scripts For multiple packages, create deployment script: ```powershell # deploy_all_packages.ps1 $packages = @('ENV_MANAGER', 'FILE_MANAGER', 'DATA_EXPORTER', 'FILE_ARCHIVER') foreach ($pkg in $packages) { Write-Host "Deploying $pkg..." Get-Content "database\CT_MRDS\packages\${pkg}.pkg" | sql "CT_MRDS/password@service" Get-Content "database\CT_MRDS\packages\${pkg}.pkb" | sql "CT_MRDS/password@service" } # Track all packages Get-Content "database\scripts\track_all_packages.sql" | sql "CT_MRDS/password@service" ``` --- ### 7. Regular Change Detection Audits Run periodic checks to catch untracked modifications: ```sql -- Check all packages for changes @database/scripts/check_package_changes_all.sql ``` Schedule this as part of weekly code review process. --- ## Quick Reference ### Essential Commands | Task | Command | |------|---------| | **Check current version** | `SELECT PACKAGE_NAME.GET_VERSION() FROM DUAL;` | | **Check build info** | `SELECT PACKAGE_NAME.GET_BUILD_INFO() FROM DUAL;` | | **Check for changes** | `SELECT ENV_MANAGER.CHECK_PACKAGE_CHANGES('OWNER', 'PACKAGE') FROM DUAL;` | | **Get hash info** | `SELECT ENV_MANAGER.GET_PACKAGE_HASH_INFO('OWNER', 'PACKAGE') FROM DUAL;` | | **Track version** | `CALL ENV_MANAGER.TRACK_PACKAGE_VERSION('OWNER', 'PKG', 'VER', 'DATE', 'AUTHOR');` | | **Check errors** | `SELECT * FROM ALL_ERRORS WHERE OWNER = 'CT_MRDS' AND NAME = 'PACKAGE_NAME';` | | **View tracking history** | `SELECT * FROM A_PACKAGE_VERSION_TRACKING WHERE PACKAGE_NAME = 'X' ORDER BY TRACKING_DATE DESC;` | --- ### Version Number Examples | Current | Bug Fix | Feature | Breaking | |---------|---------|---------|----------| | 1.0.0 | 1.0.1 | 1.1.0 | 2.0.0 | | 2.5.3 | 2.5.4 | 2.6.0 | 3.0.0 | | 3.2.0 | 3.2.1 | 3.3.0 | 4.0.0 | --- ### Deployment Checklist - [ ] Check current package status (`CHECK_PACKAGE_CHANGES`) - [ ] Make code changes in local files - [ ] Update `PACKAGE_VERSION` constant (increment appropriately) - [ ] Update `PACKAGE_BUILD_DATE` constant (current timestamp) - [ ] Add entry to `VERSION_HISTORY` constant - [ ] Deploy SPEC file - [ ] Deploy BODY file - [ ] Check for compilation errors (`ALL_ERRORS` with OWNER filter when using ADMIN) - [ ] Track new version (`TRACK_PACKAGE_VERSION`) - [ ] Verify deployment (`GET_BUILD_INFO`, `CHECK_PACKAGE_CHANGES`) - [ ] **Update source repository** - Copy updated packages to `MARS_Packages/mrds_elt-dev-database/mrds_elt-dev-database/database/` - [ ] Update documentation (if API changed) - [ ] Commit changes to Git - [ ] Notify team (if breaking changes) --- ## Related Documentation - [Package Versioning Guide](PACKAGE_VERSIONING_README.md) - Overview of versioning system - [Package Hash Tracking Guide](PACKAGE_HASH_TRACKING_GUIDE.md) - Technical details of hash system - [Package Hash Quick Guide](PACKAGE_HASH_QUICK_GUIDE.md) - Quick reference for hash commands - [Developer Quick Guide](../database/DEVELOPER_QUICK_GUIDE.md) - General development guidelines --- ## Support For questions or issues with the deployment process: 1. Check [Troubleshooting](#troubleshooting) section above 2. Review package documentation: `SELECT GET_PACKAGE_DOCUMENTATION('PACKAGE_NAME', 'SCHEMA') FROM DUAL;` 3. Check process logs: `SELECT * FROM A_PROCESS_LOG WHERE LOG_TIMESTAMP > SYSDATE - 1 ORDER BY LOG_TIMESTAMP DESC;` 4. Contact database team lead --- **Last Updated:** 2025-10-22 **Document Version:** 1.0.0 **System Version:** ENV_MANAGER 3.1.0+