
    Uj                        d Z ddlmZ ddlZddlZ ej
                  dej                        Zd ZddZ	d Z
ddZddd	Zddd
Zy)u  Ultron master DB logic for the jarvis-tools service (Railway).
Full Supabase SQL (read + write). Creds from env SUPABASE_URL +
SUPABASE_DB_PASSWORD. Seatbelt on drop/truncate/where-less delete. Isolated from
the memory service (psycopg only — no ML deps).
    )annotationsNz\b(drop|truncate)\bc                    t         j                  j                  dd      } t         j                  j                  dd      }| r|syt        j                  d|       }|sy|j                  d      }t         j                  j                  dd      }|r0|t        t         j                  j                  dd	            d
| |fS d| ddd|fS )u  (host, port, user, password). Prefers the IPv4 pooler when
    SUPABASE_POOLER_HOST is set (required from Railway — the direct
    db.<ref>.supabase.co host is IPv6-only and unreachable there). Falls back to
    the direct connection otherwise (fine from a Mac/VPS).SUPABASE_URL SUPABASE_DB_PASSWORDNz//([^.]+)\.   SUPABASE_POOLER_HOSTSUPABASE_POOLER_PORT5432z	postgres.zdb.z.supabase.coi8  postgres)osenvirongetresearchgroupint)urlpwmrefpoolers        L/Users/ahmed/devFolder/Ultron/claude-voice/jarvis-tools-service/ultron_db.py_credsr      s    
 **..
,C	.	3BB
		.#&A
''!*CZZ^^2B7FBJJNN+A6JKC5!2' 	'#l#T:r::    c                     t               d uS )N)r    r   r   
configuredr   "   s    84r   c                 j    dd l } t               \  }}}}| j                  d| d| d| d| d	dd	      S )
Nr   zhost=z port=z user=z
 password=z  dbname=postgres sslmode=require   T)connect_timeout
autocommit)psycopgr   connect)r#   hostportuserr   s        r   _connectr(   &   sU    !8D$b??
vVD6vZt <* 	+<>4  Q Qr   c                    | j                         }t        j                  |      ryt        j                  d|      r&t        j                  d|t        j
                        syy)NTz(?is)^\s*(delete|update)\bz	\bwhere\bF)strip_DANGERr   r   matchI)sqlss     r   _needs_confirmr0   .   sE    		A~~a	xx-q1		,2440r   c                   t        |       j                         } | syt        |       rt        |      j                         dk7  ryt	               5 }|j                  |       }|j                  r|j                  D cg c]  }|j                   }}|j                  d      }|s
	 d d d        ydj                  |      }dj                  d |D              }t        |      dk(  rd	nd
}	| ddt        |      z   d| |	 }
|
d d t        |
      dkD  rdnd
z   cd d d        S d|j                   dcd d d        S c c}w # 1 sw Y   y xY w)Nzultron_query failed: no SQL.yesztThat statement is irreversible (drop/truncate or a WHERE-less delete/update). Re-send with confirm='yes' to proceed.i  z(0 rows) | 
c              3  L   K   | ]  }d j                  d |D                yw)r3   c              3  :   K   | ]  }|dn
t        |        y w)Nr   )str).0vs     r   	<genexpr>z"query.<locals>.<genexpr>.<genexpr>H   s     B12A6s   N)join)r8   rs     r   r:   zquery.<locals>.<genexpr>G   s$      RLPq

BBBDs   "$u   
…(first 500 rows)r   -i  u    …[truncated]u   OK — z row(s) affected.)r7   r*   r0   lowerr(   executedescriptionname	fetchmanyr;   lenrowcount)r.   confirmconncurdcolsrowsheadbodymoreouts              r   queryrO   8   s:   
c(..
C-cs7|113u<I	tll3??$'OO4OqAFFOD4==%D! 
 ::d#D99 RLPR RD.1$i3.>*BDF"S3t9_-RvdV<Cu:c#ho!22N 
 &78 
 5 
s+   ,D?;D:D?-A*D?!D?:D??Ec           	     l   t        |       j                         } t               5 }| s|j                  d      j	                         D cg c]  }|d   	 }}g }|D ]A  }	 |j                  d| d      j                         d   }|j                  d| d| d       C d	d
j                  |      z   cd d d        S |j                  d| f      j	                         }|sd| dcd d d        S |  dd
j                  d |D              z   cd d d        S c c}w # t        $ r d}Y w xY w# 1 sw Y   y xY w)NzWselect table_name from information_schema.tables where table_schema='public' order by 1r   zselect count(*) from ""?-  (z rows)zTables:
r4   zselect column_name, data_type from information_schema.columns where table_schema='public' and table_name=%s order by ordinal_positionzNo table named .z
 columns:
c              3  4   K   | ]  \  }}d | d| d  yw)rS   rT   )Nr   )r8   cts      r   r:   zschema.<locals>.<genexpr>d   s#     0QDDAq2aS1#QDs   )	r7   r*   r(   r?   fetchallfetchone	Exceptionappendr;   )tablerF   r<   tabslinesrY   nrI   s           r   schemarb   O   s[   JE	t"&,,9#::B(*#E F #EQAaD #ED F E'=aS%BCLLNqQA r!Bqc01  5!11 
 ||(*/3 4<8: 	 $UIQ/% 
& $tyy0QD0Q'QQ' 
F ! A 
sM   $D*D	D*&D-D*;(D*-D*D*D'$D*&D''D**D3)returnbool)r.   r7   rc   rd   )r   )r.   r7   rE   r7   rc   r7   )r^   r7   rc   r7   )__doc__
__future__r   r   r   compiler-   r+   r   r   r(   r0   rO   rb   r   r   r   <module>rh      sL   
 # 	 	
"**+RTT
2;( Q9.Rr   