fix(oracle): calea DMPDIR devine parametru; sqlnet.ora ajunge unde e citit

Gasite la instalarea de productie VADECO (Oracle 21c XE, Windows Server 2019).

1. Pe serverul VADECO procesul Oracle nu poate atinge nicio cale de pe C:,
   nici macar C:\Windows\Temp, desi ACL-urile sunt corecte si serviciul ruleaza
   ca NT SERVICE\OracleServiceXE. D: merge cu exact acelasi grant. Calea DMP
   era insa hardcodata "C:\DMPDIR" in 01, 02, 05, 06 si in biblioteca, deci
   instalarea nu se putea muta. Acum e parametrul -DmpDir, expus ca /dmpdest:
   in FAZA1.cmd si FAZA2.cmd si transmis tuturor pasilor.

   Cel mai perfid era pasul 02: recrea DIRECTORY DMPDIR pe 'C:\DMPDIR' peste
   valoarea pusa de 01. Chiar cu restul instalarii mutata, SYS.NEWSCHEMA ar fi
   cautat FIRMANOUA.dmp in alta parte, iar adaugarea unei firme noi ar fi picat
   peste luni, fara legatura vizibila cu instalarea.

2. New-OracleDirectory compara doar siruri de caractere: verifica ce scrie in
   dba_directories, nu daca baza chiar poate scrie acolo. Acum face un
   UTL_FILE round-trip si esueaza pe loc, cu explicatia cauzei. Inainte,
   directorul inutilizabil trecea drept bun si importul cadea abia in impdp cu
   ORA-29283, la zeci de linii distanta. Valoarea de retur nici nu era
   verificata in 01/03/06 - de aici si "True" ratacit in log.

3. Instalarea ROAClient seteaza TNS_ADMIN de masina spre instantclient-ul ei.
   Serviciul Oracle mosteneste variabilele de masina, deci citea sqlnet.ora de
   acolo - unde nu exista niciunul - si nu din Oracle Home, unde il scria pasul
   01. Compatibilitatea pentru clienti vechi nu se aplica, iar statiile ar fi
   primit ORA-28040 cu fisierul scris corect, in locul gresit. Pasul 01 scrie
   acum sqlnet.ora si in TNS_ADMIN cand difera.

4. Pasul 05 lega schemele de DMP-uri cu "^$schema[_\.]", deci schema DANUBE
   putea primi DANUBE_20200914.dmp - datele altei firme, fara avertisment.
   Numele exact are acum intaietate, prefixul se accepta doar daca e unic, iar
   ambiguitatea se raporteaza.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SzF1hf4aFS1tmJWpPMiwGp
This commit is contained in:
Marius
2026-08-25 21:18:43 +03:00
parent 5a746990ce
commit ec66377e0f
9 changed files with 2787 additions and 2673 deletions

3
.gitignore vendored
View File

@@ -16,3 +16,6 @@ input/
# Secrets - real cPanel DNS hook config holds an API token (template is committed)
cpanel-dns.config.json
**/cpanel-dns.config.json
# Cygwin/Git-Bash crash dumps
*.stackdump

View File

@@ -34,6 +34,11 @@ REM /parolavechi:<parola> parola SYS de pe serverul vechi
REM /licente:<fisier.sql> licente dintr-un fisier, in loc de retea
REM /roaupdate:<cale> radacina oglinzii (implicit D:\ROAUPDATE)
REM /export:<cale> director export (implicit D:\ROA\EXPORT_ORADMP)
REM /dmpdest:<cale> de unde citeste baza DMP-urile (implicit C:\DMPDIR)
REM Pe unele masini procesul Oracle nu ajunge la C:\ deloc
REM (ORA-29283 la orice cale de pe C:, inclusiv C:\Windows\Temp,
REM desi ACL-urile sunt corecte). Atunci pune-l pe discul unde
REM e Oracle Home: /dmpdest:D:\DMPDIR
REM /faralicente sari peste pasul 09
REM /faraiis sari peste pasul 10
REM /farabackup sari peste pasul 11
@@ -89,6 +94,7 @@ if /i "!OPT!"=="/parolavechi" set "PAROLAVECHI=!VAL!"
if /i "!OPT!"=="/licente" set "LICENTEFIS=!VAL!"
if /i "!OPT!"=="/roaupdate" set "ROAUPDATE=!VAL!"
if /i "!OPT!"=="/export" set "EXPORTDIR=!VAL!"
if /i "!OPT!"=="/dmpdest" set "DMPDEST=!VAL!"
shift
goto :parsare
@@ -102,6 +108,7 @@ echo.
echo Kit: %KIT%
echo Id client: %IDCLIENT%
echo SMTP: %SMTP%
echo DMP: %DMPDEST%
echo ROAUPDATE: %ROAUPDATE%
echo Export: %EXPORTDIR%
if not "%VECHI%"=="" echo Server vechi: %VECHI% / %SERVICIUVECHI%
@@ -139,7 +146,7 @@ REM [2/9] 01 - baza si userul
REM ---------------------------------------------------------------------------
echo.
echo [2/9] 01-setup-database.ps1
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\01-setup-database.ps1"
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\01-setup-database.ps1" -DmpDir "%DMPDEST%"
if errorlevel 1 goto :esec_01
REM ---------------------------------------------------------------------------
@@ -147,7 +154,7 @@ REM [3/9] 02 - obiectele SYS
REM ---------------------------------------------------------------------------
echo.
echo [3/9] 02-create-sys-objects.ps1
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\02-create-sys-objects.ps1"
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\02-create-sys-objects.ps1" -DmpDir "%DMPDEST%"
if errorlevel 1 goto :esec_02
REM ---------------------------------------------------------------------------
@@ -155,7 +162,7 @@ REM [4/9] 03 - CONTAFIN_ORACLE
REM ---------------------------------------------------------------------------
echo.
echo [4/9] 03-import-contafin.ps1
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\03-import-contafin.ps1"
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\03-import-contafin.ps1" -DmpDir "%DMPDEST%"
set RC=!ERRORLEVEL!
REM Codul 5 e normal: Data Pump raporteaza "completed with errors" pentru
REM ORA-31684 (userul e creat deja de pasul 01) si ORA-39082 (warning-uri de

View File

@@ -28,6 +28,8 @@ REM /smtp:<server> server SMTP (implicit mail.romfast.ro)
REM /roaupdate:<cale> radacina oglinzii (implicit D:\ROAUPDATE)
REM /export:<cale> director export (implicit D:\ROA\EXPORT_ORADMP)
REM /dmp:<cale> de unde se copiaza DMP-urile (implicit <kit>\DMPDIR)
REM /dmpdest:<cale> de unde le citeste baza (implicit C:\DMPDIR)
REM Trebuie sa fie aceeasi valoare ca la FAZA1.
REM /faraschema nu regenera schema.txt
REM
REM Exemple:
@@ -72,6 +74,7 @@ if /i "!OPT!"=="/smtp" set "SMTP=!VAL!"
if /i "!OPT!"=="/roaupdate" set "ROAUPDATE=!VAL!"
if /i "!OPT!"=="/export" set "EXPORTDIR=!VAL!"
if /i "!OPT!"=="/dmp" set "DMPSURSA=!VAL!"
if /i "!OPT!"=="/dmpdest" set "DMPDEST=!VAL!"
shift
goto :parsare
@@ -150,12 +153,12 @@ if errorlevel 1 goto :esec_drop
echo.
echo 01-setup-database.ps1 (recreare user)
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\01-setup-database.ps1"
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\01-setup-database.ps1" -DmpDir "%DMPDEST%"
if errorlevel 1 goto :esec_01
echo.
echo 03-import-contafin.ps1
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\03-import-contafin.ps1"
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\03-import-contafin.ps1" -DmpDir "%DMPDEST%"
set RC=!ERRORLEVEL!
if "!RC!"=="0" goto :dupa_03
if "!RC!"=="5" (
@@ -177,7 +180,7 @@ REM [3/6] Schemele de firma
REM ---------------------------------------------------------------------------
echo.
echo [3/6] 05-import-companies.ps1
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\05-import-companies.ps1"
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\05-import-companies.ps1" -DumpDirectory "%DMPDEST%" -DmpDir "%DMPDEST%"
if errorlevel 1 goto :esec_05
REM ---------------------------------------------------------------------------

View File

@@ -87,7 +87,13 @@ param(
[switch]$SkipSqlnetConfig,
[Parameter(Mandatory = $false)]
[switch]$ResetSystemPassword
[switch]$ResetSystemPassword,
# Calea fizica a directorului Oracle DMPDIR. Aceeasi valoare trebuie data
# tuturor pasilor care ating DMPDIR (01, 02, 03, 05, 06), altfel ultimul
# care ruleaza repozitioneaza obiectul si ceilalti citesc din alta parte.
[Parameter(Mandatory = $false)]
[string]$DmpDir = "C:\DMPDIR"
)
$ErrorActionPreference = 'Stop'
@@ -355,6 +361,31 @@ NAMES.DIRECTORY_PATH = (TNSNAMES, EZCONNECT)
Write-LogSuccess "sqlnet.ora configured at $sqlnetOra"
Write-Log "Old client compatibility enabled (SQLNET.ALLOWED_LOGON_VERSION=8)"
# Daca exista TNS_ADMIN la nivel de masina, ACELA castiga - si pentru
# clienti, si pentru serviciul Oracle, care mosteneste variabilele de
# masina. Instalarea ROAClient il pune sa arate spre instantclient-ul
# ei (D:\ROA\instantclient_11_2_0_2), unde de obicei nu exista niciun
# sqlnet.ora: atunci serverul cade pe valorile implicite, adica
# ALLOWED_LOGON_VERSION_SERVER=12, si clientii vechi primesc ORA-28040
# desi fisierul de mai sus a fost scris corect. Scriem acelasi continut
# si acolo, altfel toata configurarea de compatibilitate e degeaba.
$tnsAdmin = [Environment]::GetEnvironmentVariable('TNS_ADMIN', 'Machine')
if ($tnsAdmin) {
$tnsAdminFull = [IO.Path]::GetFullPath($tnsAdmin.TrimEnd('\'))
if ($tnsAdminFull -ne [IO.Path]::GetFullPath($networkAdmin.TrimEnd('\'))) {
Write-LogWarning "TNS_ADMIN de masina arata spre $tnsAdminFull - acolo se citeste sqlnet.ora, nu din Oracle Home."
if (-not (Test-Path $tnsAdminFull)) {
New-Item -ItemType Directory -Path $tnsAdminFull -Force | Out-Null
}
$tnsSqlnet = Join-Path $tnsAdminFull "sqlnet.ora"
if (Test-Path $tnsSqlnet) {
Copy-Item $tnsSqlnet "$tnsSqlnet.bak_$(Get-Date -Format 'yyyyMMdd_HHmmss')" -Force
}
Set-Content -Path $tnsSqlnet -Value $sqlnetContent -Encoding ASCII
Write-LogSuccess "sqlnet.ora scris si in TNS_ADMIN: $tnsSqlnet"
}
}
# Restart listener to apply changes
Write-Log "Restarting listener to apply sqlnet.ora changes..."
$lsnrctl = Join-Path $oraHome "bin\lsnrctl.exe"
@@ -536,11 +567,12 @@ EXIT;
# Step 9: Create DMPDIR directory for Data Pump
Write-LogSection "Creating Data Pump Directory"
$dmpDir = "C:\DMPDIR"
New-OracleDirectory -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -DirectoryName "DMPDIR" -DirectoryPath $dmpDir
if (-not (New-OracleDirectory -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -DirectoryName "DMPDIR" -DirectoryPath $DmpDir)) {
throw "Directorul Data Pump DMPDIR ($DmpDir) nu e utilizabil de catre baza. Vezi mesajele de mai sus."
}
Write-LogSuccess "Data Pump directory DMPDIR created: $dmpDir"
Write-LogSuccess "Data Pump directory DMPDIR created: $DmpDir"
# Step 10: Reset passwords with 10G verifier (required for old client auth)
# After sqlnet.ora is configured, passwords must be reset to generate 10G hash

View File

@@ -1,432 +1,438 @@
#Requires -Version 5.1
<#
.SYNOPSIS
Install SYS objects for ROA Oracle.
.DESCRIPTION
Executes SQL scripts to create required SYS-owned objects including:
- AUTH_PACK package
- AUTH_DETALII, AUTH_SERII tables
- NEWSCHEMA, NEWSCHEMAPOST procedures
- NEWSCHEMAPROGRESS function
- PACK_UPDATE, PACK_UTILS packages
- Public synonyms and grants
.PARAMETER OracleHome
Oracle home directory. If not specified, auto-detects.
.PARAMETER ServiceName
Database service name. Default: XEPDB1
.PARAMETER SystemPassword
SYSTEM/SYS user password. Default: romfastsoft
.PARAMETER SqlScriptsDir
Directory containing SYS SQL scripts. Default: ..\sql
.EXAMPLE
.\02-create-sys-objects.ps1
.EXAMPLE
.\02-create-sys-objects.ps1 -ServiceName "ROA" -SystemPassword "mypassword"
.NOTES
File Name : 02-create-sys-objects.ps1
Prerequisite : Run 01-setup-database.ps1 first
Copyright 2024 : ROMFAST
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string]$OracleHome,
[Parameter(Mandatory = $false)]
[string]$ServiceName = "XEPDB1",
[Parameter(Mandatory = $false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory = $false)]
[string]$SqlScriptsDir
)
$ErrorActionPreference = 'Stop'
# Source library functions
. "$PSScriptRoot\lib\logging-functions.ps1"
. "$PSScriptRoot\lib\oracle-functions.ps1"
# Initialize logging
$logPath = Join-Path $PSScriptRoot "..\logs\02-create-sys-objects_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
Initialize-LogFile -LogPath $logPath -ScriptName "02-create-sys-objects.ps1"
try {
Write-LogSection "Installing SYS Objects"
# Validate Oracle installation
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-LogSuccess "Oracle Home: $oraHome"
# Test connection
Write-Log "Testing database connection..."
if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYS" -Password $SystemPassword -AsSysdba)) {
throw "Cannot connect to database as SYS. Please verify ServiceName and SystemPassword."
}
Write-LogSuccess "Database connection successful"
# Determine SQL scripts directory
if (-not $SqlScriptsDir) {
$SqlScriptsDir = Join-Path $PSScriptRoot "..\sql"
}
$sysObjectsScript = Join-Path $SqlScriptsDir "sys-objects.sql"
if (-not (Test-Path -Path $sysObjectsScript)) {
Write-LogWarning "sys-objects.sql not found at $sysObjectsScript"
Write-Log "Creating sys-objects.sql from embedded SQL..."
# Create the sql directory if it doesn't exist
if (-not (Test-Path -Path $SqlScriptsDir)) {
New-Item -ItemType Directory -Path $SqlScriptsDir -Force | Out-Null
}
# Embedded SYS objects SQL - minimal set for ROA
$sysObjectsSql = @"
-- sys-objects.sql
-- SYS objects required for ROA Oracle
-- Run as SYS with SYSDBA privilege
SET ECHO ON FEEDBACK ON VERIFY OFF SERVEROUTPUT ON
PROMPT
PROMPT =============================================
PROMPT Creating SYS objects for ROA
PROMPT =============================================
PROMPT
-- Create DMPDIR if not exists
PROMPT Creating directory DMPDIR...
CREATE OR REPLACE DIRECTORY DMPDIR AS 'C:\DMPDIR';
GRANT READ, WRITE ON DIRECTORY DMPDIR TO PUBLIC;
-- AUTH_DETALII table
PROMPT Creating table AUTH_DETALII...
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE SYS.AUTH_DETALII CASCADE CONSTRAINTS';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE TABLE SYS.AUTH_DETALII (
ID_DETALIU NUMBER NOT NULL,
ID_PROGRAM NUMBER NOT NULL,
CAMP_DETALIU VARCHAR2(100),
VAL_DETALIU VARCHAR2(500),
CONSTRAINT PK_AUTH_DETALII PRIMARY KEY (ID_DETALIU)
);
GRANT SELECT, INSERT, UPDATE, DELETE ON SYS.AUTH_DETALII TO PUBLIC;
CREATE PUBLIC SYNONYM AUTH_DETALII FOR SYS.AUTH_DETALII;
-- AUTH_SERII table
PROMPT Creating table AUTH_SERII...
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE SYS.AUTH_SERII CASCADE CONSTRAINTS';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE TABLE SYS.AUTH_SERII (
ID_PROGRAM NUMBER NOT NULL,
SERIE VARCHAR2(50),
NR_UTIL NUMBER,
DATA_VAL DATE,
CONSTRAINT PK_AUTH_SERII PRIMARY KEY (ID_PROGRAM)
);
GRANT SELECT, INSERT, UPDATE, DELETE ON SYS.AUTH_SERII TO PUBLIC;
CREATE PUBLIC SYNONYM AUTH_SERII FOR SYS.AUTH_SERII;
-- AUTH_PACK package specification
PROMPT Creating package AUTH_PACK...
CREATE OR REPLACE PACKAGE SYS.AUTH_PACK AS
FUNCTION selecteaza_serie(p_id_program NUMBER) RETURN VARCHAR2;
FUNCTION selecteaza_nr_util(p_id_program NUMBER) RETURN NUMBER;
FUNCTION selecteaza_data_val(p_id_program NUMBER) RETURN DATE;
PROCEDURE actualizeaza_serie(p_id_program NUMBER, p_serie VARCHAR2, p_nr_util NUMBER, p_data_val DATE);
END AUTH_PACK;
/
-- AUTH_PACK package body
CREATE OR REPLACE PACKAGE BODY SYS.AUTH_PACK AS
FUNCTION selecteaza_serie(p_id_program NUMBER) RETURN VARCHAR2 IS
v_serie VARCHAR2(50);
BEGIN
SELECT serie INTO v_serie FROM SYS.AUTH_SERII WHERE id_program = p_id_program;
RETURN v_serie;
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN NULL;
END;
FUNCTION selecteaza_nr_util(p_id_program NUMBER) RETURN NUMBER IS
v_nr_util NUMBER;
BEGIN
SELECT nr_util INTO v_nr_util FROM SYS.AUTH_SERII WHERE id_program = p_id_program;
RETURN v_nr_util;
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN NULL;
END;
FUNCTION selecteaza_data_val(p_id_program NUMBER) RETURN DATE IS
v_data_val DATE;
BEGIN
SELECT data_val INTO v_data_val FROM SYS.AUTH_SERII WHERE id_program = p_id_program;
RETURN v_data_val;
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN NULL;
END;
PROCEDURE actualizeaza_serie(p_id_program NUMBER, p_serie VARCHAR2, p_nr_util NUMBER, p_data_val DATE) IS
BEGIN
MERGE INTO SYS.AUTH_SERII t
USING (SELECT p_id_program AS id_program FROM dual) s
ON (t.id_program = s.id_program)
WHEN MATCHED THEN
UPDATE SET serie = p_serie, nr_util = p_nr_util, data_val = p_data_val
WHEN NOT MATCHED THEN
INSERT (id_program, serie, nr_util, data_val)
VALUES (p_id_program, p_serie, p_nr_util, p_data_val);
COMMIT;
END;
END AUTH_PACK;
/
GRANT EXECUTE ON SYS.AUTH_PACK TO PUBLIC;
CREATE OR REPLACE PUBLIC SYNONYM AUTH_PACK FOR SYS.AUTH_PACK;
-- VAUTH_SERII view
PROMPT Creating view VAUTH_SERII...
CREATE OR REPLACE VIEW SYS.VAUTH_SERII AS
SELECT a.id_program,
a.denumire AS nume,
auth_pack.selecteaza_serie(a.id_program) AS serie,
auth_pack.selecteaza_nr_util(a.id_program) AS nr_util,
auth_pack.selecteaza_data_val(a.id_program) AS data_val
FROM syn_nom_programe a
LEFT JOIN syn_def_programe b ON a.id_program = b.ide_program
WHERE b.sters = 0
AND b.instalat = 1;
GRANT SELECT ON SYS.VAUTH_SERII TO PUBLIC;
CREATE OR REPLACE PUBLIC SYNONYM VAUTH_SERII FOR SYS.VAUTH_SERII;
-- PACK_UPDATE package (minimal version)
PROMPT Creating package PACK_UPDATE...
CREATE OR REPLACE PACKAGE SYS.PACK_UPDATE AS
FUNCTION get_version RETURN VARCHAR2;
PROCEDURE execute_sql(p_sql VARCHAR2);
END PACK_UPDATE;
/
CREATE OR REPLACE PACKAGE BODY SYS.PACK_UPDATE AS
FUNCTION get_version RETURN VARCHAR2 IS
BEGIN
RETURN '1.0.0';
END;
PROCEDURE execute_sql(p_sql VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE p_sql;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;
END PACK_UPDATE;
/
GRANT EXECUTE ON SYS.PACK_UPDATE TO PUBLIC;
CREATE OR REPLACE PUBLIC SYNONYM PACK_UPDATE FOR SYS.PACK_UPDATE;
-- PACK_UTILS package (minimal version)
PROMPT Creating package PACK_UTILS...
CREATE OR REPLACE PACKAGE SYS.PACK_UTILS AS
FUNCTION get_db_version RETURN VARCHAR2;
FUNCTION get_instance_name RETURN VARCHAR2;
END PACK_UTILS;
/
CREATE OR REPLACE PACKAGE BODY SYS.PACK_UTILS AS
FUNCTION get_db_version RETURN VARCHAR2 IS
v_version VARCHAR2(100);
BEGIN
SELECT version_full INTO v_version FROM v`$instance;
RETURN v_version;
EXCEPTION
WHEN OTHERS THEN RETURN NULL;
END;
FUNCTION get_instance_name RETURN VARCHAR2 IS
v_instance VARCHAR2(100);
BEGIN
SELECT instance_name INTO v_instance FROM v`$instance;
RETURN v_instance;
EXCEPTION
WHEN OTHERS THEN RETURN NULL;
END;
END PACK_UTILS;
/
GRANT EXECUTE ON SYS.PACK_UTILS TO PUBLIC;
CREATE OR REPLACE PUBLIC SYNONYM PACK_UTILS FOR SYS.PACK_UTILS;
-- Grant UTL packages to PUBLIC
PROMPT Granting UTL packages...
GRANT EXECUTE ON UTL_FILE TO PUBLIC;
GRANT EXECUTE ON DBMS_LOCK TO PUBLIC;
-- Grant UTL packages to CONTAFIN_ORACLE specifically
GRANT EXECUTE ON UTL_INADDR TO CONTAFIN_ORACLE;
GRANT EXECUTE ON UTL_TCP TO CONTAFIN_ORACLE;
GRANT EXECUTE ON UTL_SMTP TO CONTAFIN_ORACLE;
GRANT EXECUTE ON UTL_HTTP TO CONTAFIN_ORACLE;
COMMIT;
PROMPT
PROMPT =============================================
PROMPT SYS objects created successfully
PROMPT =============================================
PROMPT
SELECT 'SYS_OBJECTS_COMPLETE' FROM dual;
EXIT;
"@
Set-Content -Path $sysObjectsScript -Value $sysObjectsSql -Encoding ASCII
Write-Log "Created sys-objects.sql"
}
# Execute SYS objects script
Write-LogSection "Executing sys-objects.sql"
$result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYS" -Password $SystemPassword -SqlFile $sysObjectsScript -AsSysdba
if ($result -match "SYS_OBJECTS_COMPLETE") {
Write-LogSuccess "SYS objects created successfully"
}
else {
Write-LogWarning "Script completed but could not verify success"
Write-LogDebug $result
}
# Verify created objects
Write-LogSection "Verifying SYS Objects"
$verifySql = @"
SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200
PROMPT
PROMPT === SYS Objects Status ===
PROMPT
SELECT object_name, object_type, status
FROM dba_objects
WHERE owner = 'SYS'
AND object_name IN ('AUTH_PACK', 'AUTH_DETALII', 'AUTH_SERII', 'VAUTH_SERII',
'PACK_UPDATE', 'PACK_UTILS', 'NEWSCHEMA', 'NEWSCHEMAPOST', 'NEWSCHEMAPROGRESS')
ORDER BY object_type, object_name;
PROMPT
PROMPT === Public Synonyms ===
PROMPT
SELECT synonym_name, table_owner, table_name
FROM dba_synonyms
WHERE owner = 'PUBLIC'
AND table_name IN ('AUTH_PACK', 'AUTH_DETALII', 'AUTH_SERII', 'VAUTH_SERII',
'PACK_UPDATE', 'PACK_UTILS', 'NEWSCHEMA', 'NEWSCHEMAPOST', 'NEWSCHEMAPROGRESS')
ORDER BY synonym_name;
EXIT;
"@
$verifyResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYS" -Password $SystemPassword -SqlCommand $verifySql -AsSysdba
Write-Host $verifyResult
# Count invalid objects
$invalidSql = @"
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF
SELECT 'INVALID_COUNT:' || COUNT(*)
FROM dba_objects
WHERE owner = 'SYS'
AND object_name IN ('AUTH_PACK', 'AUTH_DETALII', 'AUTH_SERII', 'VAUTH_SERII',
'PACK_UPDATE', 'PACK_UTILS', 'NEWSCHEMA', 'NEWSCHEMAPOST', 'NEWSCHEMAPROGRESS')
AND status = 'INVALID';
EXIT;
"@
$invalidResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYS" -Password $SystemPassword -SqlCommand $invalidSql -AsSysdba -Silent
$invalidCount = 0
if ($invalidResult -match "INVALID_COUNT:(\d+)") {
$invalidCount = [int]$Matches[1]
}
if ($invalidCount -gt 0) {
Write-LogWarning "$invalidCount invalid SYS objects found"
Write-Log "Attempting to recompile invalid objects..."
$recompileSql = @"
SET SERVEROUTPUT ON
BEGIN
DBMS_UTILITY.COMPILE_SCHEMA('SYS', FALSE);
END;
/
EXIT;
"@
Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYS" -Password $SystemPassword -SqlCommand $recompileSql -AsSysdba -Silent
}
else {
Write-LogSuccess "All SYS objects are valid"
}
# Summary
Write-LogSection "Setup Complete"
Write-LogSuccess "SYS objects installation completed!"
Write-Log ""
Write-Log "Objects created:"
Write-Log " - AUTH_PACK package"
Write-Log " - AUTH_DETALII table"
Write-Log " - AUTH_SERII table"
Write-Log " - VAUTH_SERII view"
Write-Log " - PACK_UPDATE package"
Write-Log " - PACK_UTILS package"
Write-Log " - Public synonyms and grants"
Write-Log ""
Write-Log "Next steps:"
Write-Log " 1. Run 03-import-contafin.ps1 to import CONTAFIN_ORACLE schema"
Close-LogFile -Success $true
exit 0
}
catch {
Write-LogError "Setup failed: $_"
Write-LogError $_.ScriptStackTrace
Close-LogFile -Success $false
exit 1
}
#Requires -Version 5.1
<#
.SYNOPSIS
Install SYS objects for ROA Oracle.
.DESCRIPTION
Executes SQL scripts to create required SYS-owned objects including:
- AUTH_PACK package
- AUTH_DETALII, AUTH_SERII tables
- NEWSCHEMA, NEWSCHEMAPOST procedures
- NEWSCHEMAPROGRESS function
- PACK_UPDATE, PACK_UTILS packages
- Public synonyms and grants
.PARAMETER OracleHome
Oracle home directory. If not specified, auto-detects.
.PARAMETER ServiceName
Database service name. Default: XEPDB1
.PARAMETER SystemPassword
SYSTEM/SYS user password. Default: romfastsoft
.PARAMETER SqlScriptsDir
Directory containing SYS SQL scripts. Default: ..\sql
.EXAMPLE
.\02-create-sys-objects.ps1
.EXAMPLE
.\02-create-sys-objects.ps1 -ServiceName "ROA" -SystemPassword "mypassword"
.NOTES
File Name : 02-create-sys-objects.ps1
Prerequisite : Run 01-setup-database.ps1 first
Copyright 2024 : ROMFAST
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string]$OracleHome,
[Parameter(Mandatory = $false)]
[string]$ServiceName = "XEPDB1",
[Parameter(Mandatory = $false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory = $false)]
[string]$SqlScriptsDir,
# Calea fizica pe care o primeste obiectul Oracle DIRECTORY DMPDIR.
# Trebuie sa fie aceeasi in toti pasii, altfel unul dintre ei repozitioneaza
# tacut directorul si SYS.NEWSCHEMA nu-si mai gaseste FIRMANOUA.dmp.
[Parameter(Mandatory = $false)]
[string]$DmpDir = "C:\DMPDIR"
)
$ErrorActionPreference = 'Stop'
# Source library functions
. "$PSScriptRoot\lib\logging-functions.ps1"
. "$PSScriptRoot\lib\oracle-functions.ps1"
# Initialize logging
$logPath = Join-Path $PSScriptRoot "..\logs\02-create-sys-objects_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
Initialize-LogFile -LogPath $logPath -ScriptName "02-create-sys-objects.ps1"
try {
Write-LogSection "Installing SYS Objects"
# Validate Oracle installation
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-LogSuccess "Oracle Home: $oraHome"
# Test connection
Write-Log "Testing database connection..."
if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYS" -Password $SystemPassword -AsSysdba)) {
throw "Cannot connect to database as SYS. Please verify ServiceName and SystemPassword."
}
Write-LogSuccess "Database connection successful"
# Determine SQL scripts directory
if (-not $SqlScriptsDir) {
$SqlScriptsDir = Join-Path $PSScriptRoot "..\sql"
}
$sysObjectsScript = Join-Path $SqlScriptsDir "sys-objects.sql"
if (-not (Test-Path -Path $sysObjectsScript)) {
Write-LogWarning "sys-objects.sql not found at $sysObjectsScript"
Write-Log "Creating sys-objects.sql from embedded SQL..."
# Create the sql directory if it doesn't exist
if (-not (Test-Path -Path $SqlScriptsDir)) {
New-Item -ItemType Directory -Path $SqlScriptsDir -Force | Out-Null
}
# Embedded SYS objects SQL - minimal set for ROA
$sysObjectsSql = @"
-- sys-objects.sql
-- SYS objects required for ROA Oracle
-- Run as SYS with SYSDBA privilege
SET ECHO ON FEEDBACK ON VERIFY OFF SERVEROUTPUT ON
PROMPT
PROMPT =============================================
PROMPT Creating SYS objects for ROA
PROMPT =============================================
PROMPT
-- Create DMPDIR if not exists
PROMPT Creating directory DMPDIR...
CREATE OR REPLACE DIRECTORY DMPDIR AS '$DmpDir';
GRANT READ, WRITE ON DIRECTORY DMPDIR TO PUBLIC;
-- AUTH_DETALII table
PROMPT Creating table AUTH_DETALII...
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE SYS.AUTH_DETALII CASCADE CONSTRAINTS';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE TABLE SYS.AUTH_DETALII (
ID_DETALIU NUMBER NOT NULL,
ID_PROGRAM NUMBER NOT NULL,
CAMP_DETALIU VARCHAR2(100),
VAL_DETALIU VARCHAR2(500),
CONSTRAINT PK_AUTH_DETALII PRIMARY KEY (ID_DETALIU)
);
GRANT SELECT, INSERT, UPDATE, DELETE ON SYS.AUTH_DETALII TO PUBLIC;
CREATE PUBLIC SYNONYM AUTH_DETALII FOR SYS.AUTH_DETALII;
-- AUTH_SERII table
PROMPT Creating table AUTH_SERII...
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE SYS.AUTH_SERII CASCADE CONSTRAINTS';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE TABLE SYS.AUTH_SERII (
ID_PROGRAM NUMBER NOT NULL,
SERIE VARCHAR2(50),
NR_UTIL NUMBER,
DATA_VAL DATE,
CONSTRAINT PK_AUTH_SERII PRIMARY KEY (ID_PROGRAM)
);
GRANT SELECT, INSERT, UPDATE, DELETE ON SYS.AUTH_SERII TO PUBLIC;
CREATE PUBLIC SYNONYM AUTH_SERII FOR SYS.AUTH_SERII;
-- AUTH_PACK package specification
PROMPT Creating package AUTH_PACK...
CREATE OR REPLACE PACKAGE SYS.AUTH_PACK AS
FUNCTION selecteaza_serie(p_id_program NUMBER) RETURN VARCHAR2;
FUNCTION selecteaza_nr_util(p_id_program NUMBER) RETURN NUMBER;
FUNCTION selecteaza_data_val(p_id_program NUMBER) RETURN DATE;
PROCEDURE actualizeaza_serie(p_id_program NUMBER, p_serie VARCHAR2, p_nr_util NUMBER, p_data_val DATE);
END AUTH_PACK;
/
-- AUTH_PACK package body
CREATE OR REPLACE PACKAGE BODY SYS.AUTH_PACK AS
FUNCTION selecteaza_serie(p_id_program NUMBER) RETURN VARCHAR2 IS
v_serie VARCHAR2(50);
BEGIN
SELECT serie INTO v_serie FROM SYS.AUTH_SERII WHERE id_program = p_id_program;
RETURN v_serie;
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN NULL;
END;
FUNCTION selecteaza_nr_util(p_id_program NUMBER) RETURN NUMBER IS
v_nr_util NUMBER;
BEGIN
SELECT nr_util INTO v_nr_util FROM SYS.AUTH_SERII WHERE id_program = p_id_program;
RETURN v_nr_util;
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN NULL;
END;
FUNCTION selecteaza_data_val(p_id_program NUMBER) RETURN DATE IS
v_data_val DATE;
BEGIN
SELECT data_val INTO v_data_val FROM SYS.AUTH_SERII WHERE id_program = p_id_program;
RETURN v_data_val;
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN NULL;
END;
PROCEDURE actualizeaza_serie(p_id_program NUMBER, p_serie VARCHAR2, p_nr_util NUMBER, p_data_val DATE) IS
BEGIN
MERGE INTO SYS.AUTH_SERII t
USING (SELECT p_id_program AS id_program FROM dual) s
ON (t.id_program = s.id_program)
WHEN MATCHED THEN
UPDATE SET serie = p_serie, nr_util = p_nr_util, data_val = p_data_val
WHEN NOT MATCHED THEN
INSERT (id_program, serie, nr_util, data_val)
VALUES (p_id_program, p_serie, p_nr_util, p_data_val);
COMMIT;
END;
END AUTH_PACK;
/
GRANT EXECUTE ON SYS.AUTH_PACK TO PUBLIC;
CREATE OR REPLACE PUBLIC SYNONYM AUTH_PACK FOR SYS.AUTH_PACK;
-- VAUTH_SERII view
PROMPT Creating view VAUTH_SERII...
CREATE OR REPLACE VIEW SYS.VAUTH_SERII AS
SELECT a.id_program,
a.denumire AS nume,
auth_pack.selecteaza_serie(a.id_program) AS serie,
auth_pack.selecteaza_nr_util(a.id_program) AS nr_util,
auth_pack.selecteaza_data_val(a.id_program) AS data_val
FROM syn_nom_programe a
LEFT JOIN syn_def_programe b ON a.id_program = b.ide_program
WHERE b.sters = 0
AND b.instalat = 1;
GRANT SELECT ON SYS.VAUTH_SERII TO PUBLIC;
CREATE OR REPLACE PUBLIC SYNONYM VAUTH_SERII FOR SYS.VAUTH_SERII;
-- PACK_UPDATE package (minimal version)
PROMPT Creating package PACK_UPDATE...
CREATE OR REPLACE PACKAGE SYS.PACK_UPDATE AS
FUNCTION get_version RETURN VARCHAR2;
PROCEDURE execute_sql(p_sql VARCHAR2);
END PACK_UPDATE;
/
CREATE OR REPLACE PACKAGE BODY SYS.PACK_UPDATE AS
FUNCTION get_version RETURN VARCHAR2 IS
BEGIN
RETURN '1.0.0';
END;
PROCEDURE execute_sql(p_sql VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE p_sql;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;
END PACK_UPDATE;
/
GRANT EXECUTE ON SYS.PACK_UPDATE TO PUBLIC;
CREATE OR REPLACE PUBLIC SYNONYM PACK_UPDATE FOR SYS.PACK_UPDATE;
-- PACK_UTILS package (minimal version)
PROMPT Creating package PACK_UTILS...
CREATE OR REPLACE PACKAGE SYS.PACK_UTILS AS
FUNCTION get_db_version RETURN VARCHAR2;
FUNCTION get_instance_name RETURN VARCHAR2;
END PACK_UTILS;
/
CREATE OR REPLACE PACKAGE BODY SYS.PACK_UTILS AS
FUNCTION get_db_version RETURN VARCHAR2 IS
v_version VARCHAR2(100);
BEGIN
SELECT version_full INTO v_version FROM v`$instance;
RETURN v_version;
EXCEPTION
WHEN OTHERS THEN RETURN NULL;
END;
FUNCTION get_instance_name RETURN VARCHAR2 IS
v_instance VARCHAR2(100);
BEGIN
SELECT instance_name INTO v_instance FROM v`$instance;
RETURN v_instance;
EXCEPTION
WHEN OTHERS THEN RETURN NULL;
END;
END PACK_UTILS;
/
GRANT EXECUTE ON SYS.PACK_UTILS TO PUBLIC;
CREATE OR REPLACE PUBLIC SYNONYM PACK_UTILS FOR SYS.PACK_UTILS;
-- Grant UTL packages to PUBLIC
PROMPT Granting UTL packages...
GRANT EXECUTE ON UTL_FILE TO PUBLIC;
GRANT EXECUTE ON DBMS_LOCK TO PUBLIC;
-- Grant UTL packages to CONTAFIN_ORACLE specifically
GRANT EXECUTE ON UTL_INADDR TO CONTAFIN_ORACLE;
GRANT EXECUTE ON UTL_TCP TO CONTAFIN_ORACLE;
GRANT EXECUTE ON UTL_SMTP TO CONTAFIN_ORACLE;
GRANT EXECUTE ON UTL_HTTP TO CONTAFIN_ORACLE;
COMMIT;
PROMPT
PROMPT =============================================
PROMPT SYS objects created successfully
PROMPT =============================================
PROMPT
SELECT 'SYS_OBJECTS_COMPLETE' FROM dual;
EXIT;
"@
Set-Content -Path $sysObjectsScript -Value $sysObjectsSql -Encoding ASCII
Write-Log "Created sys-objects.sql"
}
# Execute SYS objects script
Write-LogSection "Executing sys-objects.sql"
$result = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYS" -Password $SystemPassword -SqlFile $sysObjectsScript -AsSysdba
if ($result -match "SYS_OBJECTS_COMPLETE") {
Write-LogSuccess "SYS objects created successfully"
}
else {
Write-LogWarning "Script completed but could not verify success"
Write-LogDebug $result
}
# Verify created objects
Write-LogSection "Verifying SYS Objects"
$verifySql = @"
SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200
PROMPT
PROMPT === SYS Objects Status ===
PROMPT
SELECT object_name, object_type, status
FROM dba_objects
WHERE owner = 'SYS'
AND object_name IN ('AUTH_PACK', 'AUTH_DETALII', 'AUTH_SERII', 'VAUTH_SERII',
'PACK_UPDATE', 'PACK_UTILS', 'NEWSCHEMA', 'NEWSCHEMAPOST', 'NEWSCHEMAPROGRESS')
ORDER BY object_type, object_name;
PROMPT
PROMPT === Public Synonyms ===
PROMPT
SELECT synonym_name, table_owner, table_name
FROM dba_synonyms
WHERE owner = 'PUBLIC'
AND table_name IN ('AUTH_PACK', 'AUTH_DETALII', 'AUTH_SERII', 'VAUTH_SERII',
'PACK_UPDATE', 'PACK_UTILS', 'NEWSCHEMA', 'NEWSCHEMAPOST', 'NEWSCHEMAPROGRESS')
ORDER BY synonym_name;
EXIT;
"@
$verifyResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYS" -Password $SystemPassword -SqlCommand $verifySql -AsSysdba
Write-Host $verifyResult
# Count invalid objects
$invalidSql = @"
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF
SELECT 'INVALID_COUNT:' || COUNT(*)
FROM dba_objects
WHERE owner = 'SYS'
AND object_name IN ('AUTH_PACK', 'AUTH_DETALII', 'AUTH_SERII', 'VAUTH_SERII',
'PACK_UPDATE', 'PACK_UTILS', 'NEWSCHEMA', 'NEWSCHEMAPOST', 'NEWSCHEMAPROGRESS')
AND status = 'INVALID';
EXIT;
"@
$invalidResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYS" -Password $SystemPassword -SqlCommand $invalidSql -AsSysdba -Silent
$invalidCount = 0
if ($invalidResult -match "INVALID_COUNT:(\d+)") {
$invalidCount = [int]$Matches[1]
}
if ($invalidCount -gt 0) {
Write-LogWarning "$invalidCount invalid SYS objects found"
Write-Log "Attempting to recompile invalid objects..."
$recompileSql = @"
SET SERVEROUTPUT ON
BEGIN
DBMS_UTILITY.COMPILE_SCHEMA('SYS', FALSE);
END;
/
EXIT;
"@
Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYS" -Password $SystemPassword -SqlCommand $recompileSql -AsSysdba -Silent
}
else {
Write-LogSuccess "All SYS objects are valid"
}
# Summary
Write-LogSection "Setup Complete"
Write-LogSuccess "SYS objects installation completed!"
Write-Log ""
Write-Log "Objects created:"
Write-Log " - AUTH_PACK package"
Write-Log " - AUTH_DETALII table"
Write-Log " - AUTH_SERII table"
Write-Log " - VAUTH_SERII view"
Write-Log " - PACK_UPDATE package"
Write-Log " - PACK_UTILS package"
Write-Log " - Public synonyms and grants"
Write-Log ""
Write-Log "Next steps:"
Write-Log " 1. Run 03-import-contafin.ps1 to import CONTAFIN_ORACLE schema"
Close-LogFile -Success $true
exit 0
}
catch {
Write-LogError "Setup failed: $_"
Write-LogError $_.ScriptStackTrace
Close-LogFile -Success $false
exit 1
}

View File

@@ -1,334 +1,339 @@
#Requires -Version 5.1
<#
.SYNOPSIS
Import CONTAFIN_ORACLE schema from Data Pump dump file.
.DESCRIPTION
Imports the CONTAFIN_ORACLE schema using Oracle Data Pump (impdp).
- Creates DMPDIR directory if not exists
- Runs impdp with optimal parameters
- Verifies import (object count, invalid objects)
.PARAMETER DumpFile
Path to the CONTAFIN_ORACLE DMP file. If not specified, auto-detects from DmpDir.
.PARAMETER OracleHome
Oracle home directory. If not specified, auto-detects.
.PARAMETER ServiceName
Database service name. Default: XEPDB1
.PARAMETER SystemPassword
SYSTEM user password. Default: romfastsoft
.PARAMETER DmpDir
Oracle directory path for Data Pump. Default: C:\DMPDIR
.PARAMETER TableExistsAction
What to do if table exists: SKIP, APPEND, TRUNCATE, REPLACE. Default: REPLACE
.PARAMETER Parallel
Number of parallel workers for import. Default: 2
.EXAMPLE
.\03-import-contafin.ps1 -DumpFile "C:\dumps\CONTAFIN_ORACLE.dmp"
.EXAMPLE
.\03-import-contafin.ps1 -DumpFile "D:\backups\contafin.dmp" -ServiceName "ROA" -SystemPassword "mypass"
.NOTES
File Name : 03-import-contafin.ps1
Prerequisite : Run 01-setup-database.ps1 and 02-create-sys-objects.ps1 first
Copyright 2024 : ROMFAST
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string]$DumpFile,
[Parameter(Mandatory = $false)]
[string]$OracleHome,
[Parameter(Mandatory = $false)]
[string]$ServiceName = "XEPDB1",
[Parameter(Mandatory = $false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory = $false)]
[string]$DmpDir = "C:\DMPDIR",
[Parameter(Mandatory = $false)]
[ValidateSet('SKIP', 'APPEND', 'TRUNCATE', 'REPLACE')]
[string]$TableExistsAction = "REPLACE",
[Parameter(Mandatory = $false)]
[int]$Parallel = 1
)
$ErrorActionPreference = 'Stop'
# Source library functions
. "$PSScriptRoot\lib\logging-functions.ps1"
. "$PSScriptRoot\lib\oracle-functions.ps1"
# Initialize logging
$logPath = Join-Path $PSScriptRoot "..\logs\03-import-contafin_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
Initialize-LogFile -LogPath $logPath -ScriptName "03-import-contafin.ps1"
# Auto-detect DumpFile if not specified
if (-not $DumpFile) {
Write-Host "[INFO] DumpFile not specified, searching in $DmpDir..." -ForegroundColor Yellow
$candidates = Get-ChildItem -Path $DmpDir -Filter "*contafin*.dmp" -ErrorAction SilentlyContinue |
Sort-Object LastWriteTime -Descending
if ($candidates) {
$DumpFile = $candidates[0].FullName
Write-Host "[INFO] Auto-detected DumpFile: $DumpFile" -ForegroundColor Green
} else {
throw "No CONTAFIN_ORACLE dump file found in $DmpDir. Please specify -DumpFile parameter or copy *contafin*.dmp to $DmpDir"
}
}
# Validate DumpFile exists
if (-not (Test-Path $DumpFile)) {
throw "DumpFile not found: $DumpFile"
}
try {
Write-LogSection "Importing CONTAFIN_ORACLE Schema"
# Validate Oracle installation
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-LogSuccess "Oracle Home: $oraHome"
# Test connection
Write-Log "Testing database connection..."
if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword)) {
throw "Cannot connect to database. Please verify ServiceName and SystemPassword."
}
Write-LogSuccess "Database connection successful"
# Verify CONTAFIN_ORACLE user exists
Write-Log "Verifying CONTAFIN_ORACLE user exists..."
if (-not (Test-OracleUser -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName "CONTAFIN_ORACLE")) {
throw "User CONTAFIN_ORACLE does not exist. Run 01-setup-database.ps1 first."
}
Write-LogSuccess "User CONTAFIN_ORACLE exists"
# Create/verify DMPDIR
Write-LogSection "Configuring Data Pump Directory"
if (-not (Test-Path -Path $DmpDir)) {
New-Item -ItemType Directory -Path $DmpDir -Force | Out-Null
Write-Log "Created directory: $DmpDir"
}
New-OracleDirectory -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -DirectoryName "DMPDIR" -DirectoryPath $DmpDir
# Copy dump file to DMPDIR if not already there
$dumpFileName = Split-Path -Path $DumpFile -Leaf
$targetDumpPath = Join-Path $DmpDir $dumpFileName
# Resolve paths for accurate comparison (handles casing and path format differences)
$resolvedSource = (Resolve-Path -Path $DumpFile -ErrorAction SilentlyContinue).Path
$resolvedTarget = if (Test-Path $targetDumpPath) { (Resolve-Path -Path $targetDumpPath).Path } else { $null }
if ($resolvedSource -ne $resolvedTarget) {
Write-Log "Copying dump file to DMPDIR..."
Copy-Item -Path $DumpFile -Destination $targetDumpPath -Force
Write-LogSuccess "Dump file copied to: $targetDumpPath"
}
else {
Write-Log "Dump file already in DMPDIR: $targetDumpPath"
}
# Check dump file size
$dumpFileInfo = Get-Item $targetDumpPath
$dumpSizeMB = [math]::Round($dumpFileInfo.Length / 1MB, 2)
Write-Log "Dump file size: $dumpSizeMB MB"
# Get current object count before import
Write-Log "Getting current object count for CONTAFIN_ORACLE..."
$beforeCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName "CONTAFIN_ORACLE"
$beforeTotal = if ($beforeCounts['TOTAL']) { $beforeCounts['TOTAL'] } else { 0 }
Write-Log "Objects before import: $beforeTotal"
# Run import
Write-LogSection "Running Data Pump Import"
$impdpPath = Join-Path $oraHome "bin\impdp.exe"
if (-not (Test-Path -Path $impdpPath)) {
throw "impdp.exe not found at: $impdpPath"
}
$importLogFile = "CONTAFIN_ORACLE_import_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
# Get listener host for connection (handles listener bound to specific IP)
$dbHost = Get-ListenerHost -OracleHome $oraHome
$dbPort = 1521
# Build impdp command with EZConnect format
$connString = "SYSTEM/`"$SystemPassword`"@${dbHost}:${dbPort}/${ServiceName}"
$impdpParams = @(
"`"$connString`"",
"directory=DMPDIR",
"dumpfile=$dumpFileName",
"logfile=$importLogFile",
"schemas=CONTAFIN_ORACLE",
"table_exists_action=$TableExistsAction",
"parallel=$Parallel" # Always specify to override DMP metadata (XE requires parallel=1)
)
$arguments = $impdpParams -join " "
Write-Log "Executing impdp..."
Write-Log "Parameters: directory=DMPDIR dumpfile=$dumpFileName schemas=CONTAFIN_ORACLE table_exists_action=$TableExistsAction"
# Set Oracle environment
$env:ORACLE_HOME = $oraHome
$env:PATH = "$oraHome\bin;$env:PATH"
$env:NLS_LANG = "AMERICAN_AMERICA.AL32UTF8"
$startTime = Get-Date
# Execute impdp
$process = Start-Process -FilePath $impdpPath -ArgumentList $arguments -Wait -NoNewWindow -PassThru
$duration = (Get-Date) - $startTime
Write-Log "Import completed in $([math]::Round($duration.TotalMinutes, 2)) minutes"
# Check import log
$importLogPath = Join-Path $DmpDir $importLogFile
if (Test-Path -Path $importLogPath) {
Write-Log "Import log: $importLogPath"
# Read and analyze log for errors
$logContent = Get-Content -Path $importLogPath -Raw
if ($logContent -match "ORA-\d{5}:") {
Write-LogWarning "Import completed with Oracle errors. Check log for details."
}
if ($logContent -match "successfully loaded/unloaded") {
Write-LogSuccess "Objects successfully loaded"
}
# Count errors and warnings in log
$errorCount = ([regex]::Matches($logContent, "ORA-\d{5}:")).Count
$warningCount = ([regex]::Matches($logContent, "ORA-39\d{3}:")).Count
Write-Log "Errors in log: $errorCount"
Write-Log "Warnings in log: $warningCount"
}
# Verify import
Write-LogSection "Verifying Import"
# Get object counts after import
$afterCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName "CONTAFIN_ORACLE"
$afterTotal = if ($afterCounts['TOTAL']) { $afterCounts['TOTAL'] } else { 0 }
$afterInvalid = if ($afterCounts['INVALID']) { $afterCounts['INVALID'] } else { 0 }
Write-Log "Objects after import: $afterTotal"
Write-Log "Objects imported: $($afterTotal - $beforeTotal)"
# Display object counts by type
Write-Log ""
Write-Log "Object counts by type:"
foreach ($key in $afterCounts.Keys | Sort-Object) {
if ($key -ne 'TOTAL' -and $key -ne 'INVALID') {
Write-Log " $($key): $($afterCounts[$key])"
}
}
if ($afterInvalid -gt 0) {
Write-LogWarning "Invalid objects: $afterInvalid"
# List invalid objects
$invalidSql = @"
SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200
SELECT object_name, object_type
FROM dba_objects
WHERE owner = 'CONTAFIN_ORACLE'
AND status = 'INVALID'
ORDER BY object_type, object_name;
EXIT;
"@
$invalidList = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $invalidSql -Silent
Write-Log "Invalid objects:"
Write-Host $invalidList
# Attempt to recompile
Write-Log "Attempting to recompile invalid objects..."
$recompileSql = @"
SET SERVEROUTPUT ON
BEGIN
DBMS_UTILITY.COMPILE_SCHEMA('CONTAFIN_ORACLE', FALSE);
END;
/
EXIT;
"@
Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $recompileSql -Silent
# Recheck invalid count
$recheckCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName "CONTAFIN_ORACLE"
$recheckInvalid = if ($recheckCounts['INVALID']) { $recheckCounts['INVALID'] } else { 0 }
if ($recheckInvalid -lt $afterInvalid) {
Write-LogSuccess "Recompilation fixed $($afterInvalid - $recheckInvalid) objects"
}
if ($recheckInvalid -gt 0) {
Write-LogWarning "Still $recheckInvalid invalid objects remaining"
}
}
else {
Write-LogSuccess "No invalid objects"
}
# Summary
Write-LogSection "Import Complete"
if ($process.ExitCode -eq 0) {
Write-LogSuccess "CONTAFIN_ORACLE schema imported successfully!"
}
else {
Write-LogWarning "Import completed with warnings (exit code: $($process.ExitCode))"
}
Write-Log ""
Write-Log "Summary:"
Write-Log " Dump file: $dumpFileName ($dumpSizeMB MB)"
Write-Log " Service: $ServiceName"
Write-Log " Duration: $([math]::Round($duration.TotalMinutes, 2)) minutes"
Write-Log " Objects: $afterTotal"
Write-Log " Import log: $importLogPath"
Write-Log ""
Write-Log "Next steps:"
Write-Log " 1. Run 04-create-synonyms-grants.ps1 to create public synonyms"
Write-Log " 2. Run 05-import-companies.ps1 to import company schemas"
Close-LogFile -Success ($process.ExitCode -eq 0)
exit $process.ExitCode
}
catch {
Write-LogError "Import failed: $_"
Write-LogError $_.ScriptStackTrace
Close-LogFile -Success $false
exit 1
}
#Requires -Version 5.1
<#
.SYNOPSIS
Import CONTAFIN_ORACLE schema from Data Pump dump file.
.DESCRIPTION
Imports the CONTAFIN_ORACLE schema using Oracle Data Pump (impdp).
- Creates DMPDIR directory if not exists
- Runs impdp with optimal parameters
- Verifies import (object count, invalid objects)
.PARAMETER DumpFile
Path to the CONTAFIN_ORACLE DMP file. If not specified, auto-detects from DmpDir.
.PARAMETER OracleHome
Oracle home directory. If not specified, auto-detects.
.PARAMETER ServiceName
Database service name. Default: XEPDB1
.PARAMETER SystemPassword
SYSTEM user password. Default: romfastsoft
.PARAMETER DmpDir
Oracle directory path for Data Pump. Default: C:\DMPDIR
.PARAMETER TableExistsAction
What to do if table exists: SKIP, APPEND, TRUNCATE, REPLACE. Default: REPLACE
.PARAMETER Parallel
Number of parallel workers for import. Default: 2
.EXAMPLE
.\03-import-contafin.ps1 -DumpFile "C:\dumps\CONTAFIN_ORACLE.dmp"
.EXAMPLE
.\03-import-contafin.ps1 -DumpFile "D:\backups\contafin.dmp" -ServiceName "ROA" -SystemPassword "mypass"
.NOTES
File Name : 03-import-contafin.ps1
Prerequisite : Run 01-setup-database.ps1 and 02-create-sys-objects.ps1 first
Copyright 2024 : ROMFAST
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string]$DumpFile,
[Parameter(Mandatory = $false)]
[string]$OracleHome,
[Parameter(Mandatory = $false)]
[string]$ServiceName = "XEPDB1",
[Parameter(Mandatory = $false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory = $false)]
[string]$DmpDir = "C:\DMPDIR",
[Parameter(Mandatory = $false)]
[ValidateSet('SKIP', 'APPEND', 'TRUNCATE', 'REPLACE')]
[string]$TableExistsAction = "REPLACE",
[Parameter(Mandatory = $false)]
[int]$Parallel = 1
)
$ErrorActionPreference = 'Stop'
# Source library functions
. "$PSScriptRoot\lib\logging-functions.ps1"
. "$PSScriptRoot\lib\oracle-functions.ps1"
# Initialize logging
$logPath = Join-Path $PSScriptRoot "..\logs\03-import-contafin_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
Initialize-LogFile -LogPath $logPath -ScriptName "03-import-contafin.ps1"
# Auto-detect DumpFile if not specified
if (-not $DumpFile) {
Write-Host "[INFO] DumpFile not specified, searching in $DmpDir..." -ForegroundColor Yellow
$candidates = Get-ChildItem -Path $DmpDir -Filter "*contafin*.dmp" -ErrorAction SilentlyContinue |
Sort-Object LastWriteTime -Descending
if ($candidates) {
$DumpFile = $candidates[0].FullName
Write-Host "[INFO] Auto-detected DumpFile: $DumpFile" -ForegroundColor Green
} else {
throw "No CONTAFIN_ORACLE dump file found in $DmpDir. Please specify -DumpFile parameter or copy *contafin*.dmp to $DmpDir"
}
}
# Validate DumpFile exists
if (-not (Test-Path $DumpFile)) {
throw "DumpFile not found: $DumpFile"
}
try {
Write-LogSection "Importing CONTAFIN_ORACLE Schema"
# Validate Oracle installation
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-LogSuccess "Oracle Home: $oraHome"
# Test connection
Write-Log "Testing database connection..."
if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword)) {
throw "Cannot connect to database. Please verify ServiceName and SystemPassword."
}
Write-LogSuccess "Database connection successful"
# Verify CONTAFIN_ORACLE user exists
Write-Log "Verifying CONTAFIN_ORACLE user exists..."
if (-not (Test-OracleUser -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName "CONTAFIN_ORACLE")) {
throw "User CONTAFIN_ORACLE does not exist. Run 01-setup-database.ps1 first."
}
Write-LogSuccess "User CONTAFIN_ORACLE exists"
# Create/verify DMPDIR
Write-LogSection "Configuring Data Pump Directory"
if (-not (Test-Path -Path $DmpDir)) {
New-Item -ItemType Directory -Path $DmpDir -Force | Out-Null
Write-Log "Created directory: $DmpDir"
}
# Valoarea de retur nu era verificata - de aici si "True" ratacit in log.
# Mai rau: cand directorul nu era utilizabil, importul mergea mai departe si
# cadea abia in impdp cu ORA-29283, la zeci de linii distanta de cauza.
if (-not (New-OracleDirectory -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -DirectoryName "DMPDIR" -DirectoryPath $DmpDir)) {
throw "Directorul Data Pump DMPDIR ($DmpDir) nu e utilizabil de catre baza. Vezi mesajele de mai sus."
}
# Copy dump file to DMPDIR if not already there
$dumpFileName = Split-Path -Path $DumpFile -Leaf
$targetDumpPath = Join-Path $DmpDir $dumpFileName
# Resolve paths for accurate comparison (handles casing and path format differences)
$resolvedSource = (Resolve-Path -Path $DumpFile -ErrorAction SilentlyContinue).Path
$resolvedTarget = if (Test-Path $targetDumpPath) { (Resolve-Path -Path $targetDumpPath).Path } else { $null }
if ($resolvedSource -ne $resolvedTarget) {
Write-Log "Copying dump file to DMPDIR..."
Copy-Item -Path $DumpFile -Destination $targetDumpPath -Force
Write-LogSuccess "Dump file copied to: $targetDumpPath"
}
else {
Write-Log "Dump file already in DMPDIR: $targetDumpPath"
}
# Check dump file size
$dumpFileInfo = Get-Item $targetDumpPath
$dumpSizeMB = [math]::Round($dumpFileInfo.Length / 1MB, 2)
Write-Log "Dump file size: $dumpSizeMB MB"
# Get current object count before import
Write-Log "Getting current object count for CONTAFIN_ORACLE..."
$beforeCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName "CONTAFIN_ORACLE"
$beforeTotal = if ($beforeCounts['TOTAL']) { $beforeCounts['TOTAL'] } else { 0 }
Write-Log "Objects before import: $beforeTotal"
# Run import
Write-LogSection "Running Data Pump Import"
$impdpPath = Join-Path $oraHome "bin\impdp.exe"
if (-not (Test-Path -Path $impdpPath)) {
throw "impdp.exe not found at: $impdpPath"
}
$importLogFile = "CONTAFIN_ORACLE_import_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
# Get listener host for connection (handles listener bound to specific IP)
$dbHost = Get-ListenerHost -OracleHome $oraHome
$dbPort = 1521
# Build impdp command with EZConnect format
$connString = "SYSTEM/`"$SystemPassword`"@${dbHost}:${dbPort}/${ServiceName}"
$impdpParams = @(
"`"$connString`"",
"directory=DMPDIR",
"dumpfile=$dumpFileName",
"logfile=$importLogFile",
"schemas=CONTAFIN_ORACLE",
"table_exists_action=$TableExistsAction",
"parallel=$Parallel" # Always specify to override DMP metadata (XE requires parallel=1)
)
$arguments = $impdpParams -join " "
Write-Log "Executing impdp..."
Write-Log "Parameters: directory=DMPDIR dumpfile=$dumpFileName schemas=CONTAFIN_ORACLE table_exists_action=$TableExistsAction"
# Set Oracle environment
$env:ORACLE_HOME = $oraHome
$env:PATH = "$oraHome\bin;$env:PATH"
$env:NLS_LANG = "AMERICAN_AMERICA.AL32UTF8"
$startTime = Get-Date
# Execute impdp
$process = Start-Process -FilePath $impdpPath -ArgumentList $arguments -Wait -NoNewWindow -PassThru
$duration = (Get-Date) - $startTime
Write-Log "Import completed in $([math]::Round($duration.TotalMinutes, 2)) minutes"
# Check import log
$importLogPath = Join-Path $DmpDir $importLogFile
if (Test-Path -Path $importLogPath) {
Write-Log "Import log: $importLogPath"
# Read and analyze log for errors
$logContent = Get-Content -Path $importLogPath -Raw
if ($logContent -match "ORA-\d{5}:") {
Write-LogWarning "Import completed with Oracle errors. Check log for details."
}
if ($logContent -match "successfully loaded/unloaded") {
Write-LogSuccess "Objects successfully loaded"
}
# Count errors and warnings in log
$errorCount = ([regex]::Matches($logContent, "ORA-\d{5}:")).Count
$warningCount = ([regex]::Matches($logContent, "ORA-39\d{3}:")).Count
Write-Log "Errors in log: $errorCount"
Write-Log "Warnings in log: $warningCount"
}
# Verify import
Write-LogSection "Verifying Import"
# Get object counts after import
$afterCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName "CONTAFIN_ORACLE"
$afterTotal = if ($afterCounts['TOTAL']) { $afterCounts['TOTAL'] } else { 0 }
$afterInvalid = if ($afterCounts['INVALID']) { $afterCounts['INVALID'] } else { 0 }
Write-Log "Objects after import: $afterTotal"
Write-Log "Objects imported: $($afterTotal - $beforeTotal)"
# Display object counts by type
Write-Log ""
Write-Log "Object counts by type:"
foreach ($key in $afterCounts.Keys | Sort-Object) {
if ($key -ne 'TOTAL' -and $key -ne 'INVALID') {
Write-Log " $($key): $($afterCounts[$key])"
}
}
if ($afterInvalid -gt 0) {
Write-LogWarning "Invalid objects: $afterInvalid"
# List invalid objects
$invalidSql = @"
SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200
SELECT object_name, object_type
FROM dba_objects
WHERE owner = 'CONTAFIN_ORACLE'
AND status = 'INVALID'
ORDER BY object_type, object_name;
EXIT;
"@
$invalidList = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $invalidSql -Silent
Write-Log "Invalid objects:"
Write-Host $invalidList
# Attempt to recompile
Write-Log "Attempting to recompile invalid objects..."
$recompileSql = @"
SET SERVEROUTPUT ON
BEGIN
DBMS_UTILITY.COMPILE_SCHEMA('CONTAFIN_ORACLE', FALSE);
END;
/
EXIT;
"@
Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $recompileSql -Silent
# Recheck invalid count
$recheckCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName "CONTAFIN_ORACLE"
$recheckInvalid = if ($recheckCounts['INVALID']) { $recheckCounts['INVALID'] } else { 0 }
if ($recheckInvalid -lt $afterInvalid) {
Write-LogSuccess "Recompilation fixed $($afterInvalid - $recheckInvalid) objects"
}
if ($recheckInvalid -gt 0) {
Write-LogWarning "Still $recheckInvalid invalid objects remaining"
}
}
else {
Write-LogSuccess "No invalid objects"
}
# Summary
Write-LogSection "Import Complete"
if ($process.ExitCode -eq 0) {
Write-LogSuccess "CONTAFIN_ORACLE schema imported successfully!"
}
else {
Write-LogWarning "Import completed with warnings (exit code: $($process.ExitCode))"
}
Write-Log ""
Write-Log "Summary:"
Write-Log " Dump file: $dumpFileName ($dumpSizeMB MB)"
Write-Log " Service: $ServiceName"
Write-Log " Duration: $([math]::Round($duration.TotalMinutes, 2)) minutes"
Write-Log " Objects: $afterTotal"
Write-Log " Import log: $importLogPath"
Write-Log ""
Write-Log "Next steps:"
Write-Log " 1. Run 04-create-synonyms-grants.ps1 to create public synonyms"
Write-Log " 2. Run 05-import-companies.ps1 to import company schemas"
Close-LogFile -Success ($process.ExitCode -eq 0)
exit $process.ExitCode
}
catch {
Write-LogError "Import failed: $_"
Write-LogError $_.ScriptStackTrace
Close-LogFile -Success $false
exit 1
}

View File

@@ -1,432 +1,448 @@
#Requires -Version 5.1
<#
.SYNOPSIS
Batch import company schemas from Data Pump dump files.
.DESCRIPTION
Imports company schemas from dump files. CRITICAL: Reads passwords from
CONTAFIN_ORACLE.NOM_FIRME table to ensure correct authentication.
For each company:
1. Queries NOM_FIRME for schema name and password
2. Finds matching DMP file in DumpDirectory
3. Creates user with password from NOM_FIRME
4. Runs impdp to import schema
5. Logs progress
.PARAMETER DumpDirectory
Directory containing company DMP files. If not specified, defaults to C:\DMPDIR.
.PARAMETER OracleHome
Oracle home directory. If not specified, auto-detects.
.PARAMETER ServiceName
Database service name. Default: XEPDB1
.PARAMETER SystemPassword
SYSTEM user password. Default: romfastsoft
.PARAMETER ParallelJobs
Number of parallel import jobs. Default: 2
.PARAMETER Companies
Optional array of specific company names to import. If not specified, imports all.
.PARAMETER DryRun
Show what would be imported without actually importing.
.EXAMPLE
.\05-import-companies.ps1 -DumpDirectory "C:\dumps\companies"
.EXAMPLE
.\05-import-companies.ps1 -DumpDirectory "D:\backups" -Companies "FIRMA1","FIRMA2"
.EXAMPLE
.\05-import-companies.ps1 -DumpDirectory "C:\dumps" -DryRun
.NOTES
File Name : 05-import-companies.ps1
Prerequisite : Run 04-create-synonyms-grants.ps1 first
Copyright 2024 : ROMFAST
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string]$DumpDirectory = "C:\DMPDIR",
[Parameter(Mandatory = $false)]
[string]$OracleHome,
[Parameter(Mandatory = $false)]
[string]$ServiceName = "XEPDB1",
[Parameter(Mandatory = $false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory = $false)]
[int]$ParallelJobs = 2,
[Parameter(Mandatory = $false)]
[string[]]$Companies,
[Parameter(Mandatory = $false)]
[switch]$DryRun
)
$ErrorActionPreference = 'Stop'
# Source library functions
. "$PSScriptRoot\lib\logging-functions.ps1"
. "$PSScriptRoot\lib\oracle-functions.ps1"
# Initialize logging
$logPath = Join-Path $PSScriptRoot "..\logs\05-import-companies_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
Initialize-LogFile -LogPath $logPath -ScriptName "05-import-companies.ps1"
try {
Write-LogSection "Batch Import Company Schemas"
# Validate DumpDirectory exists
if (-not (Test-Path $DumpDirectory -PathType Container)) {
throw "DumpDirectory not found: $DumpDirectory"
}
Write-Log "Using dump directory: $DumpDirectory"
if ($DryRun) {
Write-LogWarning "DRY RUN MODE - No changes will be made"
}
# Validate Oracle installation
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-LogSuccess "Oracle Home: $oraHome"
# Test connection
Write-Log "Testing database connection..."
if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword)) {
throw "Cannot connect to database. Please verify ServiceName and SystemPassword."
}
Write-LogSuccess "Database connection successful"
# Get company list from NOM_FIRME
Write-LogSection "Reading Company List from NOM_FIRME"
$companySql = @"
SET PAGESIZE 10000 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 500
SELECT schema || '|' || parola
FROM CONTAFIN_ORACLE.NOM_FIRME
WHERE sters = 0
AND schema IS NOT NULL
ORDER BY schema;
EXIT;
"@
$companyResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $companySql -Silent
# Parse company data
$companyData = @{}
foreach ($line in $companyResult -split "`n") {
$line = $line.Trim()
if ($line -match "^([A-Z0-9_]+)\|(.*)$") {
$schema = $Matches[1]
$password = $Matches[2]
if (-not $password) { $password = "ROMFASTSOFT" }
$companyData[$schema] = $password
}
}
Write-Log "Found $($companyData.Count) companies in NOM_FIRME"
if ($companyData.Count -eq 0) {
Write-LogWarning "No companies found in NOM_FIRME"
Close-LogFile -Success $true
exit 0
}
# Filter companies if specified
if ($Companies) {
$filteredData = @{}
foreach ($company in $Companies) {
$companyUpper = $company.ToUpper()
if ($companyData.ContainsKey($companyUpper)) {
$filteredData[$companyUpper] = $companyData[$companyUpper]
}
else {
Write-LogWarning "Company $companyUpper not found in NOM_FIRME"
}
}
$companyData = $filteredData
Write-Log "Filtered to $($companyData.Count) companies"
}
# Find matching dump files
Write-LogSection "Scanning Dump Files"
$dumpFiles = Get-ChildItem -Path $DumpDirectory -Filter "*.dmp" -File
Write-Log "Found $($dumpFiles.Count) DMP files in $DumpDirectory"
# Match companies with dump files
$importList = @()
$notFoundList = @()
foreach ($schema in $companyData.Keys) {
# Try to find matching dump file (case-insensitive)
$matchingFile = $dumpFiles | Where-Object {
$_.BaseName -ieq $schema -or
$_.BaseName -imatch "^$schema[_\.]" -or
$_.BaseName -imatch "^${schema}$"
} | Select-Object -First 1
if ($matchingFile) {
$importList += [PSCustomObject]@{
Schema = $schema
Password = $companyData[$schema]
DumpFile = $matchingFile.FullName
DumpSize = [math]::Round($matchingFile.Length / 1MB, 2)
}
}
else {
$notFoundList += $schema
}
}
Write-Log "Companies to import: $($importList.Count)"
if ($notFoundList.Count -gt 0) {
Write-LogWarning "Companies without matching dump file: $($notFoundList.Count)"
foreach ($schema in $notFoundList) {
Write-Log " - $schema (no DMP file found)"
}
}
if ($importList.Count -eq 0) {
Write-LogWarning "No companies to import"
Close-LogFile -Success $true
exit 0
}
# Display import plan
Write-LogSection "Import Plan"
$totalSize = ($importList | Measure-Object -Property DumpSize -Sum).Sum
Write-Log "Total data to import: $totalSize MB"
Write-Log ""
Write-Log "Companies to import:"
foreach ($item in $importList) {
Write-Log " - $($item.Schema): $($item.DumpFile) ($($item.DumpSize) MB)"
}
if ($DryRun) {
Write-LogSection "Dry Run Complete"
Write-Log "Would import $($importList.Count) company schemas"
Close-LogFile -Success $true
exit 0
}
# Ensure DMPDIR exists
$dmpDir = "C:\DMPDIR"
if (-not (Test-Path -Path $dmpDir)) {
New-Item -ItemType Directory -Path $dmpDir -Force | Out-Null
}
# Process each company
Write-LogSection "Importing Companies"
$successCount = 0
$failCount = 0
$startTime = Get-Date
foreach ($item in $importList) {
Write-LogSection "Importing $($item.Schema)"
try {
# Check if user already exists
$userExists = Test-OracleUser -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $item.Schema
if ($userExists) {
Write-Log "User $($item.Schema) already exists"
# Get current object count
$beforeCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $item.Schema
$beforeTotal = if ($beforeCounts['TOTAL']) { $beforeCounts['TOTAL'] } else { 0 }
Write-Log "Existing objects: $beforeTotal"
}
else {
# Create user
Write-Log "Creating user $($item.Schema)..."
$createUserSql = @"
SET ECHO OFF FEEDBACK ON VERIFY OFF
CREATE USER $($item.Schema)
IDENTIFIED BY "$($item.Password)"
DEFAULT TABLESPACE ROA
TEMPORARY TABLESPACE TEMP
PROFILE DEFAULT;
GRANT CONNECT TO $($item.Schema);
GRANT RESOURCE TO $($item.Schema);
GRANT CREATE MATERIALIZED VIEW TO $($item.Schema);
GRANT CREATE PROCEDURE TO $($item.Schema);
GRANT CREATE SEQUENCE TO $($item.Schema);
GRANT CREATE TABLE TO $($item.Schema);
GRANT CREATE TRIGGER TO $($item.Schema);
GRANT CREATE VIEW TO $($item.Schema);
GRANT DEBUG CONNECT SESSION TO $($item.Schema);
GRANT SELECT ANY TABLE TO $($item.Schema);
GRANT CREATE TYPE TO $($item.Schema);
GRANT UNLIMITED TABLESPACE TO $($item.Schema);
COMMIT;
SELECT 'USER_CREATED' FROM dual;
EXIT;
"@
$createResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $createUserSql -Silent
if ($createResult -match "USER_CREATED") {
Write-LogSuccess "User $($item.Schema) created"
}
else {
throw "Failed to create user $($item.Schema)"
}
}
# Copy dump file to DMPDIR if not already there
$dumpFileName = Split-Path -Path $item.DumpFile -Leaf
$targetDumpPath = Join-Path $dmpDir $dumpFileName
if ($item.DumpFile -ne $targetDumpPath) {
Write-Log "Copying dump file to DMPDIR..."
Copy-Item -Path $item.DumpFile -Destination $targetDumpPath -Force
}
# Run import
Write-Log "Running impdp for $($item.Schema)..."
$impdpPath = Join-Path $oraHome "bin\impdp.exe"
$importLogFile = "$($item.Schema)_import_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
# Use EZConnect format for impdp (handles listener bound to specific IP)
$dbHost = Get-ListenerHost -OracleHome $oraHome
$connString = "SYSTEM/`"$SystemPassword`"@${dbHost}:1521/$ServiceName"
# Check if dump has different schema name (remapping needed)
$remapParam = ""
$dumpBaseName = [System.IO.Path]::GetFileNameWithoutExtension($dumpFileName).ToUpper()
if ($dumpBaseName -ne $item.Schema) {
$remapParam = "remap_schema=$dumpBaseName`:$($item.Schema)"
Write-Log "Schema remap: $dumpBaseName -> $($item.Schema)"
}
$impdpParams = @(
"`"$connString`"",
"directory=DMPDIR",
"dumpfile=$dumpFileName",
"logfile=$importLogFile",
"schemas=$($item.Schema)",
"table_exists_action=REPLACE",
"parallel=1" # Required for Oracle XE
)
if ($remapParam) {
$impdpParams += $remapParam
}
$arguments = $impdpParams -join " "
# Set Oracle environment
$env:ORACLE_HOME = $oraHome
$env:PATH = "$oraHome\bin;$env:PATH"
$env:NLS_LANG = "AMERICAN_AMERICA.AL32UTF8"
$importStart = Get-Date
$process = Start-Process -FilePath $impdpPath -ArgumentList $arguments -Wait -NoNewWindow -PassThru
$importDuration = (Get-Date) - $importStart
Write-Log "Import completed in $([math]::Round($importDuration.TotalMinutes, 2)) minutes"
# Verify import
$afterCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $item.Schema
$afterTotal = if ($afterCounts['TOTAL']) { $afterCounts['TOTAL'] } else { 0 }
$afterInvalid = if ($afterCounts['INVALID']) { $afterCounts['INVALID'] } else { 0 }
Write-Log "Objects after import: $afterTotal"
if ($afterInvalid -gt 0) {
Write-LogWarning "Invalid objects: $afterInvalid"
# Recompile
$recompileSql = @"
BEGIN
DBMS_UTILITY.COMPILE_SCHEMA('$($item.Schema)', FALSE);
END;
/
EXIT;
"@
Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $recompileSql -Silent
}
if ($process.ExitCode -eq 0) {
Write-LogSuccess "$($item.Schema) imported successfully ($afterTotal objects)"
$successCount++
}
else {
Write-LogWarning "$($item.Schema) import completed with warnings"
$successCount++
}
# Clean up copied dump file
if ($item.DumpFile -ne $targetDumpPath -and (Test-Path -Path $targetDumpPath)) {
Remove-Item -Path $targetDumpPath -Force -ErrorAction SilentlyContinue
}
}
catch {
Write-LogError "Failed to import $($item.Schema): $_"
$failCount++
}
}
$totalDuration = (Get-Date) - $startTime
# Summary
Write-LogSection "Import Complete"
Write-LogSuccess "Company import batch completed!"
Write-Log ""
Write-Log "Summary:"
Write-Log " Total companies: $($importList.Count)"
Write-Log " Successful: $successCount"
Write-Log " Failed: $failCount"
Write-Log " Total duration: $([math]::Round($totalDuration.TotalMinutes, 2)) minutes"
Write-Log ""
if ($notFoundList.Count -gt 0) {
Write-Log "Companies skipped (no dump file):"
foreach ($schema in $notFoundList) {
Write-Log " - $schema"
}
}
Write-Log ""
Write-Log "Next steps:"
Write-Log " 1. Run 07-verify-installation.ps1 to verify all schemas"
Close-LogFile -Success ($failCount -eq 0)
exit $(if ($failCount -eq 0) { 0 } else { 1 })
}
catch {
Write-LogError "Import failed: $_"
Write-LogError $_.ScriptStackTrace
Close-LogFile -Success $false
exit 1
}
#Requires -Version 5.1
<#
.SYNOPSIS
Batch import company schemas from Data Pump dump files.
.DESCRIPTION
Imports company schemas from dump files. CRITICAL: Reads passwords from
CONTAFIN_ORACLE.NOM_FIRME table to ensure correct authentication.
For each company:
1. Queries NOM_FIRME for schema name and password
2. Finds matching DMP file in DumpDirectory
3. Creates user with password from NOM_FIRME
4. Runs impdp to import schema
5. Logs progress
.PARAMETER DumpDirectory
Directory containing company DMP files. If not specified, defaults to C:\DMPDIR.
.PARAMETER OracleHome
Oracle home directory. If not specified, auto-detects.
.PARAMETER ServiceName
Database service name. Default: XEPDB1
.PARAMETER SystemPassword
SYSTEM user password. Default: romfastsoft
.PARAMETER ParallelJobs
Number of parallel import jobs. Default: 2
.PARAMETER Companies
Optional array of specific company names to import. If not specified, imports all.
.PARAMETER DryRun
Show what would be imported without actually importing.
.EXAMPLE
.\05-import-companies.ps1 -DumpDirectory "C:\dumps\companies"
.EXAMPLE
.\05-import-companies.ps1 -DumpDirectory "D:\backups" -Companies "FIRMA1","FIRMA2"
.EXAMPLE
.\05-import-companies.ps1 -DumpDirectory "C:\dumps" -DryRun
.NOTES
File Name : 05-import-companies.ps1
Prerequisite : Run 04-create-synonyms-grants.ps1 first
Copyright 2024 : ROMFAST
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string]$DumpDirectory = "C:\DMPDIR",
# Calea fizica a directorului Oracle DMPDIR - de acolo citeste baza.
# Implicit e aceeasi cu DumpDirectory, deci nu trebuie data decat cand
# DMP-urile stau in alta parte decat directorul pe care il vede baza.
[Parameter(Mandatory = $false)]
[string]$DmpDir,
[Parameter(Mandatory = $false)]
[string]$OracleHome,
[Parameter(Mandatory = $false)]
[string]$ServiceName = "XEPDB1",
[Parameter(Mandatory = $false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory = $false)]
[int]$ParallelJobs = 2,
[Parameter(Mandatory = $false)]
[string[]]$Companies,
[Parameter(Mandatory = $false)]
[switch]$DryRun
)
$ErrorActionPreference = 'Stop'
# Source library functions
. "$PSScriptRoot\lib\logging-functions.ps1"
. "$PSScriptRoot\lib\oracle-functions.ps1"
# Initialize logging
$logPath = Join-Path $PSScriptRoot "..\logs\05-import-companies_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
Initialize-LogFile -LogPath $logPath -ScriptName "05-import-companies.ps1"
try {
Write-LogSection "Batch Import Company Schemas"
# Validate DumpDirectory exists
if (-not (Test-Path $DumpDirectory -PathType Container)) {
throw "DumpDirectory not found: $DumpDirectory"
}
Write-Log "Using dump directory: $DumpDirectory"
if ($DryRun) {
Write-LogWarning "DRY RUN MODE - No changes will be made"
}
# Validate Oracle installation
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-LogSuccess "Oracle Home: $oraHome"
# Test connection
Write-Log "Testing database connection..."
if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword)) {
throw "Cannot connect to database. Please verify ServiceName and SystemPassword."
}
Write-LogSuccess "Database connection successful"
# Get company list from NOM_FIRME
Write-LogSection "Reading Company List from NOM_FIRME"
$companySql = @"
SET PAGESIZE 10000 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 500
SELECT schema || '|' || parola
FROM CONTAFIN_ORACLE.NOM_FIRME
WHERE sters = 0
AND schema IS NOT NULL
ORDER BY schema;
EXIT;
"@
$companyResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $companySql -Silent
# Parse company data
$companyData = @{}
foreach ($line in $companyResult -split "`n") {
$line = $line.Trim()
if ($line -match "^([A-Z0-9_]+)\|(.*)$") {
$schema = $Matches[1]
$password = $Matches[2]
if (-not $password) { $password = "ROMFASTSOFT" }
$companyData[$schema] = $password
}
}
Write-Log "Found $($companyData.Count) companies in NOM_FIRME"
if ($companyData.Count -eq 0) {
Write-LogWarning "No companies found in NOM_FIRME"
Close-LogFile -Success $true
exit 0
}
# Filter companies if specified
if ($Companies) {
$filteredData = @{}
foreach ($company in $Companies) {
$companyUpper = $company.ToUpper()
if ($companyData.ContainsKey($companyUpper)) {
$filteredData[$companyUpper] = $companyData[$companyUpper]
}
else {
Write-LogWarning "Company $companyUpper not found in NOM_FIRME"
}
}
$companyData = $filteredData
Write-Log "Filtered to $($companyData.Count) companies"
}
# Find matching dump files
Write-LogSection "Scanning Dump Files"
$dumpFiles = Get-ChildItem -Path $DumpDirectory -Filter "*.dmp" -File
Write-Log "Found $($dumpFiles.Count) DMP files in $DumpDirectory"
# Match companies with dump files
$importList = @()
$notFoundList = @()
foreach ($schema in $companyData.Keys) {
# Numele exact are intaietate. Fara asta, schema DANUBE putea primi
# DANUBE_20200914.dmp - datele altei firme, fara niciun avertisment.
$matchingFile = $dumpFiles | Where-Object { $_.BaseName -ieq $schema } | Select-Object -First 1
if (-not $matchingFile) {
$escaped = [regex]::Escape($schema)
$prefixed = @($dumpFiles | Where-Object { $_.BaseName -imatch "^$escaped[_\.]" })
if ($prefixed.Count -eq 1) {
$matchingFile = $prefixed[0]
}
elseif ($prefixed.Count -gt 1) {
$nume = ($prefixed | ForEach-Object { $_.Name }) -join ', '
Write-LogWarning " - ${schema}: $($prefixed.Count) DMP-uri ambigue ($nume) - redenumeste-l pe cel bun in $schema.dmp"
}
}
if ($matchingFile) {
$importList += [PSCustomObject]@{
Schema = $schema
Password = $companyData[$schema]
DumpFile = $matchingFile.FullName
DumpSize = [math]::Round($matchingFile.Length / 1MB, 2)
}
}
else {
$notFoundList += $schema
}
}
Write-Log "Companies to import: $($importList.Count)"
if ($notFoundList.Count -gt 0) {
Write-LogWarning "Companies without matching dump file: $($notFoundList.Count)"
foreach ($schema in $notFoundList) {
Write-Log " - $schema (no DMP file found)"
}
}
if ($importList.Count -eq 0) {
Write-LogWarning "No companies to import"
Close-LogFile -Success $true
exit 0
}
# Display import plan
Write-LogSection "Import Plan"
$totalSize = ($importList | Measure-Object -Property DumpSize -Sum).Sum
Write-Log "Total data to import: $totalSize MB"
Write-Log ""
Write-Log "Companies to import:"
foreach ($item in $importList) {
Write-Log " - $($item.Schema): $($item.DumpFile) ($($item.DumpSize) MB)"
}
if ($DryRun) {
Write-LogSection "Dry Run Complete"
Write-Log "Would import $($importList.Count) company schemas"
Close-LogFile -Success $true
exit 0
}
# Ensure DMPDIR exists
$dmpDir = if ($DmpDir) { $DmpDir } else { $DumpDirectory }
if (-not (Test-Path -Path $dmpDir)) {
New-Item -ItemType Directory -Path $dmpDir -Force | Out-Null
}
# Process each company
Write-LogSection "Importing Companies"
$successCount = 0
$failCount = 0
$startTime = Get-Date
foreach ($item in $importList) {
Write-LogSection "Importing $($item.Schema)"
try {
# Check if user already exists
$userExists = Test-OracleUser -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $item.Schema
if ($userExists) {
Write-Log "User $($item.Schema) already exists"
# Get current object count
$beforeCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $item.Schema
$beforeTotal = if ($beforeCounts['TOTAL']) { $beforeCounts['TOTAL'] } else { 0 }
Write-Log "Existing objects: $beforeTotal"
}
else {
# Create user
Write-Log "Creating user $($item.Schema)..."
$createUserSql = @"
SET ECHO OFF FEEDBACK ON VERIFY OFF
CREATE USER $($item.Schema)
IDENTIFIED BY "$($item.Password)"
DEFAULT TABLESPACE ROA
TEMPORARY TABLESPACE TEMP
PROFILE DEFAULT;
GRANT CONNECT TO $($item.Schema);
GRANT RESOURCE TO $($item.Schema);
GRANT CREATE MATERIALIZED VIEW TO $($item.Schema);
GRANT CREATE PROCEDURE TO $($item.Schema);
GRANT CREATE SEQUENCE TO $($item.Schema);
GRANT CREATE TABLE TO $($item.Schema);
GRANT CREATE TRIGGER TO $($item.Schema);
GRANT CREATE VIEW TO $($item.Schema);
GRANT DEBUG CONNECT SESSION TO $($item.Schema);
GRANT SELECT ANY TABLE TO $($item.Schema);
GRANT CREATE TYPE TO $($item.Schema);
GRANT UNLIMITED TABLESPACE TO $($item.Schema);
COMMIT;
SELECT 'USER_CREATED' FROM dual;
EXIT;
"@
$createResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $createUserSql -Silent
if ($createResult -match "USER_CREATED") {
Write-LogSuccess "User $($item.Schema) created"
}
else {
throw "Failed to create user $($item.Schema)"
}
}
# Copy dump file to DMPDIR if not already there
$dumpFileName = Split-Path -Path $item.DumpFile -Leaf
$targetDumpPath = Join-Path $dmpDir $dumpFileName
if ($item.DumpFile -ne $targetDumpPath) {
Write-Log "Copying dump file to DMPDIR..."
Copy-Item -Path $item.DumpFile -Destination $targetDumpPath -Force
}
# Run import
Write-Log "Running impdp for $($item.Schema)..."
$impdpPath = Join-Path $oraHome "bin\impdp.exe"
$importLogFile = "$($item.Schema)_import_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
# Use EZConnect format for impdp (handles listener bound to specific IP)
$dbHost = Get-ListenerHost -OracleHome $oraHome
$connString = "SYSTEM/`"$SystemPassword`"@${dbHost}:1521/$ServiceName"
# Check if dump has different schema name (remapping needed)
$remapParam = ""
$dumpBaseName = [System.IO.Path]::GetFileNameWithoutExtension($dumpFileName).ToUpper()
if ($dumpBaseName -ne $item.Schema) {
$remapParam = "remap_schema=$dumpBaseName`:$($item.Schema)"
Write-Log "Schema remap: $dumpBaseName -> $($item.Schema)"
}
$impdpParams = @(
"`"$connString`"",
"directory=DMPDIR",
"dumpfile=$dumpFileName",
"logfile=$importLogFile",
"schemas=$($item.Schema)",
"table_exists_action=REPLACE",
"parallel=1" # Required for Oracle XE
)
if ($remapParam) {
$impdpParams += $remapParam
}
$arguments = $impdpParams -join " "
# Set Oracle environment
$env:ORACLE_HOME = $oraHome
$env:PATH = "$oraHome\bin;$env:PATH"
$env:NLS_LANG = "AMERICAN_AMERICA.AL32UTF8"
$importStart = Get-Date
$process = Start-Process -FilePath $impdpPath -ArgumentList $arguments -Wait -NoNewWindow -PassThru
$importDuration = (Get-Date) - $importStart
Write-Log "Import completed in $([math]::Round($importDuration.TotalMinutes, 2)) minutes"
# Verify import
$afterCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $item.Schema
$afterTotal = if ($afterCounts['TOTAL']) { $afterCounts['TOTAL'] } else { 0 }
$afterInvalid = if ($afterCounts['INVALID']) { $afterCounts['INVALID'] } else { 0 }
Write-Log "Objects after import: $afterTotal"
if ($afterInvalid -gt 0) {
Write-LogWarning "Invalid objects: $afterInvalid"
# Recompile
$recompileSql = @"
BEGIN
DBMS_UTILITY.COMPILE_SCHEMA('$($item.Schema)', FALSE);
END;
/
EXIT;
"@
Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $recompileSql -Silent
}
if ($process.ExitCode -eq 0) {
Write-LogSuccess "$($item.Schema) imported successfully ($afterTotal objects)"
$successCount++
}
else {
Write-LogWarning "$($item.Schema) import completed with warnings"
$successCount++
}
# Clean up copied dump file
if ($item.DumpFile -ne $targetDumpPath -and (Test-Path -Path $targetDumpPath)) {
Remove-Item -Path $targetDumpPath -Force -ErrorAction SilentlyContinue
}
}
catch {
Write-LogError "Failed to import $($item.Schema): $_"
$failCount++
}
}
$totalDuration = (Get-Date) - $startTime
# Summary
Write-LogSection "Import Complete"
Write-LogSuccess "Company import batch completed!"
Write-Log ""
Write-Log "Summary:"
Write-Log " Total companies: $($importList.Count)"
Write-Log " Successful: $successCount"
Write-Log " Failed: $failCount"
Write-Log " Total duration: $([math]::Round($totalDuration.TotalMinutes, 2)) minutes"
Write-Log ""
if ($notFoundList.Count -gt 0) {
Write-Log "Companies skipped (no dump file):"
foreach ($schema in $notFoundList) {
Write-Log " - $schema"
}
}
Write-Log ""
Write-Log "Next steps:"
Write-Log " 1. Run 07-verify-installation.ps1 to verify all schemas"
Close-LogFile -Success ($failCount -eq 0)
exit $(if ($failCount -eq 0) { 0 } else { 1 })
}
catch {
Write-LogError "Import failed: $_"
Write-LogError $_.ScriptStackTrace
Close-LogFile -Success $false
exit 1
}

View File

@@ -1,327 +1,333 @@
#Requires -Version 5.1
<#
.SYNOPSIS
Add a new company schema to ROA Oracle.
.DESCRIPTION
Creates a new company user/schema with either:
- Import from a template DMP file
- Empty schema with basic structures
.PARAMETER CompanyName
Schema name for the new company. Required. Must be uppercase alphanumeric.
.PARAMETER Password
Password for the new company schema. Default: ROMFASTSOFT
.PARAMETER OracleHome
Oracle home directory. If not specified, auto-detects.
.PARAMETER ServiceName
Database service name. Default: XEPDB1
.PARAMETER SystemPassword
SYSTEM user password. Default: romfastsoft
.PARAMETER TemplateDump
Optional path to a template DMP file to import.
.PARAMETER TemplateSchema
Schema name in the template DMP file if different from target (for remap).
.PARAMETER Force
Drop and recreate if user already exists.
.EXAMPLE
.\06-add-company.ps1 -CompanyName "NEWCOMPANY"
.EXAMPLE
.\06-add-company.ps1 -CompanyName "FIRMA2024" -Password "SecurePass123"
.EXAMPLE
.\06-add-company.ps1 -CompanyName "NEWFIRMA" -TemplateDump "C:\dumps\FIRMANOUA.dmp" -TemplateSchema "FIRMANOUA"
.NOTES
File Name : 06-add-company.ps1
Prerequisite : Run 04-create-synonyms-grants.ps1 first
Copyright 2024 : ROMFAST
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidatePattern('^[A-Z0-9_]+$')]
[string]$CompanyName,
[Parameter(Mandatory = $false)]
[string]$Password = "ROMFASTSOFT",
[Parameter(Mandatory = $false)]
[string]$OracleHome,
[Parameter(Mandatory = $false)]
[string]$ServiceName = "XEPDB1",
[Parameter(Mandatory = $false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory = $false)]
[ValidateScript({ Test-Path $_ })]
[string]$TemplateDump,
[Parameter(Mandatory = $false)]
[string]$TemplateSchema,
[Parameter(Mandatory = $false)]
[switch]$Force
)
$ErrorActionPreference = 'Stop'
# Ensure company name is uppercase
$CompanyName = $CompanyName.ToUpper()
# Source library functions
. "$PSScriptRoot\lib\logging-functions.ps1"
. "$PSScriptRoot\lib\oracle-functions.ps1"
# Initialize logging
$logPath = Join-Path $PSScriptRoot "..\logs\06-add-company_${CompanyName}_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
Initialize-LogFile -LogPath $logPath -ScriptName "06-add-company.ps1"
try {
Write-LogSection "Adding New Company: $CompanyName"
# Validate Oracle installation
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-LogSuccess "Oracle Home: $oraHome"
# Test connection
Write-Log "Testing database connection..."
if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword)) {
throw "Cannot connect to database. Please verify ServiceName and SystemPassword."
}
Write-LogSuccess "Database connection successful"
# Check if user already exists
Write-Log "Checking if user $CompanyName exists..."
$userExists = Test-OracleUser -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $CompanyName
if ($userExists) {
if ($Force) {
Write-LogWarning "User $CompanyName exists. Dropping due to -Force flag..."
$dropSql = @"
SET ECHO OFF FEEDBACK ON VERIFY OFF
DROP USER $CompanyName CASCADE;
SELECT 'USER_DROPPED' FROM dual;
EXIT;
"@
$dropResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $dropSql
if ($dropResult -match "USER_DROPPED") {
Write-Log "User $CompanyName dropped"
}
else {
throw "Failed to drop user $CompanyName"
}
}
else {
throw "User $CompanyName already exists. Use -Force to drop and recreate."
}
}
# Create user
Write-LogSection "Creating User $CompanyName"
$createUserSql = @"
SET ECHO OFF FEEDBACK ON VERIFY OFF
PROMPT Creating user $CompanyName...
CREATE USER $CompanyName
IDENTIFIED BY "$Password"
DEFAULT TABLESPACE ROA
TEMPORARY TABLESPACE TEMP
PROFILE DEFAULT;
PROMPT Granting role privileges...
GRANT CONNECT TO $CompanyName;
GRANT RESOURCE TO $CompanyName;
PROMPT Granting system privileges...
GRANT CREATE MATERIALIZED VIEW TO $CompanyName;
GRANT CREATE PROCEDURE TO $CompanyName;
GRANT CREATE SEQUENCE TO $CompanyName;
GRANT CREATE TABLE TO $CompanyName;
GRANT CREATE TRIGGER TO $CompanyName;
GRANT CREATE VIEW TO $CompanyName;
GRANT DEBUG CONNECT SESSION TO $CompanyName;
GRANT SELECT ANY TABLE TO $CompanyName;
GRANT CREATE TYPE TO $CompanyName;
GRANT UNLIMITED TABLESPACE TO $CompanyName;
COMMIT;
SELECT 'USER_CREATED' FROM dual;
EXIT;
"@
$createResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $createUserSql
if ($createResult -match "USER_CREATED") {
Write-LogSuccess "User $CompanyName created successfully"
}
else {
Write-LogError "Failed to create user"
Write-LogDebug $createResult
throw "User creation failed"
}
# Import from template if specified
if ($TemplateDump) {
Write-LogSection "Importing from Template"
Write-Log "Template dump: $TemplateDump"
# Determine template schema for remapping
if (-not $TemplateSchema) {
$TemplateSchema = [System.IO.Path]::GetFileNameWithoutExtension($TemplateDump).ToUpper()
Write-Log "Assuming template schema: $TemplateSchema"
}
# Setup DMPDIR
$dmpDir = "C:\DMPDIR"
if (-not (Test-Path -Path $dmpDir)) {
New-Item -ItemType Directory -Path $dmpDir -Force | Out-Null
}
New-OracleDirectory -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -DirectoryName "DMPDIR" -DirectoryPath $dmpDir
# Copy dump to DMPDIR
$dumpFileName = Split-Path -Path $TemplateDump -Leaf
$targetDumpPath = Join-Path $dmpDir $dumpFileName
if ($TemplateDump -ne $targetDumpPath) {
Write-Log "Copying dump file to DMPDIR..."
Copy-Item -Path $TemplateDump -Destination $targetDumpPath -Force
}
# Run import with remap
Write-Log "Running impdp..."
$impdpPath = Join-Path $oraHome "bin\impdp.exe"
$importLogFile = "${CompanyName}_import_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
$connString = "SYSTEM/`"$SystemPassword`"@$ServiceName"
$impdpParams = @(
"`"$connString`"",
"directory=DMPDIR",
"dumpfile=$dumpFileName",
"logfile=$importLogFile",
"remap_schema=$TemplateSchema`:$CompanyName",
"table_exists_action=REPLACE"
)
$arguments = $impdpParams -join " "
# Set Oracle environment
$env:ORACLE_HOME = $oraHome
$env:PATH = "$oraHome\bin;$env:PATH"
$env:NLS_LANG = "AMERICAN_AMERICA.AL32UTF8"
$importStart = Get-Date
$process = Start-Process -FilePath $impdpPath -ArgumentList $arguments -Wait -NoNewWindow -PassThru
$importDuration = (Get-Date) - $importStart
Write-Log "Import completed in $([math]::Round($importDuration.TotalMinutes, 2)) minutes"
if ($process.ExitCode -eq 0) {
Write-LogSuccess "Template imported successfully"
}
else {
Write-LogWarning "Import completed with warnings (exit code: $($process.ExitCode))"
}
# Clean up copied dump file
if ($TemplateDump -ne $targetDumpPath -and (Test-Path -Path $targetDumpPath)) {
Remove-Item -Path $targetDumpPath -Force -ErrorAction SilentlyContinue
}
}
# Get final object count
Write-LogSection "Verifying Schema"
$counts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $CompanyName
$totalObjects = if ($counts['TOTAL']) { $counts['TOTAL'] } else { 0 }
$invalidObjects = if ($counts['INVALID']) { $counts['INVALID'] } else { 0 }
Write-Log "Total objects: $totalObjects"
if ($invalidObjects -gt 0) {
Write-LogWarning "Invalid objects: $invalidObjects"
# Recompile
Write-Log "Recompiling invalid objects..."
$recompileSql = @"
BEGIN
DBMS_UTILITY.COMPILE_SCHEMA('$CompanyName', FALSE);
END;
/
EXIT;
"@
Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $recompileSql -Silent
# Recheck
$recheckCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $CompanyName
$recheckInvalid = if ($recheckCounts['INVALID']) { $recheckCounts['INVALID'] } else { 0 }
if ($recheckInvalid -lt $invalidObjects) {
Write-LogSuccess "Recompilation fixed $($invalidObjects - $recheckInvalid) objects"
}
}
# Test connection with new user
Write-Log "Testing connection as $CompanyName..."
if (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Username $CompanyName -Password $Password) {
Write-LogSuccess "Connection test successful"
}
else {
Write-LogWarning "Could not connect as $CompanyName"
}
# Summary
Write-LogSection "Company Added"
Write-LogSuccess "Company $CompanyName added successfully!"
Write-Log ""
Write-Log "Summary:"
Write-Log " Schema name: $CompanyName"
Write-Log " Service: $ServiceName"
Write-Log " Objects: $totalObjects"
if ($TemplateDump) {
Write-Log " Template: $TemplateDump"
}
Write-Log ""
Write-Log "Connection string:"
Write-Log " $CompanyName/$Password@$ServiceName"
Close-LogFile -Success $true
exit 0
}
catch {
Write-LogError "Failed to add company: $_"
Write-LogError $_.ScriptStackTrace
Close-LogFile -Success $false
exit 1
}
#Requires -Version 5.1
<#
.SYNOPSIS
Add a new company schema to ROA Oracle.
.DESCRIPTION
Creates a new company user/schema with either:
- Import from a template DMP file
- Empty schema with basic structures
.PARAMETER CompanyName
Schema name for the new company. Required. Must be uppercase alphanumeric.
.PARAMETER Password
Password for the new company schema. Default: ROMFASTSOFT
.PARAMETER OracleHome
Oracle home directory. If not specified, auto-detects.
.PARAMETER ServiceName
Database service name. Default: XEPDB1
.PARAMETER SystemPassword
SYSTEM user password. Default: romfastsoft
.PARAMETER TemplateDump
Optional path to a template DMP file to import.
.PARAMETER TemplateSchema
Schema name in the template DMP file if different from target (for remap).
.PARAMETER Force
Drop and recreate if user already exists.
.EXAMPLE
.\06-add-company.ps1 -CompanyName "NEWCOMPANY"
.EXAMPLE
.\06-add-company.ps1 -CompanyName "FIRMA2024" -Password "SecurePass123"
.EXAMPLE
.\06-add-company.ps1 -CompanyName "NEWFIRMA" -TemplateDump "C:\dumps\FIRMANOUA.dmp" -TemplateSchema "FIRMANOUA"
.NOTES
File Name : 06-add-company.ps1
Prerequisite : Run 04-create-synonyms-grants.ps1 first
Copyright 2024 : ROMFAST
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidatePattern('^[A-Z0-9_]+$')]
[string]$CompanyName,
[Parameter(Mandatory = $false)]
[string]$Password = "ROMFASTSOFT",
[Parameter(Mandatory = $false)]
[string]$OracleHome,
[Parameter(Mandatory = $false)]
[string]$ServiceName = "XEPDB1",
[Parameter(Mandatory = $false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory = $false)]
[ValidateScript({ Test-Path $_ })]
[string]$TemplateDump,
[Parameter(Mandatory = $false)]
[string]$TemplateSchema,
[Parameter(Mandatory = $false)]
[switch]$Force,
# Calea fizica a directorului Oracle DMPDIR, asa cum a fost pusa la instalare.
[Parameter(Mandatory = $false)]
[string]$DmpDir = "C:\DMPDIR"
)
$ErrorActionPreference = 'Stop'
# Ensure company name is uppercase
$CompanyName = $CompanyName.ToUpper()
# Source library functions
. "$PSScriptRoot\lib\logging-functions.ps1"
. "$PSScriptRoot\lib\oracle-functions.ps1"
# Initialize logging
$logPath = Join-Path $PSScriptRoot "..\logs\06-add-company_${CompanyName}_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
Initialize-LogFile -LogPath $logPath -ScriptName "06-add-company.ps1"
try {
Write-LogSection "Adding New Company: $CompanyName"
# Validate Oracle installation
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-LogSuccess "Oracle Home: $oraHome"
# Test connection
Write-Log "Testing database connection..."
if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword)) {
throw "Cannot connect to database. Please verify ServiceName and SystemPassword."
}
Write-LogSuccess "Database connection successful"
# Check if user already exists
Write-Log "Checking if user $CompanyName exists..."
$userExists = Test-OracleUser -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $CompanyName
if ($userExists) {
if ($Force) {
Write-LogWarning "User $CompanyName exists. Dropping due to -Force flag..."
$dropSql = @"
SET ECHO OFF FEEDBACK ON VERIFY OFF
DROP USER $CompanyName CASCADE;
SELECT 'USER_DROPPED' FROM dual;
EXIT;
"@
$dropResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $dropSql
if ($dropResult -match "USER_DROPPED") {
Write-Log "User $CompanyName dropped"
}
else {
throw "Failed to drop user $CompanyName"
}
}
else {
throw "User $CompanyName already exists. Use -Force to drop and recreate."
}
}
# Create user
Write-LogSection "Creating User $CompanyName"
$createUserSql = @"
SET ECHO OFF FEEDBACK ON VERIFY OFF
PROMPT Creating user $CompanyName...
CREATE USER $CompanyName
IDENTIFIED BY "$Password"
DEFAULT TABLESPACE ROA
TEMPORARY TABLESPACE TEMP
PROFILE DEFAULT;
PROMPT Granting role privileges...
GRANT CONNECT TO $CompanyName;
GRANT RESOURCE TO $CompanyName;
PROMPT Granting system privileges...
GRANT CREATE MATERIALIZED VIEW TO $CompanyName;
GRANT CREATE PROCEDURE TO $CompanyName;
GRANT CREATE SEQUENCE TO $CompanyName;
GRANT CREATE TABLE TO $CompanyName;
GRANT CREATE TRIGGER TO $CompanyName;
GRANT CREATE VIEW TO $CompanyName;
GRANT DEBUG CONNECT SESSION TO $CompanyName;
GRANT SELECT ANY TABLE TO $CompanyName;
GRANT CREATE TYPE TO $CompanyName;
GRANT UNLIMITED TABLESPACE TO $CompanyName;
COMMIT;
SELECT 'USER_CREATED' FROM dual;
EXIT;
"@
$createResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $createUserSql
if ($createResult -match "USER_CREATED") {
Write-LogSuccess "User $CompanyName created successfully"
}
else {
Write-LogError "Failed to create user"
Write-LogDebug $createResult
throw "User creation failed"
}
# Import from template if specified
if ($TemplateDump) {
Write-LogSection "Importing from Template"
Write-Log "Template dump: $TemplateDump"
# Determine template schema for remapping
if (-not $TemplateSchema) {
$TemplateSchema = [System.IO.Path]::GetFileNameWithoutExtension($TemplateDump).ToUpper()
Write-Log "Assuming template schema: $TemplateSchema"
}
# Setup DMPDIR
$dmpDir = $DmpDir
if (-not (Test-Path -Path $dmpDir)) {
New-Item -ItemType Directory -Path $dmpDir -Force | Out-Null
}
if (-not (New-OracleDirectory -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -DirectoryName "DMPDIR" -DirectoryPath $dmpDir)) {
throw "Directorul Data Pump DMPDIR ($dmpDir) nu e utilizabil de catre baza."
}
# Copy dump to DMPDIR
$dumpFileName = Split-Path -Path $TemplateDump -Leaf
$targetDumpPath = Join-Path $dmpDir $dumpFileName
if ($TemplateDump -ne $targetDumpPath) {
Write-Log "Copying dump file to DMPDIR..."
Copy-Item -Path $TemplateDump -Destination $targetDumpPath -Force
}
# Run import with remap
Write-Log "Running impdp..."
$impdpPath = Join-Path $oraHome "bin\impdp.exe"
$importLogFile = "${CompanyName}_import_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
$connString = "SYSTEM/`"$SystemPassword`"@$ServiceName"
$impdpParams = @(
"`"$connString`"",
"directory=DMPDIR",
"dumpfile=$dumpFileName",
"logfile=$importLogFile",
"remap_schema=$TemplateSchema`:$CompanyName",
"table_exists_action=REPLACE"
)
$arguments = $impdpParams -join " "
# Set Oracle environment
$env:ORACLE_HOME = $oraHome
$env:PATH = "$oraHome\bin;$env:PATH"
$env:NLS_LANG = "AMERICAN_AMERICA.AL32UTF8"
$importStart = Get-Date
$process = Start-Process -FilePath $impdpPath -ArgumentList $arguments -Wait -NoNewWindow -PassThru
$importDuration = (Get-Date) - $importStart
Write-Log "Import completed in $([math]::Round($importDuration.TotalMinutes, 2)) minutes"
if ($process.ExitCode -eq 0) {
Write-LogSuccess "Template imported successfully"
}
else {
Write-LogWarning "Import completed with warnings (exit code: $($process.ExitCode))"
}
# Clean up copied dump file
if ($TemplateDump -ne $targetDumpPath -and (Test-Path -Path $targetDumpPath)) {
Remove-Item -Path $targetDumpPath -Force -ErrorAction SilentlyContinue
}
}
# Get final object count
Write-LogSection "Verifying Schema"
$counts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $CompanyName
$totalObjects = if ($counts['TOTAL']) { $counts['TOTAL'] } else { 0 }
$invalidObjects = if ($counts['INVALID']) { $counts['INVALID'] } else { 0 }
Write-Log "Total objects: $totalObjects"
if ($invalidObjects -gt 0) {
Write-LogWarning "Invalid objects: $invalidObjects"
# Recompile
Write-Log "Recompiling invalid objects..."
$recompileSql = @"
BEGIN
DBMS_UTILITY.COMPILE_SCHEMA('$CompanyName', FALSE);
END;
/
EXIT;
"@
Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $recompileSql -Silent
# Recheck
$recheckCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
-Password $SystemPassword -SchemaName $CompanyName
$recheckInvalid = if ($recheckCounts['INVALID']) { $recheckCounts['INVALID'] } else { 0 }
if ($recheckInvalid -lt $invalidObjects) {
Write-LogSuccess "Recompilation fixed $($invalidObjects - $recheckInvalid) objects"
}
}
# Test connection with new user
Write-Log "Testing connection as $CompanyName..."
if (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
-Username $CompanyName -Password $Password) {
Write-LogSuccess "Connection test successful"
}
else {
Write-LogWarning "Could not connect as $CompanyName"
}
# Summary
Write-LogSection "Company Added"
Write-LogSuccess "Company $CompanyName added successfully!"
Write-Log ""
Write-Log "Summary:"
Write-Log " Schema name: $CompanyName"
Write-Log " Service: $ServiceName"
Write-Log " Objects: $totalObjects"
if ($TemplateDump) {
Write-Log " Template: $TemplateDump"
}
Write-Log ""
Write-Log "Connection string:"
Write-Log " $CompanyName/$Password@$ServiceName"
Close-LogFile -Success $true
exit 0
}
catch {
Write-LogError "Failed to add company: $_"
Write-LogError $_.ScriptStackTrace
Close-LogFile -Success $false
exit 1
}