i)pdZddlZddlZddlmZddlZejeZgdZ GddZ dS)z) Export dati da Parquet a MS Access (v2) N)Path) IMDB_CODICETIPOLTITOANNODURGENEREREGISTACASTVOTOVOTANTIceZdZdZdZdedefdZ ddeded efd Zd efd Z d ede fdZ defdZ ddededefdZ dS)AccessExporterz'Gestisce export da Parquet a MS Access.cdSN)selfs +C:\PYTHON\ImdbUpdate\src\access_exporter.py__init__zAccessExporter.__init__s  template_path output_pathcFtd|jd|j|jdd|r|tj||td|dS)z? Crea database Access copiando template vuoto. zCopia template Access: z -> Tparentsexist_okzDatabase Access creato: N) loggerinfonameparentmkdirexistsunlinkshutilcopy2)rrrs rcreate_access_dbzAccessExporter.create_access_dbs  Xm.@XXkFVXXYYY   ===      !     ]K000 <{<<=====rIMDB parquet_pathaccess_db_path table_namec ddl}ddl}ddl}td|t |}|d|dz }|dz } d|d} tj | d 5} | d |d dddn #1swxYwYt| d d} d dtD} | }| d| dd}| d| d| d|d|| d|jdd|jd}d|_ |t||jdd|t|d ||~n#|~wxYw || fD]<}|r& |,#t<$rY8wxYw=nF#|| fD]<}|r& |,#t<$rY8wxYw=wxYwtd|dd|dS) z Esporta imdb.parquet in Access via pandas + TransferText. DELETE + import CSV preserva struttura e indici del template. rNzExport Parquet -> Access: _imdb_z.csv schema.ini6DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=;T autocommitzDELETE * FROM []\/, c3"K|] }d|dV dS"Nr.0cs r z:AccessExporter.export_parquet_to_access..B*BBQABBBBBBrzSELECT COUNT(*) FROM '' COPY (SELECT  FROM '') TO 'G' (FORMAT CSV, HEADER true, DELIMITER ',') [<] CharacterSet=UTF-8 Format=Delimited(,) ColNameHeader=True utf-8encodingAccess.ApplicationFzExport completato: ,z record in )tempfileduckdbwin32com.clientrrr gettempdirresolvepyodbcconnectexecutestrreplacejoin_ACCESS_COLUMNSfetchoneas_posixclose write_textr clientDispatchVisibleOpenCurrentDatabaseDoCmd TransferTextCloseCurrentDatabaseQuitr#r$ Exception)rr)r*r+rKrLwin32comtmpcsv_pathini_pathconn_strconn parquet_strcol_strcontotalappfs rexport_parquet_to_accessz'AccessExporter.export_parquet_to_access&s 100000000000 AAABBB++--..66882*2222%* )%))) T::: >d  > > > > > > > > > > > > > >l++33D#>>KiiBB/BBBBBG..""CKK G G G GHHQQSSTUVE KK%.9&&((    IIKKK   cHMccc      /**+?@@CCK ''N(;(;<<< &&q$ CMM4PPP((*** C C)  88:: $ h)  88:: $   J%JJJjJJKKKKKs,J B." J .B22J 5B26DJ A!I-J IJ 9J JJ K#<KK# K K#K K#db_pathcddl}|d}td|jd |jd}|t|t|ddd~| rE| | |tddSdS#t$rV}t d || r| Yd}~dSYd}~dSd}~wwxYw) z8Compatta db_split_IMDB.accdb via DAO (nessuna password).rNz.compact.accdbzCompattamento z...DAO.DBEngine.120 Compattamento completato) Compattamento fallito (non bloccante): )rM with_suffixrrr r[r\CompactDatabaserSr#r$renamercwarning)rrqrd compact_tmpdaoes rcompact_access_dbz AccessExporter.compact_access_dbesw))*:;;  6W\666777 %/**+=>>C   G c+.>.>Ar J J J!!## ;   ""7+++ 9::::: ; ; % % % NNJqJJ K K K!!## %""$$$$$$$$$ % % % % % % %sB%C'' E1AEE source_db destinationsctd|jdt|d|D]} t |}|dd||jz }t j||td|f#t$r*}t d|d|Yd }~d }~wwxYwd S) zA Copia database Access in multiple destinazioni. zCopia z in z destinazioniTrz Copiato in: z Errore copia in z: N) rrr lenrr"r%r&rcrz)rrrdest dest_path dest_filer}s rcopy_to_destinationsz#AccessExporter.copy_to_destinationsws   QY^QQ\1B1BQQQRRR  A AD A JJ t<<<% 6  Y 222 8Y889999 A A A?D??A??@@@@@@@@ A A AsA"B C& C  Cctd d|d}tj|d}|}|d}t}g}|D]5\}} ||vr,||| | |f6tdt|dd } td t|| D]7} | d || | | z| 8||td t|dd dS#tj$r(} td| Yd} ~ dSd} ~ wwxYw)ul Aggiorna OTT_EMESSO in IMDB tramite tabella OTT linkata nel template Access. Usa l'ultimo provider SVOD per ogni titolo (MAX data inizio). UPDATE ... INNER JOIN non è supportato via ODBC su Access: si legge OTT con SELECT semplice, si deduplica in Python, poi si aggiorna IMDB con executemany UPDATE parametrico. z3Arricchimento OTT_EMESSO via tabella linkata OTT...r/r0Fr1z SELECT Qlik_Imdb_id, QliK_Provider FROM OTT WHERE [QliK_Tipo Finestra] = 'SVOD' ORDER BY Qlik_Imdb_id, [Qlik_Data Inizio] DESC z Titoli OTT SVOD distinti: rJirz4UPDATE IMDB SET OTT_EMESSO = ? WHERE IMDB_CODICE = ?z OTT_EMESSO aggiornato: z recordz- Arricchimento OTT fallito (non bloccante): N)rrrPrQcursorrRfetchallsetaddappendrrange executemanycommitrYErrorrz) rr*rhricurrowsseenupdatesimdb_idproviderCHUNKir}s renrich_ott_in_accessz#AccessExporter.enrich_ott_in_accesss  IJJJ% P)%))) >(u===D++--C;;   55DG%) 8 8!$&&HHW%%%NNHg#6777 KKGs7||GGG H H HE1c'llE22  JAa%iK( IIKKK JJLLL KKKCLLKKKK L L L L L| P P P NNN1NN O O O O O O O O O PsE6FG #GG N gemma_db_pathpasswordc 8 ddl}ddl}ddl}t|}|dz }|dz } |dz } |dz } t d| t| dd } d d tD} | }| d | d | d| d|| d| jddt dt%j||t d|jd}d|_ |r%|t|d|n"|t| |jdn#t6$rYnwxYw|jdddt| d||~n#|~wxYwt d |jd}|rd|nd}| t|t| |d|~| !rC|"| #|t dn4#t6$r'}t $d|Yd}~nd}~wwxYwt d t%j||t d!n4#t6$r'}t $d"|Yd}~nd}~wwxYw|| | | fD]<}|!r& |",#t6$rY8wxYw=dS#|| | | fD]<}|!r& |",#t6$rY8wxYw=wxYw)#u Copia tabella IMDB in GemmaLoader.accdb via csv_transfer: 1. DuckDB scrive CSV da parquet (locale) 2. shutil.copy2 GemmaLoader → locale (bypass Access lock) 3. Access.Application importa CSV in GemmaLoader locale (TransferText) 3b. CompactRepair GemmaLoader locale (ottimizzazione) 4. shutil.copy2 locale → GemmaLoader Opzionale — fallisce silenziosamente se GemmaLoader non raggiungibile. rNzGemmaLoader_local.accdbzGemmaLoader_compact.accdbz_imdb_gemma.csvr.zCopia IMDB in GemmaLoader: r4r5r6c3"K|] }d|dV dSr8rr:s rr=z6AccessExporter.copy_to_gemma_loader..r>rr@rArBrCrDrErFrGz# Download GemmaLoader in locale...z- Aggiornamento IMDB locale (csv_transfer)...rIFr(Tz% Compattamento GemmaLoader locale...rsz;pwd=rtrurvz Upload GemmaLoader in rete...z Copia GemmaLoader completataz- Copia GemmaLoader fallita (non bloccante): )%rKrMrLrrNrOrrrSrTrUrVrQrRrXrYrZr r%r&r[r\r]r^ CurrentDb TableDefsDeletercr_r`rarbrxr#r$ryrz)rr)rrrKrdrLre local_gemma compact_pathrfrgrjrkrlrnr| pwd_localer}ros rcopy_to_gemma_loaderz#AccessExporter.copy_to_gemma_loaders; 1000000000008&&(())113366 88 ..\) A-AABBBB l++33D#>>KiiBB/BBBBBG..""C KK%.9&&((    IIKKK   cHMccc      KK= > > > L 4 4 4 KKG H H H/**+?@@CCK >++C ,<,&&((( '' 444KK <=== P P PN1NNOOOOOOOO P KK9 : : : Lm 4 4 4 KK8 9 9 9 9 P P P NNN1NN O O O O O O O O P"<8D  88:: $  k<8D  88:: $ s2D*OA I9',HI9 H!I9 H!!AI9#O9JO.B.MO N'N O NA OQ P %PQP  Q,Q Q QR2RR R RR R)r(r)__name__ __module__ __qualname____doc__rrr'rSrpr~listrrrrrrrrs311    >d > > > > >$! =L=L=L=L =L=L=L=L~%%%%%$AdA$AAAA /P4/P/P/P/PdCGTTT-0Trs   8 $ $ zzzzzzzzzzr