o
    SDi 4                     @   s|  d dl 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 d dlmZ d d	lm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  d dl!m"Z" d dl#m$Z$ d dl%m&Z& ddl'm(Z(m)Z)m*Z*m+Z+m,Z, dd Z-dd Z.de$de/ddfddZ0dedefddZ1de2de/fd d!Z3de2de4fd"d#Z5d$d% Z6G d&d' d'eZ7G d(d) d)eZ8dS )*    N)chain)Any)
quote_plus)exc
inspectionsql)NoForeignKeysError)MapperProperty)_ORMJoin)
attributes)util)_expand_cloned_from_objects)_find_columns)JoinLateral	coercions	operatorsroles)IS_STR)SnowflakeConnection)compat   )APPLICATION_NAMEPARAM_APPLICATIONPARAM_INTERNAL_APPLICATION_NAME"PARAM_INTERNAL_APPLICATION_VERSIONSNOWFLAKE_SQLALCHEMY_VERSIONc                 C   s   t ddd | S )Nz[:@/]c                 S   s   dt | d S )Nz%%%Xr   )ordgroup)m r!   R/var/www/Datamplify/venv/lib/python3.10/site-packages/snowflake/sqlalchemy/util.py<lambda>"   s    z!_rfc_1738_quote.<locals>.<lambda>)resub)textr!   r!   r"   _rfc_1738_quote!   s   r'   c                  K   s  g }d| vrt dd| v r3dj| ddt| dd| d d| v r(| d nd	d
}|g d
7 }n<d| vrRdj| d | ddt| ddd}|g d7 }ndj| d | ddt| dd| d d}|g d7 }d| v r|t| d 7 }|dg7 }d| v r|dt| d  7 }|dg7 }n	d| v rt ddd }d}t|  D ]$}| | }||vrt|rt|nt	|}|||| d | 7 }d}q|S )a  
    Composes a SQLAlchemy connect string from the given database connection
    parameters.

    Password containing special characters (e.g., '@', '%') need to be encoded to be parsed correctly.
    Unescaped password containing special characters might lead to authentication failure.
    Please follow the instructions to encode the password:
    https://github.com/snowflakedb/snowflake-sqlalchemy#escaping-special-characters-such-as---signs-in-passwords
    accountz$account parameter must be specified.hostz,snowflake://{user}:{password}@{host}:{port}/user passwordporti  )r*   r,   r)   r-   regionz(snowflake://{user}:{password}@{account}/)r(   r*   r,   )r*   r,   r(   z1snowflake://{user}:{password}@{account}.{region}/)r(   r*   r,   r.   )r*   r,   r(   r.   databaseschema/z+schema cannot be specified without databasec                 S   s   | rdS dS )N?&r!   )is_first_parameterr!   r!   r"   sepT   s   z_url.<locals>.sepT=F)
r   ArgumentErrorformatgetr'   r   sortedkeysr   str)db_parametersspecified_parametersretr5   r4   pvencoded_valuer!   r!   r"   _url%   sX   







rC   dbapi_connectionflagreturnc                 C   s    t | dr|| j_dS || _dS )zHset the _interpolate_empty_sequences config of the underlying connectiondriver_connectionN)hasattrrG   _interpolate_empty_sequences)rD   rE   r!   r!   r"   +_set_connection_interpolate_empty_sequencesa   s   

rJ   conn_kwargsc                  K   s4   t | vrt| t < t| vrt| t< t| vrt| t< | S )N)r   r   r   r   r   )rK   r!   r!   r"   #_update_connection_application_namem   s   rL   valuec                 C   s(   | dkrdS | dkrdS t d|  d)NTrueTFalseFz!Invalid boolean value detected: '')
ValueError)rM   r!   r!   r"   parse_url_booleanw   s
   rR   c              
   C   s4   zt | W S  ty } ztd|  |d }~ww )NzInvalid int value detected: ')intrQ   )rM   er!   r!   r"   parse_url_integer   s   
rU   c           
         s  g }t t|}t dkr|durd}t|}nd}d}t D ]D\}}||gD ]9}	|rCt |j|	j|rB|	|  n#q+|dusMt
||	rT|	|  n|du rdt|	trd|	|  nq+q!t|dkrt tdd  D   fdd|D }|s|durtt S |S )a  Given a list of FROM clauses, a selectable,
    and optional ON clause, return a list of integer indexes from the
    clauses list indicating the clauses that can be joined from.

    The presence of an "onclause" indicates that at least one clause can
    definitely be joined from; if the list of clauses is of length one
    and the onclause is given, returns that index.   If the list of clauses
    is more than length one, and the onclause is given, attempts to locate
    which clauses contain the same columns.

    r   NTFc                 S   s   g | ]}t |jqS r!   )r   _hide_froms).0fr!   r!   r"   
<listcomp>   s    z2_find_left_clause_to_join_from.<locals>.<listcomp>c                    s   g | ]
} | vr|qS r!   r!   )rW   iclausestoremover!   r"   rY      s    )setr   lenr   	enumerate
differencecunion
issupersetappendr   	_can_join
isinstancer   r   range)
r\   join_toonclauseidxselectablesresolve_ambiguitycols_in_onclauserZ   rX   sr!   r[   r"   _find_left_clause_to_join_from   s6   



rp   c                   @   s"   e Zd Z						dddZdS )_Snowflake_ORMJoinNFr!   c	                 C   s  t |}	t |}
|
j}|| _|| _t|d|	}|
| _t|tj	r(t|j
|}t|tjr<|j }|j}||j7 }nt|trH|}|jj}nd }|r|	j}t||rX|}n|}|j||d|
d|d\}}}}}}|d ur|r{t|||}|}nt||||}|}n|}|| _|	jr|jdd }n|	js|	jr|	}nd }|d ur| jd|i| _|d u o|}t | ||||| |r|  j!tj"| M  _!|st|
dd r|
j#j$r|
j#j%}|d ur|
jr|
j&'|}| j!|@ | _!d S d S d S d S d S )N_joined_from_infoT)source_selectabledest_selectablesource_polymorphicof_type_entityalias_secondaryextra_criteriaparententitymapper)(r   inspect
selectable
_left_memo_right_memogetattrrr   rg   r   string_typesentityr   QueryableAttribute
comparator_source_selectableproperty_extra_criteriar	   parentsql_utilclause_is_present_create_joinsr   join_target_adapteris_selectable_annotationsr9   	is_mapperis_aliased_classrc   _Snowflake_Selectable_Join__init__rj   and_rz   single_single_table_criterion_adaptertraverse)selfleftrightrj   isouterfullr}   r~   r   	left_info
right_infoadapt_toleft_orm_infoon_selectablepropleft_selectable
adapt_frompjsjsourcedest	secondarytarget_adapterry   augment_onclausesingle_critr!   r!   r"   r      s   




	

	z_Snowflake_ORMJoin.__init__)NFFNNr!   __name__
__module____qualname__r   r!   r!   r!   r"   rq      s    rq   c                   @   s   e Zd ZdddZdS )r   NFc                 C   s   t jtj|dd| _t jtj|dd | _|du r:z| | j| j| _W n! t	y9   t
| jtr6d| _n Y nw t tj|jtjd| _|| _|| _dS )zConstruct a new :class:`_expression.Join`.

        The usual entrypoint here is the :func:`_expression.join`
        function or the :meth:`_expression.FromClause.join` method of any
        :class:`_expression.FromClause` object.

        T)
deannotateN)against)r   expectr   FromClauseRoler   
self_groupr   _match_primariesrj   r   rg   r   OnClauseRoler   _asboolr   r   )r   r   r   rj   r   r   r!   r!   r"   r   :  s(   	
z#_Snowflake_Selectable_Join.__init__)NFFr   r!   r!   r!   r"   r   9  s    r   )9r$   	itertoolsr   typingr   urllib.parser   
sqlalchemyr   r   r   sqlalchemy.excr   sqlalchemy.orm.interfacesr	   sqlalchemy.orm.utilr
   sa_orm_util_ORMJoinr   sqlalchemy.sqlr   r   sqlalchemy.sql.baser   r   sqlalchemy.sql.elementsr   sqlalchemy.sql.selectabler   r   r   r   r   snowflake.connector.compatr   snowflake.connector.connectionr   snowflake.sqlalchemyr   
_constantsr   r   r   r   r   r'   rC   boolrJ   rL   r<   rR   rS   rU   rp   rq   r   r!   r!   r!   r"   <module>   s@   	<

	;s