
    h&V                       S SK Jr  S SKrS SKJrJr  S SKJr  S SKJ	r	J
r
  S SKJrJr  S SKJr  S SKJr  S S	KJr  S S
KJr  S SKJrJrJr  S SKJr  S SKJrJr  S SK J!r!  S SK"J#r#  \(       aU  S SK$r$S SKJ%r%J&r&  S SK'J(r(  S SK)r*S SKJ+r+  \$RX                  S:  a  S SKJ-r-  OS SK.J-r-  S SK/J0r0  S SK1J2r2  S SKJ3r3  S SK4J5r5J6r6J7r7  1 Skr8 " S S5      r9 " S S5      r:g)    )annotationsN)	CoroutineSequence)suppress)	Parameter	signature)TYPE_CHECKINGAny)	functions)parse_version)
from_arrow)N_INFER_DEFAULT)DuplicateErrorModuleUpgradeRequiredErrorUnsuitableSQLError)ARROW_DRIVER_REGISTRY)ODBCCursorProxySurrealDBCursorProxy)dtype_from_cursor_description)
_run_async)IterableIterator)TracebackType)ArrowDriverProperties)      )Self
TextClause)
Selectable	DataFrame)ConnectionOrCursorCursor
SchemaDict>   USEDROPALTERCREATEDELETEINSERTUPDATEUPSERTVACUUMANALYZEREPLACEc                  ,    \ rS rSrSrSS jrSS jrSrg)	CloseAfterFrameIter:   zDAllows cursor close to be deferred until the last batch is returned.c                   Xl         X l        g N)_iter_frames_cursor)selfframescursors      V/home/james-whalen/.local/lib/python3.13/site-packages/polars/io/database/_executor.py__init__CloseAfterFrameIter.__init__=   s    "    c              #     #    U R                    S h  vN   [        U R                  S5      (       a  U R                  R                  5         g g  N;7f)Nclose)r6   hasattrr7   r@   r8   s    r;   __iter__CloseAfterFrameIter.__iter__A   s?     $$$$4<<))LL  * 	%s   AA<A)r7   r6   N)r9   r
   r:   r$   returnNone)rE   zIterator[DataFrame])__name__
__module____qualname____firstlineno____doc__r<   rC   __static_attributes__ r>   r;   r2   r2   :   s    N!r>   r2   c                     \ rS rSr% SrSrS\S'   S"S jrS#S jr        S$S jr	S%S	 jr
\S&S
 j5       rS'S jr\S(S j5       r        S)S jr\S*S j5       r        S+S jr          S,S jr          S,S jr      S-S jr\S.S j5       r\S.S j5       r\S.S j5       r\S.S j5       r\S/S j5       rS0S jrS1S jr      S2S jrSSS.       S3S jjrSSS\S.         S4S  jjrS!r g)5ConnectionExecutorH   zIAbstraction for querying databases with user-supplied connection objects.Fboolcan_close_cursorc                   [        U[        5      (       a  SO5[        U5      R                  R	                  SS5      S   R                  5       U l        U R                  S:X  a	  [        US9nU R                  U5      U l	        S U l
        g )Narrow_odbc_proxy.   r   	surrealdb)client)
isinstancer   typerH   splitlowerdriver_namer   _normalise_cursorr:   result)r8   
connections     r;   r<   ConnectionExecutor.__init__O   sz     *o66 j!,,223:1=CCE 	
 {*-Z@J,,Z8r>   c                    U $ r5   rM   rB   s    r;   	__enter__ConnectionExecutor.__enter__[   s    r>   c                L   U R                  U R                  5      (       a<  SSKJn  [	        U R                  U5      (       a  [        U R                  5       5        g g U R                  (       a7  [        U R                  S5      (       a  U R                  R                  5         g g g )Nr   )AsyncConnectionr@   )
_is_alchemy_asyncr:   sqlalchemy.ext.asynciorf   rY   r   _close_async_cursorrR   rA   r@   )r8   exc_typeexc_valexc_tbrf   s        r;   __exit__ConnectionExecutor.__exit__^   su     !!$++..>$++7743356 8""wt{{G'D'DKK (E"r>   c                P    S[        U 5      R                   SU R                  < S3$ )N<z module=>)rZ   rG   r]   rB   s    r;   __repr__ConnectionExecutor.__repr__n   s)    4:&&'x0@0@/C1EEr>   c                   U R                   nUR                  5        VVs/ s H;  u  p4X2;   d  M  XBU   :w  d  M  [        R                  " U5      R	                  U5      PM=     snn=n(       a  U R                  U5      n U $ s  snnf )z&Apply schema overrides to a DataFrame.)schemaitemsFcolcastwith_columns)dfschema_overridesexisting_schemarx   dtype	cast_colss         r;   _apply_overrides#ConnectionExecutor._apply_overridesq   s     )) /446
6
% #*/33G*G #AEE#JOOE"6
 
9 

 +B	
s   B B )B c                  #    U R                   (       aY  [        U R                  S5      (       a=  SSKJn  [        U5         U R                  R                  5       I S h  vN   S S S 5        g g g  N! , (       d  f       g = f7f)Nr@   r   )AsyncContextNotStarted)rR   rA   r:   sqlalchemy.ext.asyncio.excr   r   r@   )r8   r   s     r;   ri   &ConnectionExecutor._close_async_cursor}   s^       WT[['%B%BI01kk''))) 21 &C  * 21s/   >B A0A.A0#B.A00
A>:Bc           	     0   [        U 5      n[        [        5         SnS H1  n[        [	        X$S5      =n[
        5      (       d  M&  [        U5      n  O   U(       a"  U[        U5      :  a  SU  SU 3n[        U5      eSSS5        g! , (       d  f       g= f)z<Check the module version against a minimum required version.N)__version__versionz)`read_database` queries require at least z	 version )
__import__r   AttributeErrorrY   getattrstrr   r   )module_nameminimum_versionmodmodule_versionversion_attrvermsgs          r;   _check_module_version(ConnectionExecutor._check_module_version   s     %n%59N :WS%EEcsKK%23%7N !; .=3Q"QA+iXgWhi055 &%%s   'B8B
Bc             #    #    US   nU(       a  Uc#  US   n[        U R                  U5      " 5       v   gUS   (       a  U/O/ nUS   n[        U R                  U5      nU(       d  U" U6  Sh  vN   g U" U6 n	U	(       d  gU	v   M   N7f)zGYield Arrow data as a generator of one or more RecordBatches or Tables.fetch_batchesN	fetch_allexact_batch_sizerepeat_batch_calls)r   r_   )
r8   driver_properties
batch_sizeiter_batchesr   fetch_methodsizer   fetchmany_arrowarrows
             r;   _fetch_arrowConnectionExecutor._fetch_arrow   s      */:}4,[9L$++|466#45G#HJ<bD!23G!H%dkk=AO%*D111+T2E K	  2s   A,B
.B/B
c                   U R                  5       nU(       a,  U(       d#  [        US   [        [        [        45      (       a  U$ U Vs/ s H  n[        U5      PM     sn$ s  snf )zCFetch row data in a single call, returning the complete result set.r   )fetchallrY   listtupledict)r_   
is_alchemyrowsrows       r;   _fetchall_rows!ConnectionExecutor._fetchall_rows   sZ       z$q'D%;N'O'O 	
 )--%*-	
 .s   A c             #     #     UR                  U5      nU(       d  gU(       d#  [        US   [        [        [        45      (       a  Uv   OU Vs/ s H  n[        U5      PM     snv   Mh  s  snf 7f)zDFetch row data incrementally, yielding over the complete result set.r   N)	fetchmanyrY   r   r   r   )r8   r_   r   r   r   r   s         r;   _fetchmany_rows"ConnectionExecutor._fetchmany_rows   sb      ##J/Dz$q'D%3FGG
-12TcuSzT22  3s   AA1A,%A1c               2  ^ ^^^ SSK Jm   [        R                  " 5        H  u  pV[        R
                  " SU S3T R                  5      (       d  M1  US   =n(       a  T R                  T R                  U5        U(       a,  US   (       a"  U(       d  ST R                   S3n[        U5      eUUU 4S	 jT R                  UUUS
9 5       n	U(       a  U	s  $ [        U	5      s  $    g! [         a'  mSn
[        U4S jU
 5       5      (       d  e  Sm@gSm@ff = f)z5Return resultset data in Arrow format for frame init.r   r!   ^$r   r   zCannot set `iter_batches` for z- without also setting a non-zero `batch_size`c              3     >#    U  H;  n[        UT5      (       a  TR                  UT=(       d    0 5      O	[        UTS 9v   M=     g7f))r|   N)rY   r   r   ).0batchr"   r|   r8   s     r;   	<genexpr>1ConnectionExecutor._from_arrow.<locals>.<genexpr>   sO      	&E &eY77 --e6F6L"N'@PQR&s   AA)r   r   )zdoes not support Apache Arrowz$Apache Arrow format is not supportedc              3  >   >#    U  H  o[        T5      ;   v   M     g 7fr5   )r   )r   eerrs     r;   r   r      s     B.ACH}.As   N)polarsr"   r   rv   rematchr]   r   
ValueErrorr   next	Exceptionany)r8   r   r   r|   infer_schema_lengthdriverr   r   r   r9   arrow_not_supportedr"   r   s   `  `       @@r;   _from_arrowConnectionExecutor._from_arrow   s    	%	-B-H-H-J)88axqM4+;+;<</0ABBsB2243C3CSI#)*<=j >t?O?O>PP}~(o-	 &*%6%6-)5'1 &7 &		F &26CtF|C+ .K@   	# B.ABBB C 	s+   AC% BC% C% "C% %
D/DDc                 ^^^^ SSK Jm  U(       a  U(       d  Sn[        U5      e[        U R                  =n[
        5      =n(       a  [        U R                  5      U l         [        U R                  S5      (       Ga  U R                  S:H  =n(       a  [        U R                  S5      (       a8  U R                  R                  R                   V	s/ s H  oS   U	SS 4PM     n
n	O[        U R                  S	5      (       a2  U R                  R                  R                   Vs/ s H  oS4PM     n
nOfS
U R                  < 3n[        U5      e[        U R                  S5      (       a.  U R                  R                   V	s/ s H  oS   U	SS 4PM     n
n	O/ n
U R                  U
T=(       d    0 S9mU
 VVs/ s H  u  pUPM	     snnmUUUU4S jU(       a  U R                  U R                  UUS9OU R                  U R                  US9/ 5       nU(       a  UO
[!        U5       U(       a  UR#                  5         $ $  U(       a  UR#                  5         ggs  sn	f s  snf s  sn	f s  snnf ! U(       a  UR#                  5         f f = f)z.Return resultset data row-wise for frame init.r   r!   zFCannot set `iter_batches` without also setting a non-zero `batch_size`r   
sqlalchemyr:   rV   N	_metadataz0Unable to determine metadata from query result; description)r   r|   c           	   3  J   >#    U  H  nT" UT=(       d    S TTSS9v   M     g 7f)Nr   )dataru   r|   r   orientrM   )r   r   r"   r   result_columnsr|   s     r;   r   0ConnectionExecutor._from_rows.<locals>.<genexpr>  s:      W  !-5)9,?$Ws    #)r   r   )r   )r   r"   r   rY   r_   r   r   rA   r]   r:   r   r   keys_inject_type_overridesr   r   r   r@   )r8   r   r   r|   r   r   original_resultis_asyncr   dcursor_descknm_r9   r"   r   s      ``          @@r;   
_from_rowsConnectionExecutor._from_rows   s_    	%
X  S/!!T[["@/)LL8L$T[[1DK-	(t{{J//"&"2"2l"BC:Ct{{H5537;;3E3E3Q3Q'3QaqT1QR5M3Q $ ' !k:::>++:O:O:T:T&U:TQ4y:T&U PQUQ\Q\P_`(o-T[[-88:>++:Q:Q"R:QQaD!AB%=:QK"RK"$K#'#>#> +&6&<" $? $  3>!>+"+!> ( ,, KK'1'1 -  #11$++*1UVW$ ".v4<? %%'  %%' Q' 'V #S "?, %%' sF   $A/I2 I&A I2 &I"3AI2 I'#I2 :I,A!I2 I2 2Jc                    [        5       nU HR  u  pEXC;   a  SU< S3n[        U5      eUb"  XB;  a  [        U R                  U5      nUb  XrU'   UR	                  U5        MT     U$ )a{  
Attempt basic dtype inference from a cursor description.

Notes
-----
This is limited; the `type_code` description attr may contain almost anything,
from strings or python types to driver-specific codes, classes, enums, etc.
We currently only do the additional inference from string/python type values.
(Further refinement will require per-driver module knowledge and lookups).
zcolumn z2 appears more than once in the query/result cursor)setr   r   r:   add)r8   r   r|   
dupe_checkr   descr   r~   s           r;   r   )ConnectionExecutor._inject_type_overrides2  st     U
#HBv%WX$S))!b&@5dkk4H$+0R(NN2 $  r>   c                R     SSK JnJnJn  [	        XX#45      $ ! [
         a     gf = f)z2Check if the given connection is SQLALchemy async.r   )rf   AsyncSessionasync_sessionmakerF)rh   rf   r   r   rY   ImportError)connrf   r   r   s       r;   rg   $ConnectionExecutor._is_alchemy_asyncN  s5    		  dl$WXX 		s    
&&c                t    SSK Jn  [        X5      (       a  g SSKJn  [        X5      $ ! [
         a     gf = f)z5Check if the given connection is a SQLAlchemy Engine.r   )EngineT)AsyncEngineF)sqlalchemy.enginer   rY   rh   r   r   )r   r   r   s      r;   _is_alchemy_engine%ConnectionExecutor._is_alchemy_engine\  s:     	-d##	:d00 		s   * 
77c                X    [        U 5      R                  R                  SS5      S   S:H  $ )zCCheck if the given connection is a SQLAlchemy object (of any kind).rU   rV   r   r   )rZ   rH   r[   )r   s    r;   _is_alchemy_object%ConnectionExecutor._is_alchemy_objectj  s+     Dz$$**3215EEr>   c                    SSK Jn  SSKJnJn  [        XX#45      (       a  g SSK Jn  [        X5      $ ! [         a     gf = f)z=Check if the given connection is a SQLAlchemy Session object.r   )r   )SessionsessionmakerT)r   F)rh   r   sqlalchemy.ormr   r   rY   r   r   )r   r   r   r   r   s        r;   _is_alchemy_session&ConnectionExecutor._is_alchemy_sessiono  sB     	88d7ABB	Ad77 		s   4 
A Ac                t     SSK Jn  [        X5      (       a  gSSKJn  [        X5      $ ! [
         a     gf = f)z8Check if the given result is a SQLAlchemy Result object.r   )CursorResultT)AsyncResultF)r   r   rY   rh   r   r   )r_   r   r   s      r;   _is_alchemy_result%ConnectionExecutor._is_alchemy_result  s8    
	6&//:f22 		s   * * 
77c                P   U R                   S:X  a  U R                  U5      (       a  U$ UR                  R                  S:X  a/  SU l         UR                  R	                  5       R                  5       $ UR                  R                  S:X  a	  SU l         U$ U R                  U5      (       a  SU l        UR                  5       $ U$ [        US5      (       a.  [        UR
                  =n5      (       a  U" 5       OUnSU l        U$ [        US5      (       a  U$ S	U< S
3n[        U5      e)zCNormalise a connection object such that we have the query executor.r   zdatabricks-sql-python
databricksduckdb_engineduckdbTr:   executezUnrecognised connection type "z""; no 'execute' or 'cursor' method)r]   r   enginer   raw_connectionr:   r   rR   connectrA   callable	TypeError)r8   r   r:   r   s       r;   r^   $ConnectionExecutor._normalise_cursor  s	   |+''-- ;;%%)@@'3D$;;557>>@@[[''?:'/D$K,,T22,0D)<<>)KT8$$!)DKK*?&!@!@VXfF$(D!MT9%%K08Z]nr>   c                  #    U R                  U R                  5      nU(       a  U R                  R                  5       OU R                  nU ISh  vN nU(       a  [        US5      (       d  UR                  nUR
                  " U40 UD6I Sh  vN nUsSSS5      ISh  vN   $  NV N N	! , ISh  vN  (       d  f       g= f7f)z5Execute a query using an async SQLAlchemy connection.Nr  )r   r:   beginrA   sessionr  )r8   queryoptions
is_sessionr:   r   r_   s          r;   _sqlalchemy_async_execute,ConnectionExecutor._sqlalchemy_async_execute  s     --dkk:
(2""$6T'$	":":||<<999F	 66 : 666sZ   ACB(C;B.B*B.C"B,#C*B.,C.C4B75CCc                   SSK Jn  SSKJn  SSKJn  SnSn[        U R                  U5      (       a2  SU;   a,  SU;  a&  UR                  5       nUR                  S5      US'   SnUR                  U5      nU R                  U R                  5      n	U	(       d  [        U[        5      (       a  [        U R                  S5      (       ak  U R                  R                  n[        X5      (       a  [        U5      n[        U[         5      (       a$  [#        S	 U 5       5      (       d  [%        U5      X&'   O[        U[        5      (       a  U" U5      nUc)  U	(       a  U R&                  OU R                  R(                  nXrU4$ )
z<Prepare a query for execution using a SQLAlchemy connection.r   )r   )textr   
parametersNparamsexec_driver_sqlc              3  N   #    U  H  n[        U[        [        45      v   M     g 7fr5   )rY   r   r   r   ps     r;   r   7ConnectionExecutor._sqlalchemy_setup.<locals>.<genexpr>  s!      46<
1tUm,,fs   #%)r   r   sqlalchemy.sqlr  sqlalchemy.sql.elementsr   rY   r:   copypopgetrg   r   rA   r  r   r   allr   r  r  )
r8   r  r  r   r  r   	param_keycursor_executer  r   s
             r;   _sqlalchemy_setup$ConnectionExecutor._sqlalchemy_setup  s<    	+'6 	t{{G,,''llnG 'L 9GH IY'))$++668,,%677![[88N%,,E
&$'' 46<4 1 1 &+6]"s##KE!2:..@S@S  --r>   NT)r  select_queries_onlyc               F  ^ U(       av  [        U[        5      (       aa  [        R                  " S[        R                  " SSU5      5      nU(       d  SOUR                  S5      =n[        ;   a  U S3n[        U5      eT=(       d    0 mU R                  U R                  5      (       a  U R                  UT5      u  nmnOU R                  R                  n [        U5      R                  nT(       a%  [        S UR!                  5        5       5      (       a
  U" U40 TD6n	OU4S jU=(       d    T 5       n
U" U/U
Q76 n	U	b  U	SL a  U R                  OU	n	U R"                  S	:X  a"  U R%                  U	5      (       a  U	R                  n	Xl        U $ ! [         a    0 n Nf = f)
z-Execute a query and reference the result set.z\w{3,}z/\*(.|[\r\n])*?\*/ r   z( statements are not valid 'read' queriesc              3  |   #    U  H2  nUR                   [        R                  [        R                  4;   v   M4     g 7fr5   )kindr   KEYWORD_ONLYPOSITIONAL_OR_KEYWORDr  s     r;   r   -ConnectionExecutor.execute.<locals>.<genexpr>   s1      
$ FFy--y/N/NOO$s   :<c              3  L   >#    U  H  nT(       a  UT;   d  M  TU   v   M     g 7fr5   rM   )r   or  s     r;   r   r*    s$      "%6q1PW<

%6s   $$Tr   )rY   r   r   searchsubgroup_INVALID_QUERY_TYPESr   r   r:   r!  r  r   r  r   r   valuesr]   r   r_   )r8   r  r  r#  q
query_typer   r   r  r_   positional_optionss     `        r;   r  ConnectionExecutor.execute  s|    :eS#9#9		)RVV,A2u%MNA()bqwwqz9
>RR#$LM(---R""4;;//-1-C-CE7-S*NGU![[00N	~.99F # 
]]_
 
 
 $E5W5F"%+%6w%6" $E?,>?F "(6T>x'D,C,CF,K,K]]F)  	F	s   F F F )r   r   r|   r   c               t   U R                   c  Sn[        U5      eU R                  nU=(       a    U=n(       a  SU l        U R                  U R                  4 H5  nU" UUUUS9n	U	c  M  U(       a  S [        U	U R                   S9 5       n	U	s  $    SU R                  < SU R                  < 3n[        U5      e)z
Convert the result set to a DataFrame.

Wherever possible we try to return arrow-native data directly; only
fall back to initialising with row-level data if no other option.
z.cannot return a frame before executing a queryF)r   r   r|   r   c              3  &   #    U  H  nUv   M	     g 7fr5   rM   )r   r{   s     r;   r   /ConnectionExecutor.to_polars.<locals>.<genexpr>6  s      #B #s   )r:   zCurrently no support for z connection )	r_   RuntimeErrorrR   r   r   r2   r]   r:   NotImplementedError)
r8   r   r   r|   r   r   	can_closedefer_cursor_close
frame_initframes
             r;   	to_polarsConnectionExecutor.to_polars  s     ;;BCs##))	"."<9==$)D! OO
J %)!1$7	E  %"5!#';;#E '
, ((8(8';<W 	 "#&&r>   )rR   r:   r]   r_   )r`   r#   rE   rF   )rE   r   )rj   ztype[BaseException] | Nonerk   zBaseException | Nonerl   zTracebackType | NonerE   rF   )rE   r   )r{   r"   r|   r%   rE   r"   )rE   rF   )r   r   r   r   rE   rF   )r   r   r   
int | Noner   rQ   rE   zIterable[pa.RecordBatch])r_   r$   r   rQ   rE   Iterable[Sequence[Any]])r_   r$   r   rA  r   rQ   rE   rB  )
r   rA  r   rQ   r|   SchemaDict | Noner   rA  rE   z&DataFrame | Iterator[DataFrame] | None)r   zlist[tuple[str, Any]]r|   r%   rE   r%   )r   r
   rE   rQ   )r_   r
   rE   rQ   )r   r
   rE   r$   )r  r   r  r
   rE   r
   )r  str | TextClause | Selectabler  zdict[str, Any]rE   z9tuple[Any, dict[str, Any], str | TextClause | Selectable])r  rD  r  zdict[str, Any] | Noner#  rQ   rE   r   )
r   rQ   r   rA  r|   rC  r   rA  rE   zDataFrame | Iterator[DataFrame])!rG   rH   rI   rJ   rK   rR   __annotations__r<   rc   rm   rr   staticmethodr   ri   r   r   r   r   r   r   r   rg   r   r   r   r   r^   r  r!  r  r   r?  rL   rM   r>   r;   rO   rO   H   s   S #d"
  ,  &  %	 
 
  F 	 	* 6 6 0  	 
   
" 2 
 
33-73EI3	 3, , 	,
 ,, (, 
0,\@( @( 	@(
 ,@( (@( 
0@(D *  %  
	 8     F F    B).2).=K).	B).^ *.$(-,- '	-
 "- 
-d #!%.2*9/' /' 	/'
 ,/' (/' 
)/' /'r>   rO   );
__future__r   r   collections.abcr   r   
contextlibr   inspectr   r   typingr	   r
   r   r   rw   polars._utils.variousr   polars.convertr   polars.datatypesr   polars.exceptionsr   r   r   "polars.io.database._arrow_registryr   "polars.io.database._cursor_proxiesr   r   polars.io.database._inferencer   polars.io.database._utilsr   sysr   r   typesr   pyarrowpar   version_infor   typing_extensionsr  r   sqlalchemy.sql.expressionr    r"   polars._typingr#   r$   r%   r0  r2   rO   rM   r>   r;   <module>r\     s    " 	 /  ( % ! / % , 
 E T G 02#H
7"*24 EE ! !z' z'r>   