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
340 lines
12 KiB
PowerShell
340 lines
12 KiB
PowerShell
#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
|
|
}
|