
    ˀh@T                       d dl mZ d dlZd dlmZmZ d dlmZ d dlm	Z	m
Z
 d dlmZ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mZ d dlmZ d dlmZmZ d dl m!Z! d dl"m#Z# erTd dl$Z$d dlm%Z%m&Z& d dl'm(Z( d dl)Z*d dlm+Z+ e$jX                  dk\  rd dlm-Z- nd dl.m-Z- d dl/m0Z0 d dl1m2Z2 d dlm3Z3 d dl4m5Z5m6Z6m7Z7 h dZ8 G d d      Z9 G d d      Z:y)    )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                       e Zd ZdZddZddZy)CloseAfterFrameIterzDAllows cursor close to be deferred until the last batch is returned.c                    || _         || _        y N)_iter_frames_cursor)selfframescursors      x/var/www/html/wine-match-dev/backend/winematch-backend/venv/lib/python3.12/site-packages/polars/io/database/_executor.py__init__zCloseAfterFrameIter.__init__=   s    "    c              #     K   | j                   E d {    t        | j                  d      r| j                  j                          y y 7 6w)Nclose)r5   hasattrr6   r>   r7   s    r:   __iter__zCloseAfterFrameIter.__iter__A   s=     $$$$4<<)LL  * 	%s   AA	7AN)r8   r
   r9   r$   returnNone)rB   zIterator[DataFrame])__name__
__module____qualname____doc__r;   rA    r<   r:   r2   r2   :   s    N!r<   r2   c                     e Zd ZU dZdZded<   ddZd dZ	 	 	 	 	 	 	 	 d!dZd"dZ	e
d#d	       Zd$d
Ze
d%d       Z	 	 	 	 	 	 	 	 d&dZe
d'd       Z	 	 	 	 	 	 	 	 d(dZ	 	 	 	 	 	 	 	 	 	 d)dZ	 	 	 	 	 	 	 	 	 	 d)dZ	 	 	 	 	 	 d*dZe
d+d       Ze
d+d       Ze
d+d       Ze
d+d       Zd,dZd-dZ	 	 	 	 	 	 d.dZddd	 	 	 	 	 	 	 d/dZddded	 	 	 	 	 	 	 	 	 d0dZy)1ConnectionExecutorzIAbstraction for querying databases with user-supplied connection objects.Fboolcan_close_cursorc                   t        |t              rdn5t        |      j                  j	                  dd      d   j                         | _        | j                  dk(  rt        |      }| j                  |      | _	        d | _
        y )Narrow_odbc_proxy.   r   	surrealdb)client)
isinstancer   typerE   splitlowerdriver_namer   _normalise_cursorr9   result)r7   
connections     r:   r;   zConnectionExecutor.__init__O   sw     *o6 j!,,223:1=CCE 	
 {*-Z@J,,Z8r<   c                    | S r4   rH   r@   s    r:   	__enter__zConnectionExecutor.__enter__[   s    r<   c                $   | j                  | j                        r7ddlm} t	        | j                  |      rt        | j                                y y | j                  r2t        | j                  d      r| j                  j                          y y y )Nr   )AsyncConnectionr>   )
_is_alchemy_asyncr9   sqlalchemy.ext.asyncior^   rS   r   _close_async_cursorrL   r?   r>   )r7   exc_typeexc_valexc_tbr^   s        r:   __exit__zConnectionExecutor.__exit__^   sl     !!$++.>$++743356 8""wt{{G'DKK (E"r<   c                N    dt        |       j                   d| j                  dS )N<z module=>)rT   rD   rW   r@   s    r:   __repr__zConnectionExecutor.__repr__n   s)    4:&&'x0@0@/C1EEr<   c                    | j                   }|j                         D cg c]5  \  }}||v r,|||   k7  r$t        j                  |      j	                  |      7 c}}x}r| j                  |      } | S c c}}w )z&Apply schema overrides to a DataFrame.)schemaitemsFcolcastwith_columns)dfschema_overridesexisting_schemarn   dtype	cast_colss         r:   _apply_overridesz#ConnectionExecutor._apply_overridesq   s}     )) /446
Uo%%?33G*G EE#JOOE"
 
9 

 +B	
s   :A3c                   K   | j                   rTt        | j                  d      r=ddlm} t        |      5  | j                  j                          d {    d d d        y y y 7 # 1 sw Y   y xY ww)Nr>   r   )AsyncContextNotStarted)rL   r?   r9   sqlalchemy.ext.asyncio.excrx   r   r>   )r7   rx   s     r:   ra   z&ConnectionExecutor._close_async_cursor}   sf       WT[['%BI01 *kk'')))* * &C  ** *s.   4A2A&A$A&A2$A&&A/+A2c           	        t        |       }t        t              5  d}dD ],  }t        t	        ||d      x}t
              s!t        |      } n |r!|t        |      k  rd|  d| }t        |      ddd       y# 1 sw Y   yxY w)z<Check the module version against a minimum required version.N)__version__versionz)`read_database` queries require at least z	 version )
__import__r   AttributeErrorrS   getattrstrr   r   )module_nameminimum_versionmodmodule_versionversion_attrvermsgs          r:   _check_module_versionz(ConnectionExecutor._check_module_version   s     %n% 	659N : WS,%EEcsK%23%7N .=3Q"QA+iXgWhi055	6 	6 	6s   %A;1A;;Bc             #     K   |d   }|r|#|d   } t        | j                  |              y|d   r|gng }|d   }t        | j                  |      }|s || E d{    y	  || }	|	sy|	 7 w)zGYield Arrow data as a generator of one or more RecordBatches or Tables.fetch_batchesN	fetch_allexact_batch_sizerepeat_batch_calls)r   rY   )
r7   driver_properties
batch_sizeiter_batchesr   fetch_methodsizer   fetchmany_arrowarrows
             r:   _fetch_arrowzConnectionExecutor._fetch_arrow   s      */:}4,[9L4'$++|466#45G#HJ<bD!23G!H%dkk=AO%*D111+T2E K	  2s   AA4A2A4c                   | j                         }|r"|st        |d   t        t        t        f      r|S |D cg c]  }t        |       c}S c c}w )zCFetch row data in a single call, returning the complete result set.r   )fetchallrS   listtupledict)rY   
is_alchemyrowsrows       r:   _fetchall_rowsz!ConnectionExecutor._fetchall_rows   sS       z$q'D%;N'O 	
 )--%*-	
 .s   Ac             #     K   	 |j                  |      }|sy|st        |d   t        t        t        f      r| n|D cg c]  }t        |       c} Uc c}w w)zDFetch row data incrementally, yielding over the complete result set.r   N)	fetchmanyrS   r   r   r   )r7   rY   r   r   r   r   s         r:   _fetchmany_rowsz"ConnectionExecutor._fetchmany_rows   s\      ##J/Dz$q'D%3FG
-12cuSz22  3s   ?AAAc                   ddl m 	 t        j                         D ]  \  }}t	        j
                  d| d j                        s+|d   x}r j                   j                  |       |r"|d   r|sd j                   d}t        |       fd	 j                  |||
      D        }	|r|	c S t        |	      c S  	 y# t        $ r!d}
t        fd|
D              s Y dydww xY w)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  |   K   | ]3  }t        |      rj                  |xs i       nt        |        5 yw))rr   N)rS   rv   r   ).0batchr"   rr   r7   s     r:   	<genexpr>z1ConnectionExecutor._from_arrow.<locals>.<genexpr>   sK      	 " &eY7 --e6F6L"N'@PQR	s   9<)r   r   )zdoes not support Apache Arrowz$Apache Arrow format is not supportedc              3  8   K   | ]  }|t              v   y wr4   )r   )r   eerrs     r:   r   z1ConnectionExecutor._from_arrow.<locals>.<genexpr>   s     BqCH}Bs   N)polarsr"   r   rl   rematchrW   r   
ValueErrorr   next	Exceptionany)r7   r   r   rr   infer_schema_lengthdriverr   r   r   r8   arrow_not_supportedr"   r   s   `  `       @@r:   _from_arrowzConnectionExecutor._from_arrow   s    	%	-B-H-H-J D))88axqM4+;+;</0ABBsB2243C3CSI#)*<=j >t?O?O>PP}~(o-	 &*%6%6-)5'1 &7 &		F &26CtF|C+D@   	# B.ABB C 	s*   >C A+C 7C C 	C1C,,C1c                  ddl m |r|sd}t        |      t        | j                  x}t
              x}rt        | j                        | _        	 t        | j                  d      r| j                  dk(  x}rt        | j                  d      r6| j                  j                  j                  D 	cg c]  }	|	d   |	dd f }
}	nt        | j                  d	      r0| j                  j                  j                  D cg c]  }|df }
}n^d
| j                  }t        |      t        | j                  d      r,| j                  j                  D 	cg c]  }	|	d   |	dd f }
}	ng }
| j                  |
xs i       |
D cg c]  \  }}|	 c}}fd|r| j                  | j                  ||      n| j                  | j                  |      gD        }|r|n
t!        |      	 |r|j#                          S S 	 |r|j#                          yyc c}	w c c}w c c}	w c c}}w # |r|j#                          w w xY w)z.Return resultset data row-wise for frame init.r   r!   zFCannot set `iter_batches` without also setting a non-zero `batch_size`r   
sqlalchemyr9   rP   N	_metadataz0Unable to determine metadata from query result; description)r   rr   c              3  @   K   | ]  } |xs d d        y w)Nr   )datark   rr   r   orientrH   )r   r   r"   r   result_columnsrr   s     r:   r   z0ConnectionExecutor._from_rows.<locals>.<genexpr>  s9        !-5)9,?$ s   )r   r   )r   )r   r"   r   rS   rY   r   r   r?   rW   r9   r   r   keys_inject_type_overridesr   r   r   r>   )r7   r   r   rr   r   r   original_resultis_asyncr   dcursor_descknm_r8   r"   r   s      ``          @@r:   
_from_rowszConnectionExecutor._from_rows   sB    	%
X  S/!!T[["@/)LL8L$T[[1DK-	(t{{J/"&"2"2l"BC:Ct{{H537;;3E3E3Q3Q'./QqT1QR5M' ' !k::>++:O:O:T:T&UQ4y&U&U PQUQ\Q\P_`(o-T[[-8:>++:Q:Q"RQAaD!AB%="RK"R"$K#'#>#> +&6&<" $? $  3>!>Q"!> ( ,, KK'1'1 -  #11$++*1UV$ ".v4<? %%'  %%' Q' 'V #S "?, %%' sE   A H0 5H;H0 H AH0 H%(!H0 	H*AH0 H0 0Ic                    t               }|D ]N  \  }}||v rd|d}t        |      |!||vrt        | j                  |      }||||<   |j	                  |       P |S )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   r9   add)r7   r   rr   
dupe_checkr   descr   rt   s           r:   r   z)ConnectionExecutor._inject_type_overrides2  s     U
# 	HBZv%WX$S))!b0@&@5dkk4H$+0$R(NN2	  r<   c                T    	 ddl m}m}m} t	        | |||f      S # t
        $ r Y yw xY w)z2Check if the given connection is SQLALchemy async.r   )r^   AsyncSessionasync_sessionmakerF)r`   r^   r   r   rS   ImportError)connr^   r   r   s       r:   r_   z$ConnectionExecutor._is_alchemy_asyncN  s:    		  d_lDV$WXX 		s    	''c                l    ddl m} t        | |      ry	 ddlm} t        | |      S # t
        $ r Y yw xY w)z5Check if the given connection is a SQLAlchemy Engine.r   )EngineT)AsyncEngineF)sqlalchemy.enginer   rS   r`   r   r   )r   r   r   s      r:   _is_alchemy_enginez%ConnectionExecutor._is_alchemy_engine\  s;     	-dF#	:dK00 		s   ' 	33c                X    t        |       j                  j                  dd      d   dk(  S )zCCheck if the given connection is a SQLAlchemy object (of any kind).rO   rP   r   r   )rT   rE   rU   )r   s    r:   _is_alchemy_objectz%ConnectionExecutor._is_alchemy_objectj  s+     Dz$$**3215EEr<   c                    ddl m} ddlm}m} t        | |||f      ry	 ddl m} t        | |      S # t        $ r Y yw xY w)z=Check if the given connection is a SQLAlchemy Session object.r   )r   )SessionsessionmakerT)r   F)r`   r   sqlalchemy.ormr   r   rS   r   r   )r   r   r   r   r   s        r:   _is_alchemy_sessionz&ConnectionExecutor._is_alchemy_sessiono  sF     	88d\7LAB	Ad$677 		s   2 	>>c                   | j                   dk(  r| j                  |      r|S |j                  j                  dk(  r/d| _         |j                  j	                         j                         S |j                  j                  dk(  r	d| _         |S | j                  |      rd| _        |j                         S |S t        |d      r)t        |j
                  x}      r |       n|}d| _        |S t        |d      r|S d	|d
}t        |      )zCNormalise a connection object such that we have the query executor.r   zdatabricks-sql-python
databricksduckdb_engineduckdbTr9   executezUnrecognised connection type "z""; no 'execute' or 'cursor' method)rW   r   enginer   raw_connectionr9   r   rL   connectr?   callable	TypeError)r7   r   r9   r   s       r:   rX   z$ConnectionExecutor._normalise_cursor  s    |+''- ;;%%)@@'3D$;;557>>@@[[''?:'/D$K,,T2,0D)<<>)KT8$!)DKK*?&!@VXfF$(D!MT9%K08Z]nr<   c                l  K   | j                  | j                        }|r| j                  j                         n| j                  }|4 d{   }|rt        |d      s|j                  } |j
                  |fi | d{   }|cddd      d{    S 7 L7 7 	# 1 d{  7  sw Y   yxY ww)z5Execute a query using an async SQLAlchemy connection.Nr   )r   r9   beginr?   sessionr   )r7   queryoptions
is_sessionr9   r   rY   s          r:   _sqlalchemy_async_executez,ConnectionExecutor._sqlalchemy_async_execute  s     --dkk:
(2""$ 	 	T'$	":||'4<<999F		 	 	 :	 	 	 	sZ   A
B4BB41BBBB4BB4BB4B1%B(&B1-B4c                   ddl m} ddlm} ddlm} d}d}t        | j                  |      r.d|v r*d|vr&|j                         }|j                  d      |d<   d}|j                  |      }| j                  | j                        }	|	st        |t              rtt        | j                  d      r^| j                  j                  }t        ||      rt        |      }t        |t               r9t#        d	 |D              s't%        |      ||<   nt        |t              r ||      }|$|	r| j&                  n| j                  j(                  }|||fS )
z<Prepare a query for execution using a SQLAlchemy connection.r   )r   )textr   
parametersNparamsexec_driver_sqlc              3  H   K   | ]  }t        |t        t        f        y wr4   )rS   r   r   r   ps     r:   r   z7ConnectionExecutor._sqlalchemy_setup.<locals>.<genexpr>  s       412
1tUm,4s    ")r   r   sqlalchemy.sqlr   sqlalchemy.sql.elementsr   rS   r9   copypopgetr_   r   r?   r   r   r   allr   r   r   )
r7   r   r   r   r   r   	param_keycursor_executer   r   s
             r:   _sqlalchemy_setupz$ConnectionExecutor._sqlalchemy_setup  s*    	+'6 	t{{G,''llnG 'L 9GH IY'))$++668,%67![[88N%,E
&$' 46<4 1 &+6]	"s#KE!2:..@S@S  w--r<   NT)r   select_queries_onlyc                  |rht        |t              rXt        j                  dt        j                  dd|            }|sdn|j                  d      x}t        v r| d}t        |      xs i | j                  | j                        r| j                  |      \  }}n| j                  j                  }	 t        |      j                  }r t        d |j!                         D              r
 ||fi }	nfd|xs D        }
 ||g|
 }	|	|	du r| j                  n|	}	| j"                  d	k(  r|	j                  }	|	| _        | S # t        $ r i }Y w xY w)
z-Execute a query and reference the result set.z\w{3,}z/\*(.|[\r\n])*?\*/ r   z( statements are not valid 'read' queriesc              3  t   K   | ]0  }|j                   t        j                  t        j                  fv  2 y wr4   )kindr   KEYWORD_ONLYPOSITIONAL_OR_KEYWORDr   s     r:   r   z-ConnectionExecutor.execute.<locals>.<genexpr>  s2      
 FFy--y/N/NOO
s   68c              3  6   K   | ]  }r|v s
|     y wr4   rH   )r   or   s     r:   r   z-ConnectionExecutor.execute.<locals>.<genexpr>  s#      " 1PW<
"s   
Tr   )rS   r   r   searchsubgroup_INVALID_QUERY_TYPESr   r   r9   r   r   r   r   r   r   valuesrW   rY   )r7   r   r   r  q
query_typer   r   r   rY   positional_optionss     `        r:   r   zConnectionExecutor.execute  s`    :eS#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" $E?,>?F "(6T>x']]F)  	F	s   ;E EE)r   r   rr   r   c               V   | j                   d}t        |      | j                  }|xr |x}rd| _        | j                  | j                  fD ]4  } |||||      }	|	|rd t        |	| j                         D        }	|	c S  d| j                  d| j                  }t        |      )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   rr   r   c              3      K   | ]  }|  y wr4   rH   )r   rq   s     r:   r   z/ConnectionExecutor.to_polars.<locals>.<genexpr>'  s       s   )r9   zCurrently no support for z connection )	rY   RuntimeErrorrL   r   r   r2   rW   r9   NotImplementedError)
r7   r   r   rr   r   r   	can_closedefer_cursor_close
frame_initframes
             r:   	to_polarszConnectionExecutor.to_polars  s     ;;BCs##))	"."<9==$)D! OO
 	J %)!1$7	E  %"5!#';;#E '	, ((8(8';<W 	 "#&&r<   )rZ   r#   rB   rC   )rB   r   )rb   ztype[BaseException] | Nonerc   zBaseException | Nonerd   zTracebackType | NonerB   rC   )rB   r   )rq   r"   rr   r%   rB   r"   )rB   rC   )r   r   r   r   rB   rC   )r   r   r   
int | Noner   rK   rB   zIterable[pa.RecordBatch])rY   r$   r   rK   rB   Iterable[Sequence[Any]])rY   r$   r   r  r   rK   rB   r  )
r   r  r   rK   rr   SchemaDict | Noner   r  rB   z&DataFrame | Iterator[DataFrame] | None)r   zlist[tuple[str, Any]]rr   r%   rB   r%   )r   r
   rB   rK   )r   r
   rB   r$   )r   r   r   r
   rB   r
   )r   str | TextClause | Selectabler   zdict[str, Any]rB   z9tuple[Any, dict[str, Any], str | TextClause | Selectable])r   r  r   zdict[str, Any] | Noner  rK   rB   r   )
r   rK   r   r  rr   r  r   r  rB   zDataFrame | Iterator[DataFrame])rD   rE   rF   rG   rL   __annotations__r;   r\   re   ri   staticmethodrv   ra   r   r   r   r   r   r   r   r_   r   r   r   rX   r   r   r   r   r  rH   r<   r:   rJ   rJ   H   si   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<   rJ   );
__future__r   r   collections.abcr   r   
contextlibr   inspectr   r   typingr	   r
   r   r   rm   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%   r  r2   rJ   rH   r<   r:   <module>r6     s    " 	 /  ( % ! / % , 
 E T G 02#H
7"*24 EE ! !k' k'r<   