# Publicarea scripturilor de baza de date catre clienti Scriptul: `COMUN\utile\publicare_scripturi.ps1`. Inlocuieste pasii manuali din `tasks.exe` (`D:\PROIECTE\fox\tasks`, formularul din `clase\generare_script.vcx`), care raman varianta de rezerva. Cum se scrie un script de migrare: `scripturi-migrare-db.md`. ```powershell powershell -File COMUN\utile\publicare_scripturi.ps1 -DryRun # ce ar face pe luna curenta powershell -File COMUN\utile\publicare_scripturi.ps1 # luna curenta, tot fluxul powershell -File COMUN\utile\publicare_scripturi.ps1 -Luna 2026-08 # alta luna powershell -File COMUN\utile\publicare_scripturi.ps1 -Fisier a.sql,b.sql # doar scripturile date ``` Alte optiuni: `-DoarImport` (fara arhiva), `-DoarArhiva` (doar regenerare arhiva), `-Toate` (republica si scripturile identice), `-FaraVerificareZip`, `-Settings`, `-ZipPath`, `-DirScripturi`, `-Alias`, `-User`, `-Password`, `-SqlPlus`. ## Configurarea Se citeste din `settings.ini`-ul lui `tasks.exe` (`D:\PROIECTE\fox\tasks\settings.ini`, schimbabil cu `-Settings`), aceleasi chei pe care le foloseste formularul; orice parametru dat explicit bate ini-ul. | din ini | ce devine | |---|---| | `[connection] host_database` | nume de **DSN ODBC** — aliasul TNS e cheia `ServerName` a DSN-ului din registri (`CENTRAL` → `ROA_CENTRAL`) | | `[connection] username_database` / `password_database` | utilizatorul Oracle | | `[folder] script_folder` | directorul scripturilor, cu `\SCRIPTURI\` → `\SCRIPTURI_CLAR\` (+ `\\\`) | | `[folder] roa_output` | + `_UPDATE\` = directorul arhivelor | | `[folder] sqlplus_exe` | clientul Oracle (si `TNS_ADMIN` = directorul lui) | | `[script]` | prefixele valide (`CO_`, `FF_`, `RF_`, `SYS_`, `JCS_`) — prefix necunoscut = avertisment | `sqlplus_exe` arata spre `instantclient_19_18`; `instantclient_11_2_0_2` (valoarea de dinainte) are un `tnsnames.ora` vechi, cu `ROA_CENTRAL` pe `10.0.20.122` in loc de `.121`, deci conexiunea expira. `settings.ini` e local (ignorat de SVN). ## Cei doi pasi **1. Import** — fiecare `.sql` intra ca un rand in `CONTAFIN_ORACLE.UPD_DATABASE` de pe `ROA_CENTRAL`, cu `SCRIPT_ORDER = 0` (randul contine scriptul intreg, nu instructiuni parsate), `SCRIPT_NAME` cu MAJUSCULE si `.SQL`, `SCRIPT_TYPE` = ce urmeaza dupa `NN_`, `SCRIPT_CONTENT` = fisierul in clar. `ID` vine din trigger, `DATAORA` din `SYSDATE` implicit, `SCRIPT_APPVER`/`SCRIPT_EXTRA_FILE` raman goale. Daca `SCRIPT_NAME` exista deja, se face **update pe acelasi `id`** — asa se republica un script corectat, pentru ca clientul face `MERGE ... on (a.id = b.id)`. **2. Arhiva lunara** — in `Y:\ROAUPDATE\_UPDATE\` se scriu `database_YYYYMMDD_YYYYMMDD.zip` **si** `databasen_...zip` (identice azi: `database_` era varianta criptata cu `wrap.exe`, nu se mai foloseste). Fiecare contine XML-ul cu acelasi nume ca zip-ul (format `VFPData`/`crsxml`, Windows-1252, CRLF, tab-uri, `script_content` gol) plus cate un `.sql` per script. Indexii `roa_database.xml` / `roa_databasen.xml` listeaza arhivele existente si se schimba doar cand apare o luna noua. Continutul din arhiva se citeste **inapoi din baza**, nu de pe disc — deci arhiva contine exact ce va primi clientul. ## Verificari facute automat - fisier cu sfarsituri de linie LF: **refuzat** (parsarea pe client se face pe `CHR(13)+CHR(10)`); - dupa import, continutul e citit inapoi din CLOB si comparat octet cu octet cu fisierul; la diferenta se opreste inainte de arhiva; - scripturile deja publicate cu acelasi continut se sar (`-Toate` forteaza republicarea); - arhiva generata se citeste inapoi cu cititorul clientului (`pack_utils.decodebase64` + `zip_util_pkg.get_file`) si se compara lungime + MD5 per fisier — o arhiva facuta din PowerShell este citita corect de `zip_util_pkg`; - fisierele inlocuite din `_UPDATE` se copiaza intai in `_UPDATE\_backup\\`. `Y:\ROAUPDATE\_UPDATE\` e **live**: clientii descarca de acolo imediat ce fisierul e pus. ## Ce face clientul `PACK_UPDATE.UpdateScripts` (`COMUN\docs\PACK_UPDATE.pck`) descarca indexul, apoi arhivele care acopera perioada neaplicata, extrage XML-ul cu `zip_util_pkg.get_file`, face `MERGE` in `UPD_DATABASE` pe `id`, apoi pentru fiecare rand cu `script_extra_file` pune continutul fisierului in `script_content` — pentru `.sql` text clar, fara base64 (base64 e doar pentru instructiunile parsate, alta ramura). Actualizare blocata: `depanare-pack-update.md`. ## Detalii de implementare Continutul circula **hexazecimal** in ambele sensuri (`utl_i18n.raw_to_char` / `string_to_raw` cu `WE8MSWIN1252`), pe bucati de 900 de octeti, in blocuri PL/SQL de cate 15 bucati. Motivul: baza e `AL32UTF8`, fisierele sunt CP1252, iar comanda trimisa lui `sqlplus` ramane ASCII pur — nu depinde de `NLS_LANG` si nu poate strica octetii >= 0x80. Consecinta utila: comparatia dintre fisier si CLOB e exacta, nu pe lungime.