o
    RDiz                     @  s,  U 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l
mZ d dlmZmZmZmZmZ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mZ ddl m!Z!m"Z" ddl#m$Z$m%Z%m&Z&m'Z' ddl(m)Z)m*Z*m+Z+m,Z,m-Z- ddl.m/Z/ ddl.m0Z1 ddl2m3Z3 ddl4m5Z5m6Z6m7Z7 ddl8m9Z9 ee:Z;dZ<dZ=erd dl>m?Z? d dl0m@Z@mAZA ddlBmCZC ddlDmEZE ddlFmGZGmHZH ddlImJZJ g ZKdeLd< dZMd ZNd!ZO	"dEdFd.d/ZPe	G d0d1 d1eZQG d2d3 d3eZRdGd=d>ZSG d?d@ d@ejTZUG dAdB dBeUZVG dCdD dDeUZWdS )H    )annotationsN)	b64decode)Enumunique)	getLogger)TYPE_CHECKINGAnyCallableIterator
NamedTupleSequence)Self   )ArrowConverterContext)exponential_backoff)OKUNAUTHORIZEDurlparse)FIELD_TYPESIterUnit)'ER_FAILED_TO_CONVERT_ROW_TO_PYTHON_TYPEER_NO_PYARROW)ErrorInterfaceErrorNotSupportedErrorProgrammingError)RetryRequestget_http_retryable_erroris_retryable_http_coderaise_failed_request_errorraise_okta_unauthorized_error)installed_pandas)pyarrow)SecretDetector)
HttpConfigSessionManagerSessionManagerFactory)TimerContextManager
      )	DataFrame)DataTypeTable)SnowflakeConnection)SnowflakeConverterType)ResultMetadataV2SnowflakeCursor)Responsez,list[Callable[[ResultMetadataV2], DataType]]FIELD_TYPE_TO_PA_TYPEz/x-amz-server-side-encryption-customer-algorithmz)x-amz-server-side-encryption-customer-keyAES256Tdatabytescontextr   use_dict_resultboolnumpynumber_to_decimalrow_unitr   check_error_on_every_columnc           	      C  sL   ddl m}m} td |tjkr|d | |||||S |d | |||||S )Nr   )PyArrowRowIteratorPyArrowTableIteratorz+Using nanoarrow as the arrow data converter)nanoarrow_arrow_iteratorr=   r>   loggerdebugr   ROW_UNIT)	r4   r6   r7   r9   r:   r;   r<   r=   r>    rC   Y/var/www/Datamplify/venv/lib/python3.10/site-packages/snowflake/connector/result_batch.py_create_nanoarrow_iterator8   s.   	

rE   c                   @  s   e Zd ZdZdZdZdZdS )DownloadMetricsz:Defines the keywords by which to store metrics for chunks.downloadparseloadN)__name__
__module____qualname____doc__rG   rH   rI   rC   rC   rC   rD   rF   [   s
    rF   c                   @  s*   e Zd ZU dZded< ded< ded< dS )RemoteChunkInfozKSmall class that holds information about chunks that are given by back-end.strurlintuncompressedSizecompressedSizeN)rJ   rK   rL   rM   __annotations__rC   rC   rC   rD   rN   d   s
   
 rN   cursorr0   _formatrO   dict[str, Any]schemaSequence[ResultMetadataV2]returnlist[ResultBatch]c              
     s  g d  |d }| dd}|}g }|dkr'd fd	d
fdd|D n| d}tjj d|v r|d }	tdt|	  | d}
i d|v rpi |d  D ]\}}||< d|vrntd| d|  qWn|
d urtdt	|
  t
t< |
t< d!dd|dkrfdd|	D }n fdd|	D }|D ]}||j8 }q|dkrtj| d|jjj d}n9|d urtj|| jjjjjjj d}ntd|  tjdd jjjjjjj d}|g| S )"Nrowtypetotalr   jsoncolrW   rZ   "tuple[str, SnowflakeConverterType]c                   s$   | d   } jj|| }||fS )Ntype)upper_connection	converterto_python_method)r_   	type_namepython_method)rU   rC   rD   col_to_converterz   s
   z6create_batches_from_response.<locals>.col_to_converterc                   s   g | ]} |qS rC   rC   .0c)rh   rC   rD   
<listcomp>       z0create_batches_from_response.<locals>.<listcomp>rowsetBase64chunkszchunk size=qrmkchunkHeaders
encryptionzadded chunk header: key=z, value=zqrmk=rk   rN   c                 S  s   t | d | d | d dS )NrP   rR   rS   )rP   rR   rS   )rN   )rk   rC   rC   rD   remote_chunk_info   s
   z7create_batches_from_response.<locals>.remote_chunk_infoc                   s:   g | ]}t |d   |jjjjj dqS )rowCountjson_result_force_utf8_decodingsession_manager)JSONResultBatch_use_dict_resultrc    _json_result_force_utf8_decoding_session_managercloneri   )chunk_headerscolumn_convertersrU   rs   rX   rC   rD   rl      s    
c                   s@   g | ]}t |d  | jjjjjjj d	qS )rt   rw   )ArrowResultBatchry   rc   _numpy_arrow_number_to_decimalr{   r|   ri   )arrow_contextr}   rU   rs   rX   rC   rD   rl      s    
rowsetr   z9Don't know how to construct ResultBatches from response:  )r_   rW   rZ   r`   )rk   rW   rZ   rN   )getr   rc   _session_parametersr@   rA   lenitemsr#   mask_secrets	SSE_C_AESSSE_C_ALGORITHM	SSE_C_KEYrowcountrx   	from_datary   r{   r|   r   r   r   error)rU   rV   r4   rX   rowtypes	total_lenfirst_chunk_lenrest_of_chunks
rowset_b64ro   rp   
header_keyheader_valuerk   first_chunkrC   )r   r}   rh   r~   rU   rs   rX   rD   create_batches_from_responsel   s   






r   c                   @  s   e Zd ZdZ	d;d<ddZed=ddZed>ddZed>ddZed?ddZ	ed@ddZ
e
jdAddZ
ed d! ZejdBd$d!ZdCd&d'Z	d;dDd+d,ZejdEd.d/ZdFd0d1ZejdGd3d4ZejdHd6d7Zej	d;dId9d:ZdS )JResultBatchaz  Represents what the back-end calls a result chunk.

    These are parts of a result set of a query. They each know how to retrieve their
    own results and convert them into Python native formats.

    As you are iterating through a ResultBatch you should check whether the yielded
    value is an ``Exception`` in case there was some error parsing the current row
    we might yield one of these to allow iteration to continue instead of raising the
    ``Exception`` when it occurs.

    These objects are pickleable for easy distribution and replication.

    Please note that the URLs stored in these do expire. The lifetime is dictated by the
    Snowflake back-end, at the time of writing this this is 6 hours.

    They can be iterated over multiple times and in different ways. Please follow the
    code in ``cursor.py`` to make sure that you are using this class correctly.

    Nr   rQ   r}   dict[str, str] | Noners   RemoteChunkInfo | NonerX   rY   r7   r8   rw   SessionManager | NonerZ   Nonec           	      C  s   || _ || _|| _|| _|d urdd |D nd | _|| _|| _i | _d | _| jr=t	| jj
}|jdd}|d | _d S t| j | _d S )Nc                 S  s   g | ]}|  qS rC   )_to_result_metadata_v1rj   srC   rC   rD   rl     rm   z(ResultBatch.__init__.<locals>.<listcomp>/r   )r   _chunk_headers_remote_chunk_info_schemarX   ry   r{   _metrics_datar   rP   pathrsplitidrO   )	selfr   r}   rs   rX   r7   rw   
parsed_url
path_partsrC   rC   rD   __init__   s   	zResultBatch.__init__c                 C  s
   | j duS )zWhether this chunk is local.Nr   r   rC   rC   rD   _local  s   
zResultBatch._local
int | Nonec                 C     | j rdS | jjS )zzReturns the size of chunk in bytes in compressed form.

        If it's a local chunk this function returns None.
        N)r   r   rS   r   rC   rC   rD   compressed_size     zResultBatch.compressed_sizec                 C  r   )z|Returns the size of chunk in bytes in uncompressed form.

        If it's a local chunk this function returns None.
        N)r   r   rR   r   rC   rC   rD   uncompressed_size#  r   zResultBatch.uncompressed_size	list[str]c                 C  s   dd | j D S )Nc                 S     g | ]}|j qS rC   )name)rj   r_   rC   rC   rD   rl   /      z,ResultBatch.column_names.<locals>.<listcomp>)r   r   rC   rC   rD   column_names-  s   zResultBatch.column_namesc                 C  s   | j S Nr{   r   rC   rC   rD   rw   1     zResultBatch.session_managerc                 C  s
   || _ d S r   r   )r   rw   rC   rC   rD   rw   5  s   
c                 C  s   | j jS r   )r{   configr   rC   rC   rD   http_config9  s   zResultBatch.http_configr   r$   c                 C  s$   | j r	|| j _d S tj|d| _ d S )N)r   )r{   r   r&   get_manager)r   r   rC   rC   rD   r   =  s   8Iterator[dict | Exception] | Iterator[tuple | Exception]c                 C  s   |   S )a  Returns an iterator through the data this chunk holds.

        In case of this chunk being a local one it iterates through the local already
        parsed data and if it's a remote chunk it will download, parse its data and
        return an iterator through it.
        )create_iterr   rC   rC   rD   __iter__D  s   	zResultBatch.__iter__
connectionSnowflakeConnection | Noner1   c                 K  s  d}|dur	|j nt  }ttD ]$}zt }td| j  | jj	}|| j
td}|re|jre|jjdure|j|d }	td| j d|	  |	jdi |}
W d   n1 s_w   Y  n>| jdur| j|d }	|	jdi |}
W d   n1 sw   Y  ntd| j d	 tjd
d}|jdi |}
|
jtkrtd| j  	 W d   W  n|t|
jrt|
j}t||
jtkrtd|
 ntd|d|
 W d   n1 sw   Y  W q ttfy6 } z<|td krt|tr
|jd }||}|t |}t!d| j d|d  d| d| d	 t"#| W Y d}~qd}~ww |$ | j%t&j'j(< |
S )z;Downloads the data that the ``ResultBatch`` is pointing at.r   Nz%started downloading result batch id: )rP   headerstimeoutrP   zdownloading result batch id: z with existing session r   z/ with new session through local session managerF)use_poolingz)successfully downloaded result batch id: r   z+Failed to fetch the large result set batch z	 for the z th time, backing off for zs for the reason: '')r   rC   ))_backoff_generatorr   rangeMAX_DOWNLOAD_RETRYr'   r@   rA   r   r   rP   r   DOWNLOAD_TIMEOUTrestrw   use_requests_sessionrequestr{   use_sessionr&   r   r   status_coder   r   r   r   r   r    r   	Exception
isinstanceargsnext	exceptiontimesleepget_timing_millisr   rF   rG   value)r   r   kwargssleep_timerbackoffretrydownload_metric	chunk_urlrequest_datasessionresponselocal_session_managerr   erC   rC   rD   	_downloadO  s   



.

8zResultBatch._download`Iterator[dict | Exception] | Iterator[tuple | Exception] | Iterator[Table] | Iterator[DataFrame]c                 K     t  )a  Downloads the data from from blob storage that this ResultChunk points at.

        This function is the one that does the actual work for ``self.__iter__``.

        It is necessary because a ``ResultBatch`` can return multiple types of
        iterators. A good example of this is simply iterating through
        ``SnowflakeCursor`` and calling ``fetch_pandas_batches`` on it.
        NotImplementedError)r   r   rC   rC   rD   r     s   zResultBatch.create_iterc                 C  s"   t sd}t}tt||dd S )NzOptional dependency: 'pandas' is not installed, please see the following link for install instructions: https://docs.snowflake.com/en/user-guide/python-connector-pandas.html#installationmsgerrno)r!   r   r   errorhandler_make_exceptionr   )r   r   r   rC   rC   rD   _check_can_use_pandas  s   z!ResultBatch._check_can_use_pandasr*   c                 C  r   r   r   r   rC   rC   rD   	to_pandas  r   zResultBatch.to_pandasr,   c                 C  r   r   r   r   rC   rC   rD   to_arrow  r   zResultBatch.to_arrowr   c                 K  r   )zDownloads the data that the ``ResultBatch`` is pointing at and populates it into self._data.
        Returns the instance itself.r   r   r   r   rC   rC   rD   populate_data  s   zResultBatch.populate_datar   )r   rQ   r}   r   rs   r   rX   rY   r7   r8   rw   r   rZ   r   )rZ   r8   )rZ   r   )rZ   r   )rZ   r   )rw   r   rZ   r   )r   r$   rZ   r   )rZ   r   )r   r   rZ   r1   )rZ   r   )rZ   r   )rZ   r*   rZ   r,   r   r   rZ   r   )rJ   rK   rL   rM   r   propertyr   r   r   r   rw   setterr   r   r   abcabstractmethodr   r   r   r   r   rC   rC   rC   rD   r      sB    		

V
r   c                      s   e Zd Zdddd7 fddZe	d8d9ddZd:dd Zd;d"d#Zd<d%d&Z	d8d=d)d*Z		d8d>d,d-Z
	d8d?d/d0Zd1d2 Zd3d4 Zd5d6 Z  ZS )@rx   FNru   r   rQ   r}   r   rs   r   rX   rY   r~   ,Sequence[tuple[str, SnowflakeConverterType]]r7   r8   rv   rw   r   rZ   r   c          	        s&   t  |||||| || _|| _d S r   )superr   rz   r~   )	r   r   r}   rs   rX   r~   r7   rv   rw   	__class__rC   rD   r     s   
zJSONResultBatch.__init__r4   Sequence[Sequence[Any]]data_lenc              	   C  s*   | t |dd||||d}|||_|S )z:Initializes a ``JSONResultBatch`` from static, local data.Nr   )r   _parser   )clsr4   r  rX   r~   r7   rw   	new_chunkrC   rC   rD   r     s   	zJSONResultBatch.from_datar   r1   listc              
   C  sn   | j r)z
t|jddd}W n ty( } zd|}t| t|dd}~ww |j}t	d
d|d	gS )
a  This function loads a compressed JSON file into memory.

        Returns:
            Whatever ``json.loads`` return, but in a list.
            Unfortunately there's no type hint for this.
            For context: https://github.com/python/typing/issues/182
        zutf-8strict)errorsz2failed to decode json result content due to error )r   Nr   [])rz   rO   contentr   r@   r   r   textr^   loadsjoin)r   r   	read_dataexcerr_msgrC   rC   rD   _load  s   	


zJSONResultBatch._load0list[dict | Exception] | list[tuple | Exception]c                 C  s  t d| j  g }| jrq|D ]^}i }z(t| j|| jD ]\\}}}}|du s,|du r.|n||||j< q|| W q t	yn }	 z&d|j d| d| d|	 }
t 
|
 |tt|
td W Y d}	~	qd}	~	ww |S |D ]k}dgt| j }z/d}t| j|| jD ]\\}}}}|du s|du r|n||||< |d	7 }q|t| W qs t	y }	 z&d|j d| d| d|	 }
t 
|
 |tt|
td W Y d}	~	qsd}	~	ww |S )
z+Parses downloaded data into its final form.zparsing for result batch id: NzFailed to convert: field z: z::z	, Error: r   r   r   )r@   rA   r   ry   zipr~   r   r   appendr   r   r   r   r   r   r   tuple)r   downloaded_dataresult_listrow
row_result_trk   vr_   r   r   idx_colrC   rC   rD   r    sj   $
% 

zJSONResultBatch._parserO   c                 C     d| j  dS )NzJSONResultChunk()r   r   rC   rC   rD   __repr__V     zJSONResultBatch.__repr__r   r   c                 K  s   | j |d}td| j  t }| |}W d    n1 s"w   Y  td| j  | | jtj	j
< t }| |}W d    n1 sLw   Y  | | jtjj
< |S )Nr   !started loading result batch id: "finished loading result batch id: )r   r@   rA   r   r'   r  r   r   rF   rI   r   r  rH   )r   r   r   r   load_metricr  parse_metricparsed_datarC   rC   rD   _fetch_dataY  s   zJSONResultBatch._fetch_datar   c                 K  s   | j dd|i|| _| S Nr   rC   )r*  r   r   rC   rC   rD   r   i  s   zJSONResultBatch.populate_datar   c                 K  s(   | j rt| jS t| jdd|i|S r+  )r   iterr   r*  r   rC   rC   rD   r   o  s   
zJSONResultBatch.create_iterc                 C  s   t dt|  dS )Nz Trying to use arrow fetching on z which is not ArrowResultChunk)r   ra   r   rC   rC   rD   _arrow_fetching_errorv  s   z%JSONResultBatch._arrow_fetching_errorc                 C     |   r   r-  r   rC   rC   rD   r   |     zJSONResultBatch.to_pandasc                 C  r.  r   r/  r   rC   rC   rD   r     r0  zJSONResultBatch.to_arrow)r   rQ   r}   r   rs   r   rX   rY   r~   r   r7   r8   rv   r8   rw   r   rZ   r   r   )r4   r  r  rQ   rX   rY   r~   r   r7   r8   rw   r   )r   r1   rZ   r  )rZ   r  rZ   rO   )r   r   rZ   r  r   )r   r   rZ   r   )rJ   rK   rL   r   classmethodr   r  r  r"  r*  r   r   r-  r   r   __classcell__rC   rC   r   rD   rx     s&    



8rx   c                      s   e Zd Z	dCdD fddZdEddZdFddZ	 dGdHd%d&Ze	dCdId(d)Z	dCdJd-d.Z		dCdKd0d1Z
dLd3d4ZdCdMd5d6Z	dCdNd8d9Z	dCdOd;d<Z	dCdPd>d?Z	dCdQdAdBZ  ZS )Rr   Nr   rQ   r}   r   rs   r   r6   r   r7   r8   r9   rX   rY   r:   rw   r   rZ   r   c
           
        s,   t  ||||||	 || _|| _|| _d S r   )r   r   _contextr   _number_to_decimal)
r   r   r}   rs   r6   r7   r9   rX   r:   rw   r   rC   rD   r     s   
zArrowResultBatch.__init__rO   c                 C  r  )NzArrowResultChunk(r   r!  r   rC   rC   rD   r"    r#  zArrowResultBatch.__repr__r   r1   r;   r   r   c                 C  s   t |j| j| j| j| j|S )zCreates a ``PyArrowIterator`` from a response.

        This is used to iterate through results in different ways depending on which
        mode that ``PyArrowIterator`` is in.
        )rE   r  r4  ry   r   r5  )r   r   r;   rC   rC   rD   r    s   zArrowResultBatch._loadTr4   str | bytes	iter_unitr<   c                 C  sB   t |dkr
tg S t|trt|}t|| j| j| j| j	||S )zCreates a ``PyArrowIterator`` files from a str.

        This is used to iterate through results in different ways depending on which
        mode that ``PyArrowIterator`` is in.
        r   )
r   r,  r   rO   r   rE   r4  ry   r   r5  )r   r4   r7  r<   rC   rC   rD   
_from_data  s   
zArrowResultBatch._from_datar  c	           
      C  s$   | |dd||||||d	}	||	_ |	S )z<Initializes an ``ArrowResultBatch`` from static, local data.Nr   r   )
r  r4   r  r6   r7   r9   rX   r:   rw   r  rC   rC   rD   r     s   zArrowResultBatch.from_datar   r   JIterator[dict | Exception] | Iterator[tuple | Exception] | Iterator[Table]c              	   C  s  | j r-z| | j||r|jW S dW S  ty,   |r+t|ddr+td| j   w | j|d}td| j	  t
 )}z| ||}W n ty`   |r_t|ddr_td|   w W d   n1 skw   Y  td| j	  | | jtjj< |S )z?Create an iterator for the ResultBatch. Used by get_arrow_iter.N_debug_arrow_chunkFzarrow data can not be parsed: r$  r%  r&  )r   r8  r   ,check_arrow_conversion_error_on_every_columnr   getattrr@   rA   r   r   r'   r  r   r   rF   rI   r   )r   r7  r   r   r'  loaded_datarC   rC   rD   _create_iter  s<   	zArrowResultBatch._create_iterIterator[Table]c                 C  s   | j tj|dS )z?Returns an iterator for this batch which yields a pyarrow Tabler7  r   )r>  r   
TABLE_UNIT)r   r   rC   rC   rD   _get_arrow_iter  s   z ArrowResultBatch._get_arrow_iterr,   c                   s4   t r	dd tD   fdd| jD }t| S )z)Returns empty Arrow table based on schemac                 S  r   rC   )pa_type)rj   r   rC   rC   rD   rl     r   z8ArrowResultBatch._create_empty_table.<locals>.<listcomp>c                   s$   g | ]}t |j |j |qS rC   )pafieldr   	type_coder   r2   rC   rD   rl     s    )r!   r   r   rD  rX   empty_table)r   fieldsrC   rG  rD   _create_empty_table  s   
z$ArrowResultBatch._create_empty_tablec                 C  s&   t | j|dd}|dur|S |  S )z%Returns this batch as a pyarrow Tabler$  N)r   rB  rJ  )r   r   valrC   rC   rD   r     s   zArrowResultBatch.to_arrowr*   c                 K  s$   |    | j|d}|jdi |S )z(Returns this batch as a pandas DataFramer$  NrC   )r   r   r   )r   r   r   tablerC   rC   rD   r     s   zArrowResultBatch.to_pandasIterator[DataFrame]c                 K  s0   g }| j dd|i|}|js|| t|S )z:An iterator for this batch which yields a pandas DataFramer   NrC   )r   emptyr  r,  )r   r   r   iterator_data	dataframerC   rC   rD   _get_pandas_iter'  s
   
z!ArrowResultBatch._get_pandas_iterr   c                 K  sZ   | dtj}|tjkr&| dd}|dkr | jdd|i|S | j|dS | j||dS )	zKThe interface used by ResultSet to create an iterator for this ResultBatch.r7  	structurepandasr   r$  r@  NrC   )popr   rB   rA  rQ  rB  r>  )r   r   r   r7  rR  rC   rC   rD   r   1  s   	
zArrowResultBatch.create_iterr   c                 K  s   | j |dj| _| S )Nr$  )r   r  r   r   rC   rC   rD   r   D  s   zArrowResultBatch.populate_datar   )r   rQ   r}   r   rs   r   r6   r   r7   r8   r9   r8   rX   rY   r:   r8   rw   r   rZ   r   r1  )r   r1   r;   r   rZ   r   T)r4   r6  r7  r   r<   r8   rZ   r   )r4   rO   r  rQ   r6   r   r7   r8   r9   r8   rX   rY   r:   r8   rw   r   )r7  r   r   r   rZ   r9  )r   r   rZ   r?  r   )r   r   rZ   r,   )r   r   rZ   r*   )r   r   rZ   rM  )r   r   rZ   r   r   )rJ   rK   rL   r   r"  r  r8  r2  r   r>  rB  rJ  r   r   rQ  r   r   r3  rC   rC   r   rD   r     s0    


!
	r   rU  )r4   r5   r6   r   r7   r8   r9   r8   r:   r8   r;   r   r<   r8   )
rU   r0   rV   rO   r4   rW   rX   rY   rZ   r[   )X
__future__r   r   r^   r   base64r   enumr   r   loggingr   typingr   r   r	   r
   r   r   typing_extensionsr   r   r   backoff_policiesr   compatr   r   r   	constantsr   r   	errorcoder   r   r  r   r   r   r   networkr   r   r   r   r    optionsr!   r"   rD  secret_detectorr#   rw   r$   r%   r&   	time_utilr'   rJ   r@   r   r   rS  r*   r+   r,   r   r-   rd   r.   rU   r/   r0   vendored.requestsr1   r2   rT   r   r   r   rE   rF   rN   r   ABCr   rx   r   rC   rC   rC   rD   <module>   s\     
#
v x +