Ë
    âß²jg  ã            	      óø   — d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	m
Z
 ddddej                  dd	dd
œ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Zej                  ddœdd„«       Zdd„Zej                  dd„«       Zy)uÍ  Shared SQLite primitives for the small per-profile / board stores.

``open_db`` is the one connect + PRAGMA stack; ``transaction`` is the one commit-and-ALWAYS-close
shape. Every hand-rolled ``_connect``/``_transaction`` pair used to re-carry the #69567 fix (a
``with conn:`` only commits â€” it never closes, so each call leaked a connection and its WAL/SHM fds
until GC, exhausting ``RLIMIT_NOFILE`` on long-running gateways) and at least one copy missed it.
é    )ÚannotationsN)ÚPath)ÚCallableÚIteratoriˆ  TFé   )Úbusy_timeout_msÚwalÚforeign_keysÚsynchronous_fullÚrow_factoryÚcheck_same_threadÚwal_lock_retriesÚ
initializec       	        óz  — ddl m}
 t        | «      } | j                  j	                  dd¬«       t        j                  | |dz  |¬«      }	 ||_        |j                  dt        |«      › �«       |rt        |«      D ]  }	  |
||¬«        n |r|j                  d«       |r|j                  d«       |	� |	|«       |S # t
        j                  $ rJ}t        |«      j                  «       d	k7  s|d
z   |k(  r‚ t        j                  dd|z  z  «       Y d}~Œ›d}~ww xY w# t         $ r |j#                  «        ‚ w xY w)uÉ  Open ``path`` (parent created), apply the PRAGMA set, run ``initialize``; closed if anything raises.

    ``busy_timeout_ms`` is the single busy knob: it is passed as ``connect(timeout=)`` AND set as the
    explicit PRAGMA so it is observable. ``wal=True`` goes through ``apply_wal_with_fallback`` â€” the
    only journal-mode setter that carries the WAL-reset-bug gate, the network-FS silent-refusal
    fallback and the never-live-downgrade invariant; a raw ``PRAGMA journal_mode=WAL`` bypasses all
    three. Only the transient ``database is locked`` from that pragma is retried (``wal_lock_retries``):
    a first opener initializing a shared DB can make it ignore the busy timeout, notably on Windows.
    r   )Úapply_wal_with_fallbackT)ÚparentsÚexist_okiè  )Útimeoutr   zPRAGMA busy_timeout=)Údb_labelzdatabase is lockedr   g{®Gáz„?é   NzPRAGMA foreign_keys=ONzPRAGMA synchronous=FULL)Úhermes_state_walr   r   ÚparentÚmkdirÚsqlite3Úconnectr   ÚexecuteÚintÚrangeÚOperationalErrorÚstrÚlowerÚtimeÚsleepÚBaseExceptionÚclose)Úpathr   r   r	   r
   r   r   r   r   r   r   ÚconnÚattemptÚexcs                 ú;/home/ubuntu/.hermes/hermes-agent/hermes_cli/sqlite_util.pyÚopen_dbr+      s6  € õ, 9ä�‹:€DØ‡K�K×Ñ˜d¨TÐÔ2ä�?‰?˜4¨¸4Ñ)?ÐSdÔe€DðØ&ˆÔØ�‰Ð+¬C°Ó,@Ð+AÐBÔCÙÜ Ð!1Ó2ò 4�ð4Ù+¨D¸8ÕDÙð4ñ Ø�L‰LÐ1Ô2ÙØ�L‰LÐ2Ô3ØÐ!Ù�tÔð €Køô ×/Ñ/ò 4Ü˜3“x—~‘~Ó'Ð+?Ò?À7ÈQÁ;ÐRbÒCbØÜ—J‘J˜t q¨'¡zÑ2×3Ñ3ûð4ûô ò Ø�
‰
ŒØðús7   Á4D Â 
B?Â
3D Â?DÃA DÄD ÄDÄD ÄD:)Ú	immediatec             #  ó´   K  — 	 |r| j                  d«       | 5  | –— ddd«       | j                  «        y# 1 sw Y   ŒxY w# | j                  «        w xY w­w)z\Commit on success, roll back on error, and ALWAYS close ``conn`` (see the module docstring).úBEGIN IMMEDIATEN)r   r%   )r'   r,   s     r*   Útransactionr/   F   sN   è ø€ ðÙØ�L‰LÐ*Ô+Øñ 	ØŠJ÷	ð 	�
‰
�÷	ð 	ûð 	�
‰
�üs.   ‚A„A ™7žA ¦A·A ¼A ÁAÁAc                ó¬   — 	 | j                  d|› d|› �«       y# t        j                  $ r&}dt        |«      j	                  «       v rY d}~y‚ d}~ww xY w)a#  ``ALTER TABLE <table> ADD COLUMN <ddl>``, idempotent across races: True when this call added
    it, False on the ``duplicate column name`` a concurrent migrator caused.

    ``column`` is the human-readable name for the call site; ``ddl`` carries the actual definition. See
    #21708.
    zALTER TABLE z ADD COLUMN Tzduplicate column nameNF)r   r   r   r    r!   )r'   ÚtableÚcolumnÚddlr)   s        r*   Úadd_column_if_missingr4   R   sR   € ðØ�‰�| E 7¨,°s°eÐ<Ô=ØøÜ×#Ñ#ò Ø"¤c¨#£h§n¡nÓ&6Ñ6ÜØûðús   ‚ šA­AÁAÁAc              #  óÌ   K  — | j                  d«       	 | –— | j                  d«       y# t        $ r- 	 | j                  d«       ‚ # t        j                  $ r Y ‚ w xY ww xY w­w)zæAn IMMEDIATE write transaction on a long-lived connection (stays open). The explicit ROLLBACK is
    guarded so a SQLite auto-rollback (no transaction left under EIO / contention / corruption) cannot
    shadow the original error.r.   ÚCOMMITÚROLLBACKN)r   Ú	Exceptionr   r   )r'   s    r*   Ú	write_txnr9   b   sp   è ø€ ð
 	‡L�LÐ"Ô#ð	ØŠ
ð 	�‰�XÕøô ò ð	Ø�L‰L˜Ô$ð 	øô ×'Ñ'ò 	ØØð	úðüs<   ‚A$•+ ™A$«	A!µAÁA!ÁAÁA!ÁAÁA!Á!A$)r&   z
Path | strr   r    r   r   r	   Úboolr
   r:   r   r:   r   r:   r   r   r   z+Callable[[sqlite3.Connection], None] | NoneÚreturnúsqlite3.Connection)r'   r<   r,   r:   r;   zIterator[sqlite3.Connection])
r'   r<   r1   r    r2   r    r3   r    r;   r:   )r'   r<   )Ú__doc__Ú
__future__r   Ú
contextlibr   r"   Úpathlibr   Útypingr   r   ÚRowr+   Úcontextmanagerr/   r4   r9   © ó    r*   ú<module>rF      sà   ðñõ #ã Û Û Ý ß %ð  ØØØ"Ø—‘Ø"ØØ>Bñ1Ø
ð1ð ð1ð ð	1ð
 
ð1ð ð1ð ð1ð ð1ð ð1ð <ð1ð ó1ðh ×ÑØ?Dô ó ðóð  ×Ñòó ñrE   