Ë
    Ì
âi—Ã  ã                   ó¸   — d Z ddlZddlZddlZddlZddlZddlZddlmZ ddl	m
Z
 ddlmZ ddlmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZmZmZ  G d„ d«      Zy)z
Database checks module
é    N©ÚPath)ÚLogger)ÚSchemaAnalyzer)ÚDockerUtils)ÚModelSchemaAnalyzer)ÚMigrationChecker)ÚINDEX_DEFINITIONSÚTRIGGER_DEFINITIONS)ÚDictÚListÚOptionalc                   óü   — e Zd ZdZdedefd„Zdefd„Zdde	de	fd„Z
de	fd	„Zde	de	fd
„Zde	fd„Zdede	fd„Zdde	de	fd„Zdde	de	fd„Zdede	fd„Zdede	fd„Zde	fd„Zde	fd„Zde	fd„Zdde	de	fd„Zde	fd„Zy)ÚDatabaseChecksz$Check database schema and connectionÚloggerÚproject_dirc                 óx  — || _         || _        t        j                  j	                  |d«      | _        t        |«      | _        t        |«      | _	        t        |«      | _        t        |«      | _        | j
                  t        j                  vr+t        j                  j                  d| j
                  «       y y )NÚbackendr   )r   r   ÚosÚpathÚjoinÚbackend_dirr   Úschema_analyzerr   Údocker_utilsr   Úmodel_schema_analyzerr	   Úmigration_checkerÚsysÚinsert)Úselfr   r   s      ú</home/factor_ks/STREAMA2026/tests/modules/database_checks.pyÚ__init__zDatabaseChecks.__init__   s�   € ØˆŒØ&ˆÔÜŸ7™7Ÿ<™<¨°YÓ?ˆÔÜ-¨kÓ:ˆÔÜ'¨Ó4ˆÔÜ%8¸Ó%EˆÔ"Ü!1°+Ó!>ˆÔð ×Ñ¤3§8¡8Ñ+Ü�H‰H�O‰O˜A˜t×/Ñ/Õ0ð ,ó    Úreturnc                 óú  — t        «       }t        | j                  «      dz  dz  }|j                  «       sh d£S 	 |j	                  d«      D ]r  }|j
                  dk(  rŒ|j                  d¬«      }t        j                  d|«      }|j                  |«       t        j                  d	|«      }|j                  |«       Œt 	 |S # t        $ r-}| j                  j                  d
d|› �«       h d£cY d}~S d}~ww xY w)z6Dynamically extract table names from SQLAlchemy modelsÚappÚmodels¾   ÚtagsÚusersÚstreamsÚchaptersÚcommentsÚsessionsÚstream_tagsÚactivity_logÚtwitch_oauthÚchat_messagesÚsite_settingsÚwatch_historyÚprocessing_jobsú*.pyz__init__.pyúutf-8©Úencodingz'__tablename__\s*=\s*["\']([^"\']+)["\']z\b(\w+)\s*=\s*Table\s*\(ÚDATABASEz#Failed to scan models dynamically: N)Úsetr   r   ÚexistsÚglobÚnameÚ	read_textÚreÚfindallÚupdateÚ	Exceptionr   Úwarning)r   Úexpected_tablesÚ
models_dirÚ
model_fileÚcontentÚtablename_matchesÚtable_matchesÚes           r    Ú _get_expected_tables_from_modelsz/DatabaseChecks._get_expected_tables_from_models$   sý   € ä›%ˆÜ˜$×*Ñ*Ó+¨eÑ3°hÑ>ˆ
à× Ñ Ô"òð ð	Ø(Ÿo™o¨fÓ5ò 6�
Ø—?‘? mÒ3Øà$×.Ñ.¸Ð.Ó@�ä$&§J¡JÐ/YÐ[bÓ$cÐ!Ø×&Ñ&Ð'8Ô9ô !#§
¡
Ð+FÈÓ P�Ø×&Ñ& }Õ5ñ6ð, Ðøô ò 	Ø�K‰K×Ñ 
Ð.QÐRSÐQTÐ,UÔVòõ ûð	ús   »BC Ã	C:Ã"C5Ã/C:Ã5C:Úauto_fixc                 ó¬  — | j                   j                  d«       | j                  «       sy| j                  |«      sy| j	                  |«      sy| j                  |«      sy| j                  «       sy| j                  «       sy| j                  «       sy| j                  |«      sy| j                  «       sy| j                   j                  dd«       y)z1Run all database checks and optionally fix issueszDatabase ChecksFr9   zAll database checks passedT)r   Ú	subheaderÚ_check_database_connectionÚ_compare_schema_with_modelsÚ_check_indexesÚ_check_triggersÚ_check_initial_dataÚcheck_migration_systemÚ_check_model_schema_coverageÚ_check_migration_consistencyÚ_check_all_model_tables_existÚsuccess)r   rL   s     r    Úrun_all_checkszDatabaseChecks.run_all_checksJ   sÎ   € à�‰×ÑÐ/Ô0ð ×.Ñ.Ô0Øð ×/Ñ/°Ô9Øð ×"Ñ" 8Ô,Øð ×#Ñ# HÔ-Øð ×'Ñ'Ô)Øð ×*Ñ*Ô,Øð ×0Ñ0Ô2Øð ×0Ñ0°Ô:Øð ×1Ñ1Ô3Øà�‰×Ñ˜JÐ(DÔEØr"   c                 óâ  — | j                   j                  dd«       	 ddl} |j                  g d¢ddd¬«      }|j                  dk(  r| j                   j                  dd	«       y| j                   j                  dd
|j                  › �«       y# j                  $ r | j                   j                  dd«       Y yt        $ r)}| j                   j                  dd|› �«       Y d}~yd}~ww xY w)z4Check if database connection works using docker execr9   zChecking database connection...r   N)ÚdockerÚexecústreama2026-postgresÚ
pg_isreadyú-UÚstreamaú-dÚstreama2026Té
   ©Úcapture_outputÚtextÚtimeoutzDatabase connection successfulzDatabase connection failed: Fz#Database connection check timed outz"Database connection check failed: )
r   ÚinfoÚ
subprocessÚrunÚ
returncoderX   ÚerrorÚstderrÚTimeoutExpiredrB   )r   ri   ÚresultrJ   s       r    rO   z)DatabaseChecks._check_database_connectionu   sÛ   € à�‰×Ñ˜Ð%FÔGð	Ûà#�Z—^‘^ÚnØ#ØØô	ˆFð × Ñ  AÒ%Ø—‘×#Ñ# JÐ0PÔQØà—‘×!Ñ! *Ð0LÈVÏ]É]ÈOÐ.\Ô]ØøØ×(Ñ(ò 	Ø�K‰K×Ñ˜jÐ*OÔPÙÜò 	Ø�K‰K×Ñ˜jÐ,NÈqÈcÐ*RÔSÜûð	ús$   žAB Á&)B Â+C.Â=C.ÃC)Ã)C.c           
      óÎ  — | j                   j                  dd«       	 ddl} |j                  g d¢ddd¬«      }|j                  dk7  r*| j                   j                  dd	|j                  › �«       y
t        «       }|j                  j                  d«      D ]w  }|j                  «       sŒ|j                  d«      rŒ&d|v sŒ+|j                  d«      }t        |«      dk\  sŒK|d   j                  «       }|sŒa|dk7  sŒg|j                  |«       Œy | j                  «       }d}	||z
  }
|
r˜| j                   j                  dddj                  |
«      › �«       d
}	|rf| j                   j                  dd«       | j!                  |
«      r| j                   j#                  dd«       n| j                   j                  dd«       ||z
  }|rQ|dhk(  r| j                   j                  dd«       n.| j                   j%                  dddj                  |«      › �«       |D ]I  }||v r!| j                   j#                  dd|› d�«       Œ(| j                   j                  dd|› d�«       d
}	ŒK |�r˜| j&                  j)                  «       }| j&                  j+                  «       }|d   �r
|d   j-                  «       D ]6  \  }}| j                   j                  dd|› ddj                  |«      › �«       Œ8 |rž| j                   j                  dd«       | j/                  «       rU| j                   j#                  dd«       | j&                  j1                  ||«      rV| j                   j#                  dd «       n9| j                   j                  dd!«       n| j                   j                  dd"«       d
}	|d#   rO| j                   j                  dd$dj                  |d#   «      › �«       | j                   j                  dd"«       d
}	|	S # j2                  $ r | j                   j                  dd%«       Y y
t4        $ r)}| j                   j                  dd&|› �«       Y d}~y
d}~ww xY w)'z>Compare database tables with expected tables using docker execr9   zComparing tables with models...r   N©
r[   r\   r]   Úpsqlr_   r`   ra   rb   ú-cz\dtTrc   rd   úFailed to get table list: Fú
ú|Úpublicé   é   r=   zMissing tables: ú, z#Attempting to fix missing tables...zMissing tables fixedzFailed to fix missing tablesÚalembic_versionz<Extra table found: alembic_version (expected for migrations)zExtra tables found: zTable ú: existsz	: missingÚmissing_columnsz": missing columns in init-db.sql: z0Attempting to auto-create and apply migration...z*Migration created and applied successfullyz init-db.sql updated successfullyz Failed to create/apply migrationzRRun 'docker compose exec backend alembic revision --autogenerate -m "description"'Úmissing_tableszMissing tables in init-db.sql: zSchema comparison timed outzSchema comparison failed: )r   rh   ri   rj   rk   rl   rm   r:   ÚstdoutÚsplitÚstripÚ
startswithÚlenÚaddrK   r   Ú_fix_missing_tablesrX   rC   r   Úcompare_schemasÚanalyze_modelsÚitemsÚ _auto_create_and_apply_migrationÚauto_fix_init_dbrn   rB   )r   rL   ri   ro   Ú	db_tablesÚlineÚpartsÚ
table_nameÚmodel_tablesÚall_okr~   Úextra_tablesÚschema_differencesÚmodels_infoÚcolumnsrJ   s                   r    rP   z*DatabaseChecks._compare_schema_with_models�   s=  € à�‰×Ñ˜Ð%FÔGðb	Ûð $�Z—^‘^ÚvØ#ØØô	ˆFð × Ñ  AÒ%Ø—‘×!Ñ! *Ð0JÈ6Ï=É=È/Ð.ZÔ[Øô ›ˆIØŸ™×+Ñ+¨DÓ1ò 6�Ø—:‘:•<¨¯©¸Õ(<ÀÈTÒAQØ ŸJ™J s›O�EÜ˜5“z Q“Ø%*¨1¡X§^¡^Ó%5˜
Ú%¨*¸Ó*>Ø%ŸM™M¨*Õ5ð6ð  ×@Ñ@ÓBˆLàˆFð *¨IÑ5ˆNÙØ—‘×!Ñ! *Ð0@ÀÇÁÈ>ÓAZÐ@[Ð.\Ô]Ø�áØ—K‘K×$Ñ$ ZÐ1VÔWØ×/Ñ/°Ô?ØŸ™×+Ñ+¨JÐ8NÕOàŸ™×)Ñ)¨*Ð6TÔUð % |Ñ3ˆLÙàÐ$5Ð#6Ò6Ø—K‘K×$Ñ$ ZÐ3oÕqà—K‘K×'Ñ'¨
Ð6JÈ4Ï9É9ÐUaÓKbÐJcÐ4dÔeð +ò #�
Ø Ñ*Ø—K‘K×'Ñ'¨
°f¸Z¸LÈÐ4QÕRà—K‘K×%Ñ% j°F¸:¸,ÀiÐ2PÔQØ"‘Fð#ò Ø%)×%9Ñ%9×%IÑ%IÓ%KÐ"Ø"×2Ñ2×AÑAÓC�à%Ð&7Ó8Ø/AÐBSÑ/T×/ZÑ/ZÓ/\ò CÑ+˜
 GØŸ™×)Ñ)¨*¸¸z¸lÐJlÐmq×mvÑmvÐw~Ómð  mAð  7Bõ  CðCñ  ØŸ™×(Ñ(¨Ð5gÔhØ×@Ñ@ÔBØ ŸK™K×/Ñ/°
Ð<hÔià#×3Ñ3×DÑDÐEWÐYdÔeØ $§¡× 3Ñ 3°JÐ@bÕ cà ŸK™K×-Ñ-¨jÐ:\Õ]àŸ™×(Ñ(¨ð  6Lô  Mð #�Fà%Ð&6Ò7Ø—K‘K×%Ñ% jÐ4SÐTX×T]ÑT]Ð^pð  rBñ  _Có  UDð  TEð  3Fô  GØ—K‘K×$Ñ$ Zð  2Hô  Ià"�FàˆMøà×(Ñ(ò 	Ø�K‰K×Ñ˜jÐ*GÔHÙÜò 	Ø�K‰K×Ñ˜jÐ,FÀqÀcÐ*JÔKÜûð	úsI   žAP Á38P Â,P Â>P ÃP Ã#P Ã9P Ã?LP Ð+Q$Ð3Q$Ð;QÑQ$c           
      óN  — 	 ddl m } |j                  «       j                  d«      }dddddd	d
dd|› �g	}| j                  j	                  |«      \  }}|s | j
                  j                  dd|› �«       y| j
                  j                  dd«       g d¢}| j                  j	                  |«      \  }}|s | j
                  j                  dd|› �«       y| j
                  j                  dd«       y# t        $ r)}| j
                  j                  dd|› �«       Y d}~yd}~ww xY w)z0Automatically create and apply Alembic migrationr   ©Údatetimeú%Y%m%d_%H%Mr[   Úcomposer\   r   ÚalembicÚrevisionz--autogenerateú-mÚauto_migration_r9   úFailed to create migration: FúMigration created successfully)r[   r™   r\   r   rš   ÚupgradeÚheadúFailed to apply migration: úMigration applied successfullyTzAuto-migration failed: N)	r—   ÚnowÚstrftimer   Ú_run_commandr   rl   rX   rB   )	r   r—   Ú	timestampÚ
cmd_createÚsuccess_createÚoutputÚcmd_upgradeÚsuccess_upgraderJ   s	            r    r‰   z/DatabaseChecks._auto_create_and_apply_migrationø   s7  € ð	å)Ø Ÿ™›×/Ñ/°Ó>ˆIð # I¨v°yÀ)ÈZÐYiÐkoð  tCð  DMð  CNð  rOð  PˆJØ%)×%6Ñ%6×%CÑ%CÀJÓ%OÑ"ˆN˜Fá!Ø—‘×!Ñ! *Ð0LÈVÈHÐ.UÔVØà�K‰K×Ñ 
Ð,LÔMò aˆKØ&*×&7Ñ&7×&DÑ&DÀ[Ó&QÑ#ˆO˜Vá"Ø—‘×!Ñ! *Ð0KÈFÈ8Ð.TÔUØà�K‰K×Ñ 
Ð,LÔMØøäò 	Ø�K‰K×Ñ˜jÐ,CÀAÀ3Ð*GÔHÜûð	ús%   ‚A2C2 Á5AC2 ÃC2 Ã2	D$Ã;DÄD$r~   c                 óþ  — | j                   j                  dd«       t        j                  j	                  | j
                  d«      }t        j                  j                  |«      s| j                   j                  dd«       y	 t        |d«      5 }|j                  «       }ddd«       d|v r„d	vr€| j                   j                  dd
«       d}d|v r|j                  d|dz   «      }n||z  }t        |d«      5 }|j                  |«       ddd«       | j                   j                  dd«       yy# 1 sw Y   Œ’xY w# 1 sw Y   Œ3xY w# t        $ r)}| j                   j                  dd|› �«       Y d}~yd}~ww xY w)z5Attempt to fix missing tables by updating init-db.sqlr9   z*Checking init-db.sql for missing tables...úinit-db.sqlúinit-db.sql not foundFÚrNr2   z(CREATE TABLE IF NOT EXISTS site_settingsz,Adding site_settings table to init-db.sql...ad  

-- Site settings table for configuration
CREATE TABLE IF NOT EXISTS site_settings (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    key VARCHAR(100) UNIQUE NOT NULL,
    value TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- Index for site_settings
CREATE INDEX IF NOT EXISTS idx_site_settings_key ON site_settings(key);

-- Trigger for updated_at on site_settings
CREATE TRIGGER update_site_settings_updated_at BEFORE UPDATE ON site_settings
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
z-CREATE TRIGGER update_twitch_oauth_updated_atÚwz(site_settings table added to init-db.sqlTzFailed to update init-db.sql: )r   rh   r   r   r   r   r;   rl   ÚopenÚreadÚreplaceÚwriterX   rB   )r   r~   Úinit_db_pathÚfrG   Úsite_settings_sqlrJ   s          r    r…   z"DatabaseChecks._fix_missing_tables  sh  € à�‰×Ñ˜Ð%QÔRä—w‘w—|‘| D×$4Ñ$4°mÓDˆä�w‰w�~‰~˜lÔ+Ø�K‰K×Ñ˜jÐ*AÔBØð-	Ü�l CÓ(ð #¨AØŸ&™&›(�÷#ð  .Ñ0Ð5_ÐgnÑ5nØ—‘× Ñ  Ð-[Ô\ð%Ð!ð& CÀgÑMØ%Ÿo™oØGØ)Ð,[Ñ[ó‘Gð
 Ð0Ñ0�Gä˜,¨Ó,ð %°Ø—G‘G˜GÔ$÷%ð —‘×#Ñ# JÐ0ZÔ[Øà÷Q#ð #ú÷D%ð %ûô ò 	Ø�K‰K×Ñ˜jÐ,JÈ1È#Ð*NÔOÜûð	úsI   ÂE
 ÂD2Â!AE
 Ã:D>Ä$E
 Ä2D;Ä7E
 Ä>EÅE
 Å
	E<ÅE7Å7E<c                 ó¬  — | j                   j                  dd«       	 ddl} |j                  g d¢ddd¬«      }|j                  dk7  r*| j                   j                  dd	|j                  › �«       yt        «       }|j                  j                  d
«      D ]i  }|j                  «       sŒd|v sd|v sŒ|j                  d«      }t        |«      dk\  sŒ=|d   j                  «       }|sŒS|dk7  sŒY|j                  |«       Œk h d£}d}	|D ]G  }||v r!| j                   j                  dd|› d�«       Œ(| j                   j                  dd|› d�«       ŒI t        |«      t        |«      z
  }
|
r…| j                   j                  dddj                  |
«      › d�«       |rT|
rR| j                   j                  dd«       | j                  t!        |
«      «      s| j                   j                  dd«       y# j"                  $ r | j                   j                  dd«       Y yt$        $ r)}| j                   j                  dd|› �«       Y d}~yd}~ww xY w)z1Check if required indexes exist using docker execr9   zChecking indexes...r   N)
r[   r\   r]   rr   r_   r`   ra   rb   rs   z\diTrc   rd   zFailed to get index list: ru   Úidx_Úix_rv   rx   ry   r=   >   Úix_streams_statusÚix_comments_user_idÚix_sessions_user_idÚix_site_settings_keyÚix_chapters_stream_idÚix_comments_parent_idÚix_comments_stream_idÚix_streams_created_byÚix_sessions_expires_atÚix_activity_log_user_idÚix_twitch_oauth_user_idÚix_watch_history_user_idÚix_processing_jobs_statusÚix_activity_log_created_atÚix_chat_messages_stream_idÚix_watch_history_stream_idÚix_processing_jobs_stream_idÚix_chapters_game_display_nameÚ ix_watch_history_last_watched_atzIndex r|   ú: missing (may be in migration)zMissing indexes: rz   z (may be in migration)z<Auto-fix enabled - creating migration for missing indexes...z@Failed to create index migration - indexes may be added manuallyzIndex check timed outzIndex check failed: )r   rh   ri   rj   rk   rC   rm   r:   r   r€   r�   rƒ   r„   rX   r   Ú_auto_create_index_migrationÚlistrn   rB   )r   rL   ri   ro   Ú
db_indexesrŒ   r�   Ú
index_nameÚexpected_indexesr�   Úmissing_indexesrJ   s               r    rQ   zDatabaseChecks._check_indexesQ  s.  € à�‰×Ñ˜Ð%:Ô;ðI	Ûð $�Z—^‘^ÚvØ#ØØô	ˆFð × Ñ  AÒ%Ø—‘×#Ñ# JÐ2LÈVÏ]É]ÈOÐ0\Ô]Øô ›ˆJØŸ™×+Ñ+¨DÓ1ò 7�Ø—:‘:•< V¨t¡^°uÀ²}Ø ŸJ™J s›O�EÜ˜5“z Q“Ø%*¨1¡X§^¡^Ó%5˜
Ú%¨*¸Ó*>Ø&ŸN™N¨:Õ6ð7ò Ðð, ˆFØ.ò g�
Ø Ñ+Ø—K‘K×'Ñ'¨
°f¸Z¸LÈÐ4QÕRà—K‘K×$Ñ$ Z°6¸*¸ÐEdÐ1eÕfð	gô "Ð"2Ó3´c¸*³oÑEˆOÙØ—‘× Ñ  Ð/@ÀÇÁÈ?ÓA[Ð@\Ð\rÐ-sÔtñ ¡Ø—K‘K×$Ñ$ ZÐ1oÔpØ×<Ñ<¼TÀ/Ó=RÔSØŸ™×+Ñ+¨JÐ8zÔ{ð øà×(Ñ(ò 	Ø�K‰K×Ñ 
Ð,CÔDÙÜò 	Ø�K‰K×Ñ 
Ð.BÀ1À#Ð,FÔGÜûð	úsC   žAG5 Á38G5 Â,G5 Â5G5 ÃG5 Ã+G5 Ã1DG5 Ç5+IÈ"IÈ*IÉIc                 óX  — | j                   j                  dd«       	 ddl} |j                  g d¢dd¬«      }t	        «       }|j
                  dk(  r“|j                  j                  «       j                  d«      }|D ]e  }|j                  «       sŒ|j                  d	«      rŒ&|j                  d
«      rŒ8d|vsŒ=d|v sŒB|j                  «       }|sŒU|j                  |«       Œg g d¢}d}	g }
|D ]Z  }||v r!| j                   j                  dd|› d�«       Œ(| j                   j                  dd|› d�«       d}	|
j                  |«       Œ\ |	r| j                   j                  dd«       |	S | j                   j                  dd«       |rk|
ri| j                   j                  dd«       | j                  |
«      r | j                   j                  dd«       d}	|	S | j                   j                  dd«       |	S # t        $ r)}| j                   j                  dd|› �«       Y d}~yd}~ww xY w)z2Check if required triggers exist using docker execr9   zChecking triggers...r   N)
r[   r\   r]   rr   r_   r`   ra   rb   rs   zUSELECT trigger_name FROM information_schema.triggers WHERE trigger_schema = 'public';T©re   rf   ru   ú-Útrigger_nameú(Ú_)Úupdate_users_updated_atÚupdate_streams_updated_atÚupdate_comments_updated_atÚupdate_twitch_oauth_updated_atÚupdate_site_settings_updated_atzTrigger u   : exists âœ“rÏ   Fu   All triggers exist âœ“zSome triggers missingz;Attempting to auto-create migration for missing triggers...z2Trigger migration created and applied successfullyz(Failed to create/apply trigger migrationzFailed to check triggers: )r   rh   ri   rj   r:   rk   r   r�   r€   r‚   r„   rX   Úappendrl   Ú_auto_create_trigger_migrationrB   )r   rL   ri   ro   Údb_triggersÚlinesrŒ   rÙ   Úexpected_triggersr�   Úmissing_triggersrJ   s               r    rR   zDatabaseChecks._check_triggers   s"  € à�‰×Ñ˜Ð%;Ô<ð9	Ûð $�Z—^‘^ò HØ#ØôˆFô ›%ˆKØ× Ñ  AÒ%àŸ™×+Ñ+Ó-×3Ñ3°DÓ9�Ø!ò :�Dà—z‘z•|¨D¯O©O¸CÕ,@ÈÏÉÐYgÕIhÐmpÐx|Òm|ð  BEð  IMò  BMØ'+§z¡z£|˜Ú'Ø'ŸO™O¨LÕ9ð:ò!Ðð ˆFØ!ÐØ 1ò :�Ø ;Ñ.Ø—K‘K×'Ñ'¨
°h¸|¸nÈLÐ4YÕZà—K‘K×$Ñ$ Z°8¸L¸>ÐIhÐ1iÔjØ"�FØ$×+Ñ+¨LÕ9ð:ñ Ø—‘×#Ñ# JÐ0HÔIð ˆMð —‘×!Ñ! *Ð.EÔFñ Ñ 0Ø—K‘K×$Ñ$ ZÐ1nÔoØ×:Ñ:Ð;KÔLØŸ™×+Ñ+¨JÐ8lÔmØ!%˜ð ˆMð Ÿ™×)Ñ)¨*Ð6`ÔaàˆMøäò 	Ø�K‰K×Ñ˜jÐ,FÀqÀcÐ*JÔKÜûð	úsJ   žA2G7 ÂG7 Â#G7 Â5G7 Â:G7 Â?G7 ÃBG7 Å,A,G7 ÇG7 Ç7	H)È H$È$H)ræ   c           
      óR  — 	 ddl }ddlm} |j                  «       j                  d«      }ddddd	d
ddd|› �g	} |j                  |ddd¬«      }|j
                  dk7  r*| j                  j                  dd|j                  › �«       yg d¢} |j                  |ddd¬«      }|j
                  dk7  s|j                  j                  «       s| j                  j                  dd«       y|j                  j                  «       j                  d«      d   }	d|	› �}
| j                  j                  dd|	› �«       ddddd	d|
g} |j                  |ddd¬«      }|j
                  dk7  r*| j                  j                  dd|j                  › �«       y|j                  }d}|D ]9  }|dk(  r|dz  }Œ|d k(  r|d!z  }Œ|d"k(  r|d#z  }Œ$|d$k(  r|d%z  }Œ/|d&k(  sŒ5|d'z  }Œ; d}|D ]9  }|dk(  r|d(z  }Œ|d k(  r|d)z  }Œ|d"k(  r|d*z  }Œ$|d$k(  r|d+z  }Œ/|d&k(  sŒ5|d,z  }Œ; |j                  d-«      }t        |«      d.kD  r”|d.   j                  d/«      }d0|› d1�}t        |«      d.kD  r
|d2|› d3�z  }n|d4z  }|d   |z   }| j                  d	z  d
z  d5z  |	z  }	 |j                  |d6¬7«       | j                  j!                  dd8t        |«      › d9�«       g d;¢} |j                  |ddd¬«      }|j
                  dk7  r*| j                  j                  dd<|j                  › �«       y| j                  j!                  dd=«       y# t"        $ r)}| j                  j                  dd:|› �«       Y d}~yd}~ww xY w# t"        $ r)}| j                  j                  dd>|› �«       Y d}~yd}~ww xY w)?zOAutomatically create and apply migration for missing triggers using docker execr   Nr–   r˜   r[   r™   r\   ú-Tr   rš   r›   rœ   Úadd_missing_triggers_Té   rd   r9   rž   F©r[   r™   r\   rè   r   Úshrs   z6ls -t /app/alembic/versions/*.py 2>/dev/null | head -1rc   úNo migration file foundú/éÿÿÿÿú/app/alembic/versions/úMigration file: ÚcatúFailed to read migration file: Ú rà   a      op.execute("""
        DROP TRIGGER IF EXISTS update_site_settings_updated_at ON site_settings;
        CREATE TRIGGER update_site_settings_updated_at
        BEFORE UPDATE ON site_settings
        FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
    """)
rÜ   zí    op.execute("""
        DROP TRIGGER IF EXISTS update_users_updated_at ON users;
        CREATE TRIGGER update_users_updated_at
        BEFORE UPDATE ON users
        FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
    """)
rÝ   zõ    op.execute("""
        DROP TRIGGER IF EXISTS update_streams_updated_at ON streams;
        CREATE TRIGGER update_streams_updated_at
        BEFORE UPDATE ON streams
        FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
    """)
rÞ   zù    op.execute("""
        DROP TRIGGER IF EXISTS update_comments_updated_at ON comments;
        CREATE TRIGGER update_comments_updated_at
        BEFORE UPDATE ON comments
        FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
    """)
rß   a	      op.execute("""
        DROP TRIGGER IF EXISTS update_twitch_oauth_updated_at ON twitch_oauth;
        CREATE TRIGGER update_twitch_oauth_updated_at
        BEFORE UPDATE ON twitch_oauth
        FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
    """)
zm    op.execute("""
        DROP TRIGGER IF EXISTS update_site_settings_updated_at ON site_settings;
    """)
z]    op.execute("""
        DROP TRIGGER IF EXISTS update_users_updated_at ON users;
    """)
za    op.execute("""
        DROP TRIGGER IF EXISTS update_streams_updated_at ON streams;
    """)
zc    op.execute("""
        DROP TRIGGER IF EXISTS update_comments_updated_at ON comments;
    """)
zk    op.execute("""
        DROP TRIGGER IF EXISTS update_twitch_oauth_updated_at ON twitch_oauth;
    """)
údef upgrade():ry   údef downgrade():údef upgrade():
ú

údef downgrade():
ru   ú
def downgrade():
    pass
Úversionsr6   r7   úMigration updated with z trigger statementsz(Failed to write migration file locally: ©r[   r™   r\   rè   r   rš   r    r¡   r¢   r£   zAuto-trigger migration failed: )ri   r—   r¤   r¥   rj   rk   r   rl   rm   r   r�   r€   rh   rƒ   r   Ú
write_textrX   rB   )r   ræ   ri   r—   r§   r¨   Úresult_createÚcmd_findÚresult_findÚlatest_migrationÚmigration_pathÚcmd_readÚresult_readÚmigration_contentÚtrigger_statementsÚtriggerÚdowngrade_statementsÚupgrade_sectionÚafter_upgradeÚnew_upgradeÚnew_contentÚlocal_migration_pathrJ   r«   Úresult_upgrades                            r    râ   z-DatabaseChecks._auto_create_trigger_migrationß  s®  € ðc	ÛÝ)Ø Ÿ™›×/Ñ/°Ó>ˆIð # I¨v°t¸YÈ	ÐS]Ð_cÐg|ð  ~Gð  }Hð  fIð  JˆJØ*˜JŸN™N¨:ÀdÐQUÐ_aÔbˆMà×'Ñ'¨1Ò,Ø—‘×!Ñ! *Ð0LÈ]×MaÑMaÐLbÐ.cÔdØò LˆHØ(˜*Ÿ.™.¨À$ÈTÐ[]Ô^ˆKà×%Ñ%¨Ò*°+×2DÑ2D×2JÑ2JÔ2LØ—‘×!Ñ! *Ð.GÔHØà*×1Ñ1×7Ñ7Ó9×?Ñ?ÀÓDÀRÑHÐØ5Ð6FÐ5GÐHˆNØ�K‰K×Ñ˜ZÐ+;Ð<LÐ;MÐ)NÔOð ! )¨V°T¸9ÀeÈ^Ð\ˆHØ(˜*Ÿ.™.¨À$ÈTÐ[]Ô^ˆKà×%Ñ%¨Ò*Ø—‘×!Ñ! *Ð0OÐP[×PbÑPbÐOcÐ.dÔeØà +× 2Ñ 2Ðð "$ÐØ+ò 
|�ØÐ?Ò?Ø&ð  +@ñ  @Ñ&ØÐ 9Ò9Ø&ð  +`ñ  `Ñ&ØÐ ;Ò;Ø&ð  +hñ  hÑ&ØÐ <Ò<Ø&ð  +lñ  lÑ&ØÐ @Ó@Ø&ð  +|ñ  |Ñ&ð
|ð $&Ð Ø+ò 
]�ØÐ?Ò?Ø(ð  -_ñ  _Ñ(ØÐ 9Ò9Ø(ð  -Oñ  OÑ(ØÐ ;Ò;Ø(ð  -Sñ  SÑ(ØÐ <Ò<Ø(ð  -Uñ  UÑ(ØÐ @Ó@Ø(ð  -]ñ  ]Ñ(ð
]ð 0×5Ñ5Ð6FÓGˆOÜ�?Ó# aÒ'Ø /°Ñ 2× 8Ñ 8Ð9KÓ L�à 0Ð1CÐ0DÀDÐI�ä�}Ó%¨Ò)ØÐ%7Ð8LÐ7MÈRÐ#PÑP‘KàÐ#CÑC�Kà-¨aÑ0°;Ñ>�ð (,×'7Ñ'7¸)Ñ'CÀiÑ'OÐR\Ñ'\Ð_oÑ'oÐ$ð!Ø(×3Ñ3°KÈ'Ð3ÔRØ—K‘K×'Ñ'¨
Ð6MÌcÐRbÓNcÐMdÐdwÐ4xÔyò gˆKØ+˜ZŸ^™^¨KÈÐSWÐacÔdˆNà×(Ñ(¨AÒ-Ø—‘×!Ñ! *Ð0KÈN×LaÑLaÐKbÐ.cÔdØà�K‰K×Ñ 
Ð,LÔMØøô !ò !Ø—K‘K×%Ñ% jÐ4\Ð]^Ð\_Ð2`ÔaÜ ûð!ûô ò 	Ø�K‰K×Ñ˜jÐ,KÈAÈ3Ð*OÔPÜûð	úsk   ‚BM4 ÂAM4 Ã(B'M4 ÆAM4 Ç?M4 ÈA=M4 Ê<L? ËAM4 Ì"M4 Ì?	M1ÍM,Í'M4 Í,M1Í1M4 Í4	N&Í=N!Î!N&rÕ   c                 óê  — 	 ddl }ddlm} |j                  «       j                  d«      }ddddd	d
ddd|› �g	} |j                  |ddd¬«      }|j
                  dk7  r*| j                  j                  dd|j                  › �«       yg d¢} |j                  |ddd¬«      }|j
                  dk7  s|j                  j                  «       s| j                  j                  dd«       y|j                  j                  «       j                  d«      d   }	d|	› �}
| j                  j                  dd|	› �«       ddddd	d|
g} |j                  |ddd¬«      }|j
                  dk7  r*| j                  j                  dd|j                  › �«       y|j                  }t        }d}|D ](  }||v sŒ||   \  }}}|rdnd}|d|› d |› d!|› d"|› d#�	z  }Œ* d}|D ]  }||v sŒ|d$|› d%�z  }Œ |j                  d&«      }t        |«      d'kD  rÉ|d'   j                  d(«      }d)|› d*�}t        |«      d'kD  r
|d+|› d*�z  }n|d,z  }|d   |z   }ddddd	d-d.d/|
› d0|› d1�g} |j                  ||ddd¬2«      }|j
                  dk7  r*| j                  j                  dd3|j                  › �«       y| j                  j                  dd4t        |«      › d5�«       g d6¢} |j                  |ddd¬«      }|j
                  dk7  r*| j                  j                  dd7|j                  › �«       y| j                  j                  dd8«       y# t         $ r)}| j                  j                  dd9|› �«       Y d}~yd}~ww xY w):zNAutomatically create and apply migration for missing indexes using docker execr   Nr–   r˜   r[   r™   r\   rè   r   rš   r›   rœ   Úadd_missing_indexes_Trê   rd   r9   rž   Frë   rc   rí   rî   rï   rð   rñ   rò   ró   rô   zUNIQUE z"    op.execute("""
        CREATE zINDEX IF NOT EXISTS z ON rÚ   z);
    """)
z0    op.execute("""
        DROP INDEX IF EXISTS z;
    """)
rõ   ry   rö   r÷   ru   rù   rú   rì   rs   zcat > z
 << 'EOF'
z
EOF)Úinputre   rf   rg   z Failed to write migration file: rü   z index statementsrý   r¢   r£   zAuto-index migration failed: )ri   r—   r¤   r¥   rj   rk   r   rl   rm   r   r�   r€   rh   r
   rƒ   rX   rB   )r   rÕ   ri   r—   r§   r¨   rÿ   r   r  r  r  r  r  r  Úindex_definitionsÚindex_statementsrÓ   ÚtableÚcolumnÚuniqueÚ
unique_strr	  r
  r  r  r  Ú	cmd_writeÚresult_writer«   r  rJ   s                                  r    rÐ   z+DatabaseChecks._auto_create_index_migrationF  s\  € ðY	ÛÝ)Ø Ÿ™›×/Ñ/°Ó>ˆIð # I¨v°t¸YÈ	ÐS]Ð_cÐg{ð  }Fð  |Gð  fHð  IˆJØ*˜JŸN™N¨:ÀdÐQUÐ_aÔbˆMà×'Ñ'¨1Ò,Ø—‘×!Ñ! *Ð0LÈ]×MaÑMaÐLbÐ.cÔdØò LˆHØ(˜*Ÿ.™.¨À$ÈTÐ[]Ô^ˆKà×%Ñ%¨Ò*°+×2DÑ2D×2JÑ2JÔ2LØ—‘×!Ñ! *Ð.GÔHØà*×1Ñ1×7Ñ7Ó9×?Ñ?ÀÓDÀRÑHÐØ5Ð6FÐ5GÐHˆNØ�K‰K×Ñ˜ZÐ+;Ð<LÐ;MÐ)NÔOð ! )¨V°T¸9ÀeÈ^Ð\ˆHØ(˜*Ÿ.™.¨À$ÈTÐ[]Ô^ˆKà×%Ñ%¨Ò*Ø—‘×!Ñ! *Ð0OÐP[×PbÑPbÐOcÐ.dÔeØà +× 2Ñ 2Ðô !2Ðð  "ÐØ-ò ]�
ØÐ!2Ò2Ø,=¸jÑ,IÑ)�E˜6 6Ù.4¡¸"�JØ$Ð*MÈjÈ\ÐYmÐnxÐmyÐy}ð  Dð  ~Eð  EFð  GMð  FNð  N\ð  )]ñ  ]Ñ$ð	]ð $&Ð Ø-ò z�
ØÐ!2Ò2Ø(Ð._Ð`jÐ_kÐkxÐ,yÑyÑ(ðzð
 0×5Ñ5Ð6FÓGˆOÜ�?Ó# aÒ'Ø /°Ñ 2× 8Ñ 8Ð9KÓ L�à 0Ð1AÐ0BÀ"ÐE�ä�}Ó%¨Ò)ØÐ%7Ð8LÐ7MÈRÐ#PÑP‘KàÐ#CÑC�Kà-¨aÑ0°;Ñ>�ð & y°&¸$À	È4ÐQUÐY_Ð`nÐ_oÐozð  |Gð  {Hð  HMð  XNð  O�	Ø-˜zŸ~™~¨i¸{Ð[_ÐfjÐtvÔw�à×*Ñ*¨aÒ/Ø—K‘K×%Ñ% jÐ4TÐUa×UhÑUhÐTiÐ2jÔkØ à—‘×#Ñ# JÐ2IÌ#ÈoÓJ^ÐI_Ð_pÐ0qÔrò gˆKØ+˜ZŸ^™^¨KÈÐSWÐacÔdˆNà×(Ñ(¨AÒ-Ø—‘×!Ñ! *Ð0KÈN×LaÑLaÐKbÐ.cÔdØà�K‰K×Ñ 
Ð,LÔMØøäò 	Ø�K‰K×Ñ˜jÐ,IÈ!ÈÐ*MÔNÜûð	úsF   ‚BM  ÂAM  Ã(B'M  ÆM  Æ..M  ÇC	M  Ê'A;M  Ì#M  Í 	M2Í	M-Í-M2c                 ó   — | j                   j                  dd«       	 ddl} |j                  g d¢dd¬«      }|j                  dk(  r½|j
                  j                  «       j                  d«      }t        |«      d	k\  r°	 t        |d
   j                  «       «      }|dk(  r| j                   j                  dd«       y|dk\  r!| j                   j                  dd|› d�«       y| j                   j                  dd|› d�«       y| j                   j                  dd|j                  › �«       yy# t        $ r | j                   j                  dd«       Y yw xY w# t        $ r)}| j                   j                  dd|› �«       Y d}~yd}~ww xY w)z.Check if initial data exists using docker execr9   zChecking initial data...r   N)
r[   r\   r]   rr   r_   r`   ra   rb   rs   z#SELECT COUNT(*) FROM site_settings;Tr×   ru   é   rx   z3Site settings table is empty - missing initial dataFé   zSite settings: u	    rows âœ“zSite settings: only z rows (expected at least 5)z#Failed to parse site settings countzFailed to check initial data: )r   rh   ri   rj   rk   r   r�   r€   rƒ   Úintrl   rX   rC   Ú
ValueErrorrm   rB   )r   ri   ro   rä   Úsite_settings_countrJ   s         r    rS   z"DatabaseChecks._check_initial_data£  sŒ  € à�‰×Ñ˜Ð%?Ô@ð#	Ûð $�Z—^‘^ò VØ#ØôˆFð × Ñ  AÒ%àŸ™×+Ñ+Ó-×3Ñ3°DÓ9�Ü�u“: ’?ð%Ü.1°%¸±(·.±.Ó2BÓ.CÐ+à.°!Ò3Ø ŸK™K×-Ñ-¨jÐ:oÔpØ#(Ø0°AÒ5Ø ŸK™K×/Ñ/°
¸oÐNaÐMbÐbkÐ<lÔmØ#'à ŸK™K×/Ñ/°
Ð>RÐSfÐRgð  hCð  =Dô  EØ#(ð
 —‘×!Ñ! *Ð0NÈvÏ}É}ÈoÐ.^Ô_Øð% #øô &ò %ØŸ™×)Ñ)¨*Ð6[Ô\Ù$ð%ûô ò 	Ø�K‰K×Ñ˜jÐ,JÈ1È#Ð*NÔOÜûð	úsH   žA!E Â =D0 Â>%D0 Ã$ D0 Ä)E Ä0%EÅE ÅEÅE Å	FÅ$FÆFc           	      ó  — | j                   j                  dd«       	 ddl}ddl}ddl}ddlm}  || j                  «      }|dz  }|dz  dz  d	z  }|j                  «       s| j                   j                  dd
«       yt        |d«      5 }|j                  «       }	ddd«       |dz  }
|
j                  «       �sD| j                   j                  dd«       g }	j                  d«      }|D �cg c]$  }|j                  «       j                  d«      rŒ#|‘Œ& }}dj                  |«      }d} |j                   |||j"                  |j$                  z  |j&                  z  «      D ]:  }|j)                  d«      j                  «       }|sŒ%||vsŒ*|j+                  |«       Œ< d} |j                   |||j"                  «      D ]:  }|j)                  d«      j                  «       }|sŒ%||vsŒ*|j+                  |«       Œ< n¹t        |
d«      5 }|j                  «       }ddd«       d„ } |	«      } |«      }t-        |«      }t-        |«      }||z
  }||z
  }|s|s| j                   j/                  dd«       y| j                   j                  ddt1        |«      › dt1        |«      › d�«       t3        |«      }|�r³| j                   j                  ddt1        |«      › d�«       |j                  «       �ryt5        |j7                  d«      d¬«      }t9        d„ |dd D «       «      }|�s)| j                   j                  dd«       | j                   j                  dd«        |j:                  g d¢ddt=        |«      ¬ «      }|j>                  dk(  �r–| j                   j/                  dd!«       t5        |j7                  d«      d¬«      }|�r¡|d   } | j                   j                  dd"| j@                  › �«       t        | d«      5 }|j                  «       }!ddd«       !j                  d#«      }"t1        |"«      d$kD  �r.|"d$   j                  d%«      }#d&}$|D ]  }|$d'|› d(�z  }$Œ d)|$› d*�}%t1        |#«      d$kD  r|%d+|#d$   › �z  }%n|%d,z  }%t        | d-«      5 }|jC                  |"d   |%z   «       ddd«       | j                   j/                  dd.t1        |«      › d/�«       |dz  }
t        |
d-«      5 }|jC                  |	«       ddd«       | j                   j/                  dd0«       nF| j                   jE                  dd1|jF                  › �«       n| j                   j/                  dd2«       | j                   j/                  dd3«       y# 1 sw Y   �ŒðxY wc c}w # 1 sw Y   �ŒƒxY w# 1 sw Y   �Œ”xY w# 1 sw Y   �Œ
xY w# 1 sw Y   ŒÂxY w# tH        $ r)}&| j                   jE                  dd4|&› �«       Y d}&~&yd}&~&ww xY w)5zMCheck if Alembic migration system is set up and check for init-db.sql changesr9   zChecking migration system...r   Nr   r®   r   rš   rû   r¯   Tr°   zinit-db.reference.sqlzEReference file init-db.reference.sql not found - using regex fallbackru   z--zdINSERT INTO\s+\w+\s*\([^)]+\)\s*VALUES\s*\([\s\S]+?\)(?:\s*ON CONFLICT\s*\([^)]+\)\s*DO\s+NOTHING)?;zALTER TABLE\s+\w+\s+[^;]+;c                 óè   — g }t        j                  | «      }|D ]U  }t        |«      }t        j                  |dd¬«      }|j	                  «       sŒ7|j                  |j	                  «       «       ŒW |S )z,Parse SQL content into individual statementsTF)Ústrip_commentsÚreindent)ÚsqlparseÚparseÚstrÚformatr�   rá   )Úsql_contentÚ
statementsÚparsedÚstmtÚstmt_strÚ
clean_stmts         r    Úparse_sql_statementszCDatabaseChecks.check_migration_system.<locals>.parse_sql_statementsÿ  sm   € à!#�JÜ%Ÿ^™^¨KÓ8�FØ &ò B˜ä#& t£9˜ä%-§_¡_°XÈdÐ]bÔ%c˜
Ø%×+Ñ+Õ-Ø&×-Ñ-¨j×.>Ñ.>Ó.@ÕAðBð &Ð%r"   z"No changes detected in init-db.sqlzFound z added, z removed statementsz statements from diffr5   )Úreversec              3   óF   ‡K  — | ]  Št        ˆfd „dD «       «      –— Œ y­w)c              3   ór   •K  — | ].  }|j                  «       ‰j                  j                  «       v –— Œ0 y ­w©N)Úlowerr=   )Ú.0Úkeywordr·   s     €r    ú	<genexpr>zBDatabaseChecks.check_migration_system.<locals>.<genexpr>.<genexpr>,  s&   øè ø€ ÒkÀ'˜GŸM™M›O¨q¯v©v¯|©|«~Ô=Ñkùs   ƒ47)ÚinitialÚdataÚschemaN)Úany©r5  r·   s    @r    r7  z8DatabaseChecks.check_migration_system.<locals>.<genexpr>+  s%   øè ø€ ò 1àô ÓkÐMjÔk×kñ1ùs   ƒ!r  z7init-db.sql has changes but no matching migration foundz-Creating migration for init-db.sql changes...)r[   r™   r\   r   rš   r›   rœ   Úsync_init_db_changes)re   rf   ÚcwdrŸ   rñ   rõ   ry   rö   z
    # From init-db.sql
z    op.execute("""
        z

    """)
r÷   rø   rù   z

def downgrade():
    pass
r±   rü   z statements from init-db.sqlz+Reference file updated to match init-db.sqlrž   u,   Migration for init-db.sql changes exists âœ“zMigration system check passedz"Failed to check migration system: )%r   rh   ri   r   r?   Úpathlibr   r   r;   rC   r²   r³   r€   r�   r‚   r   ÚfinditerÚ
IGNORECASEÚ	MULTILINEÚDOTALLÚgrouprá   r:   rX   rƒ   rÑ   Úsortedr<   r;  rj   r'  rk   r=   rµ   rl   rm   rB   )'r   ri   r   r?   r   Úproject_rootr¶   Úversions_dirr·   rG   Úreference_pathÚdata_statementsrä   rŒ   Úclean_linesÚclean_contentÚinsert_patternÚmatchr,  Úalter_patternÚreference_contentr/  Úcurrent_statementsÚreference_statementsÚcurrent_setÚreference_setÚadded_statementsÚremoved_statementsÚrecent_migrationsÚhas_matching_migrationro   Únew_migrationsr  r  r
  r  Ústatements_blockr  rJ   s'                                          r    rT   z%DatabaseChecks.check_migration_systemÌ  s+  € à�‰×Ñ˜Ð%CÔDð_	ÛÛÛÝ$ñ   × 0Ñ 0Ó1ˆLØ'¨-Ñ7ˆLØ'¨)Ñ3°iÑ?À*ÑLˆLà×&Ñ&Ô(Ø—‘×#Ñ# JÐ0GÔHØä�l CÓ(ð #¨AØŸ&™&›(�÷#ð *Ð,CÑCˆNà!×(Ñ(Õ*Ø—‘×#Ñ# JÐ0wÔxà"$�ØŸ™ dÓ+�Ø05Ö[¨¸T¿Z¹Z»\×=TÑ=TÐUYÕ=ZštÐ[�Ð[Ø $§	¡	¨+Ó 6�ð "I�Ø(˜RŸ[™[¨¸ÈÏÉÐXZ×XdÑXdÑHdÐgi×gpÑgpÑHpÓqò 5�EØ Ÿ;™; q›>×/Ñ/Ó1�DÚ ¨OÒ ;Ø'×.Ñ.¨tÕ4ð5ð
 !>�Ø(˜RŸ[™[¨¸ÀrÇ}Á}ÓUò 5�EØ Ÿ;™; q›>×/Ñ/Ó1�DÚ ¨OÒ ;Ø'×.Ñ.¨tÕ4ñ5ô ˜.¨#Ó.ð 1°!Ø()¯©«Ð%÷1ò&ñ &:¸'Ó%BÐ"Ù';Ð<MÓ'NÐ$ô "Ð"4Ó5�Ü #Ð$8Ó 9�ð $/°Ñ#>Ð ð &3°[Ñ%@Ð"á'Ñ0BØ—K‘K×'Ñ'¨
Ð4XÔYØà—‘× Ñ  ¨v´cÐ:JÓ6KÐ5LÈHÔUXÐYkÓUlÐTmð  nAð  .Bô  Cô #'Ð'7Ó"8�ÚØ—‘× Ñ  ¨v´c¸/Ó6JÐ5KÐK`Ð-aÔbð  ×&Ñ&Õ(ä(.¨|×/@Ñ/@ÀÓ/HÐRVÔ(WÐ%Ü-0ñ 1à!2°2°AÐ!6ô1ó .Ð*ò
 2ØŸ™×+Ñ+¨JÐ8qÔrØŸ™×(Ñ(¨Ð5dÔeð "0 §¡ÚyØ+/Ø!%Ü # LÓ 1ô	"˜ð "×,Ñ,°Ó1Ø ŸK™K×/Ñ/°
Ð<\Ô]ô .4°L×4EÑ4EÀfÓ4MÐW[Ô-\˜NÚ-Ø3AÀ!Ñ3DÐ 0Ø $§¡× 0Ñ 0°Ð?OÐP`×PeÑPeÐOfÐ=gÔ hô &*Ð*:¸CÓ%@ð !AÀAØ89¿¹»Ð$5÷!Að 3D×2IÑ2IÐJZÓ2[ Ü#& Ó#7¸!Ó#;Ø4CÀAÑ4F×4LÑ4LÐM_Ó4` Mð 8TÐ$4Ø0?ò %n¨Ø(8Ð>ZÐ[_ÐZ`Ð`lÐ<mÑ(mÑ(8ð%nð 5EÐEUÐDVÐVZÐ2[ Kä'*¨=Ó'9¸AÒ'=Ø(3Ð9KÈMÐZ[ÑL\ÐK]Ð7^Ñ(^©à(3Ð7YÑ(Y¨ô *.Ð.>ÀÓ)Dð %RÈØ()¯©°ÀÑ0BÀ[Ñ0PÔ(Q÷%Rð %)§K¡K×$7Ñ$7¸
ÐF]Ô^aÐbqÓ^rÐ]sð  tPð  EQô  %Rð 6BÐD[Ñ5[ NÜ)-¨n¸cÓ)Bð %9ÀaØ()¯©°Ô(8÷%9ð %)§K¡K×$7Ñ$7¸
ÐDqÕ$rà ŸK™K×-Ñ-¨jÐ<XÐY_×YfÑYfÐXgÐ:hÕiàŸ™×+Ñ+¨JÐ8fÔgà�K‰K×Ñ 
Ð,KÔLØ÷Y#ñ #üò \÷ 1ñ 1ú÷V!Añ !Aú÷*%Rñ %Rú÷%9ð %9ûô ò 	Ø�K‰K×Ñ˜jÐ,NÈqÈcÐ*RÔSÜûð	úsÎ   žA W Á?W ÂV
ÂAW Ã-$VÄVÄA1W ÆW ÆAW Ç%W Ç* W È
VÈAW É7FW ÐV)ÐA?W ÒV6Ò.AW Ó0WÔBW Ö
VÖW ÖV&Ö!W Ö)V3Ö.W Ö6W Ö;W ×W×W ×	X×W<×<Xc                 ó¸  — | j                   j                  dd«       	 | j                  j                  «       }| j                   j                  dd|d   › d�«       | j                   j                  dd|d   › �«       | j                   j                  dd|d	   › �«       |d
   r–t	        d„ |d
   j                  «       D «       «      }| j                   j                  dd|› d�«       |d
   j                  «       D ]=  \  }}| j                   j                  dd|› ddj                  d„ |D «       «      › �«       Œ? |d   rCt	        d„ |d   j                  «       D «       «      }| j                   j                  dd|› d�«       |j                  d«      r“t	        d„ |d   j                  «       D «       «      }|dkD  rk| j                   j                  dd|› �«       |d   j                  «       D ]6  \  }}| j                   j                  dd|› ddj                  |«      › �«       Œ8 y# t        $ r)}	| j                   j                  dd|	› �«       Y d}	~	yd}	~	ww xY w)z5Check model-schema coverage using ModelSchemaAnalyzerr9   z!Checking model-schema coverage...zModel-Schema coverage: Úcoverage_percentageú%zTotal model fields: Útotal_model_fieldszCovered fields: Úcovered_fieldsÚmissing_from_schemasc              3   ó2   K  — | ]  }t        |«      –— Œ y ­wr3  ©rƒ   ©r5  Úfieldss     r    r7  z>DatabaseChecks._check_model_schema_coverage.<locals>.<genexpr>~  s   è ø€ Ò#o°F¤C¨§KÑ#oùó   ‚zMissing from schemas: z fieldsz  z: rz   c              3   ó&   K  — | ]	  }|d    –— Œ y­w)r=   N© r<  s     r    r7  z>DatabaseChecks._check_model_schema_coverage.<locals>.<genexpr>�  s   è ø€ ÒMhÐ\]ÈaÐPVÍiÑMhùs   ‚Úextra_in_schemasc              3   ó2   K  — | ]  }t        |«      –— Œ y ­wr3  ra  rb  s     r    r7  z>DatabaseChecks._check_model_schema_coverage.<locals>.<genexpr>„  s   è ø€ Ò!i°&¤# f§+Ñ!iùrd  zExtra in schemas: z fields (may be intentional)Útype_mismatchesc              3   ó2   K  — | ]  }t        |«      –— Œ y ­wr3  ra  )r5  Ú
mismatchess     r    r7  z>DatabaseChecks._check_model_schema_coverage.<locals>.<genexpr>‰  s   è ø€ Ò)x¸j¬#¨j¯/Ñ)xùrd  r   zType mismatches found: Tz'Failed to check model-schema coverage: N)r   rh   r   Úcompare_model_schema_coverageÚsumÚvaluesrC   rˆ   r   ÚgetrB   rl   )
r   Úcoverage_reportÚmissing_countÚ
model_namerc  Úextra_countÚtype_mismatch_countrŽ   rk  rJ   s
             r    rU   z+DatabaseChecks._check_model_schema_coverager  sa  € à�‰×Ñ˜Ð%HÔIð	Ø"×8Ñ8×VÑVÓXˆOà�K‰K×Ñ˜ZÐ+BÀ?ÐShÑCiÐBjÐjkÐ)lÔmØ�K‰K×Ñ˜ZÐ+?ÀÐPdÑ@eÐ?fÐ)gÔhØ�K‰K×Ñ˜ZÐ+;¸OÐL\Ñ<]Ð;^Ð)_Ô`àÐ5Ò6Ü #Ñ#o¸oÐNdÑ>e×>lÑ>lÓ>nÔ#oÓ o�Ø—‘×#Ñ# JÐ2HÈÈÐW^Ð0_Ô`Ø*9Ð:PÑ*Q×*WÑ*WÓ*Yò lÑ&�J Ø—K‘K×$Ñ$ Z°2°j°\ÀÀDÇIÁIÑMhÐagÔMhÓDhÐCiÐ1jÕkðlð Ð1Ò2Ü!Ñ!i¸OÐL^Ñ<_×<fÑ<fÓ<hÔ!iÓi�Ø—‘× Ñ  Ð/AÀ+ÀÐNjÐ-kÔlð ×"Ñ"Ð#4Ô5Ü&)Ñ)xÈOÐ\mÑLn×LuÑLuÓLwÔ)xÓ&xÐ#Ø&¨Ò*Ø—K‘K×'Ñ'¨
Ð6MÐNaÐMbÐ4cÔdØ2AÐBSÑ2T×2ZÑ2ZÓ2\ò aÑ.˜
 JØŸ™×(Ñ(¨°r¸*¸ÀRÈÏ	É	ÐR\ÓH]ÐG^Ð5_Õ`ðað øäò 	Ø�K‰K×Ñ˜jÐ,SÐTUÐSVÐ*WÔXÜûð	ús   žHH' È'	IÈ0IÉIc                 óš  — | j                   j                  dd«       	 | j                  j                  «       }|d   r| j                   j	                  dd«       n^| j                   j                  dd«       |d   r| j                   j                  dd«       |d   r| j                   j                  dd	«       |d
   d   rW| j                   j                  dd«       d|d
   v r4| j                   j                  dddj                  |d
   d   «      › �«       y# t        $ r)}| j                   j                  dd|› �«       Y d}~yd}~ww xY w)z2Check migration consistency using MigrationCheckerr9   z!Checking migration consistency...Úis_up_to_datezMigrations are up to datez Migrations may not be up to dateÚneeds_upgradeu     â†’ Database needs upgradeÚdrift_detectedu     â†’ Migration drift detectedÚmodel_changesÚneeds_migrationzHModel changes detected that may need migration (file modifications only)Úmodified_modelsz  Modified models: rz   Tz'Failed to check migration consistency: N)	r   rh   r   Úcheck_migration_consistencyrX   rC   r   rB   rl   )r   rL   Úconsistency_reportrJ   s       r    rV   z+DatabaseChecks._check_migration_consistency–  sN  € à�‰×Ñ˜Ð%HÔIð	Ø!%×!7Ñ!7×!SÑ!SÓ!UÐà! /Ò2Ø—‘×#Ñ# JÐ0KÕLà—‘×#Ñ# JÐ0RÔSØ% oÒ6Ø—K‘K×$Ñ$ ZÐ1OÔPØ%Ð&6Ò7Ø—K‘K×'Ñ'¨
Ð4TÔUà! /Ñ2Ð3DÒEØ—‘× Ñ  Ð-wÔxØ$Ð(:¸?Ñ(KÑKØ—K‘K×$Ñ$ ZÐ3FÀtÇyÁyÐQcÐdsÑQtð  vGñ  RHó  HIð  GJð  2Kô  Lð øäò 	Ø�K‰K×Ñ˜jÐ,SÐTUÐSVÐ*WÔXÜûð	ús   žC9D Ä	E
Ä!EÅE
c                 ó   — | j                   j                  dd«       	 ddl} |j                  g d¢ddd¬«      }|j                  dk7  r*| j                   j                  dd	|j                  › �«       y
t        «       }|j                  j                  d«      D ]w  }|j                  «       sŒ|j                  d«      rŒ&d|v sŒ+|j                  d«      }t        |«      dk\  sŒK|d   j                  «       }|sŒa|dk7  sŒg|j                  |«       Œy h d£}d}||z
  }	|	r2| j                   j                  dddj                  |	«      › �«       d
}|S | j                   j                  dd«       |S # j                   $ r | j                   j                  dd«       Y y
t"        $ r)}
| j                   j                  dd|
› �«       Y d}
~
y
d}
~
ww xY w)z+Check if all model tables exist in databaser9   z"Checking all model tables exist...r   Nrq   Trc   rd   rt   Fru   rv   rw   rx   ry   r=   r'   zMissing tables in database: rz   z"All model tables exist in databasezTable check timed outzFailed to check model tables: )r   rh   ri   rj   rk   rl   rm   r:   r   r€   r�   r‚   rƒ   r„   r   rX   rn   rB   )r   ri   ro   r‹   rŒ   r�   rŽ   r�   r�   r~   rJ   s              r    rW   z,DatabaseChecks._check_all_model_tables_exist²  s¯  € à�‰×Ñ˜Ð%IÔJð0	Ûð $�Z—^‘^ÚvØ#ØØô	ˆFð × Ñ  AÒ%Ø—‘×!Ñ! *Ð0JÈ6Ï=É=È/Ð.ZÔ[Øô ›ˆIØŸ™×+Ñ+¨DÓ1ò 6�Ø—:‘:•<¨¯©¸Õ(<ÀÈTÒAQØ ŸJ™J s›O�EÜ˜5“z Q“Ø%*¨1¡X§^¡^Ó%5˜
Ú%¨*¸Ó*>Ø%ŸM™M¨*Õ5ð6òˆLð ˆFØ)¨IÑ5ˆNáØ—‘×!Ñ! *Ð0LÈTÏYÉYÐWeÓMfÐLgÐ.hÔiØ�ð ˆMð —‘×#Ñ# JÐ0TÔUàˆMøà×(Ñ(ò 	Ø�K‰K×Ñ˜jÐ*AÔBÙÜò 	Ø�K‰K×Ñ˜jÐ,JÈ1È#Ð*NÔOÜûð	úsO   žAE/ Á38E/ Â,E/ Â>E/ ÃE/ Ã#E/ Ã9E/ Ã?AE/ ÅE/ Å/+GÆGÆ$GÇGN)T)F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r'  r!   r:   rK   ÚboolrY   rO   rP   r‰   r…   rQ   rR   rÑ   râ   rÐ   rS   rT   rU   rV   rW   rf  r"   r    r   r      s  „ Ù.ð1˜vð 1°Có 1ð$°#ó $ñL) tð )°tó )ðV¨Dó ð6f°Dð f¸Tó fðP°$ó ð@7°#ð 7¸$ó 7ñrM tð M¸ó Mñ^=¨ð =¸ó =ð~e¸tð eÈó eðN[¸Dð [ÀTó [ðz' Tó 'ðRd¨ó dðL"¨dó "ñH°Tð Àdó ð84¨tô 4r"   r   )r‚  r   r   ri   Údifflibr?   r%  r?  r   Útests.utils.loggerr   Útests.utils.schema_analyzerr   Útests.utils.docker_utilsr   Ú!tests.utils.model_schema_analyzerr   Útests.utils.migration_checkerr	   Útests.utils.db_constantsr
   r   Útypingr   r   r   r   rf  r"   r    ú<module>rŒ     sE   ðñó 
Û 
Û Û Û 	Û Ý Ý %Ý 6Ý 0Ý AÝ :ß Kß 'Ñ '÷Rò Rr"   