o
    SDi~T                     @   s<  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
 d dlmZ d dlmZ dd	lmZ ed
Zdd ZG dd de
ZG dd dZG dd de
ZG dd deZG dd deZG dd deZG dd deZG dd deeZG dd deZG dd  d eZG d!d" d"eZG d#d$ d$eZeZ d
S )%    )Sequence)List)falsetrue)
DDLElement)
UpdateBase)ClauseElement)FromClauseRole   )string_typesNc                 C   s   | rt  S t S N)r   r   )bln r   ]/var/www/Datamplify/venv/lib/python3.10/site-packages/snowflake/sqlalchemy/custom_commands.pytranslate_bool   s   r   c                   @   sL   e Zd ZdZdZdd ZG dd deZdd Zd	d
 Z	dd Z
dd ZdS )	MergeInto
merge_intoNc                 C   s   || _ || _|| _g | _d S r   )targetsourceonclauses)selfr   r   r   r   r   r   __init__      
zMergeInto.__init__c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )zMergeInto.clausemerge_into_clausec                 C   s   i | _ d | _|| _d S r   )set	predicatecommand)r   r   r   r   r   r   &   s   
zMergeInto.clause.__init__c              
   C   s   | j d urdt| j  nd}| jdkr/t| j  \}}d|| jd|dtt|S | jr?ddd | j D nd}d|| j| jrQd	t| S dS )
Nz AND  INSERTz+WHEN NOT MATCHED{} THEN {} ({}) VALUES ({})z, c                 S   s"   g | ]}|d   d|d  qS )r   z = r
   r   ).0r   r   r   r   
<listcomp>:   s   " z-MergeInto.clause.__repr__.<locals>.<listcomp>zWHEN MATCHED{} THEN {}{}z SET )	r   strr   zipr   itemsformatjoinmap)r   case_predicatesetssets_tosr   r   r   __repr__+   s*   

zMergeInto.clause.__repr__c                 K   
   || _ | S r   )r   )r   kwargsr   r   r   valuesD      zMergeInto.clause.valuesc                 C   r,   r   )r   )r   exprr   r   r   whereH   r/   zMergeInto.clause.whereN)__name__
__module____qualname____visit_name__r   r+   r.   r1   r   r   r   r   clause#   s    r6   c                 C   sF   d dd | jD }d| j d| j d| j |r d|  S d S )N c                 S   s   g | ]}t |qS r   )repr)r    r6   r   r   r   r!   M   s    z&MergeInto.__repr__.<locals>.<listcomp>zMERGE INTO z USING z ON r   )r&   r   r   r   r   )r   r   r   r   r   r+   L   s   zMergeInto.__repr__c                 C      |  d}| j| |S )NUPDATEr6   r   appendr   r6   r   r   r   when_matched_then_updateR      
z"MergeInto.when_matched_then_updatec                 C   r9   )NDELETEr;   r=   r   r   r   when_matched_then_deleteW   r?   z"MergeInto.when_matched_then_deletec                 C   r9   )Nr   r;   r=   r   r   r   when_not_matched_then_insert\   r?   z&MergeInto.when_not_matched_then_insert)r2   r3   r4   r5   _bindr   r   r6   r+   r>   rA   rB   r   r   r   r   r      s    )r   c                   @   s*   e Zd ZdZdee fddZdd ZdS )FilesOptionzO
    Class to represent FILES option for the snowflake COPY INTO statement
    
file_namesc                 C   s
   || _ d S r   )rE   r   rE   r   r   r   r   g   s   
zFilesOption.__init__c                 C   s"   dd | j D }dd| dS )Nc                 S   s    g | ]}d | d d d  qS )'z\')replace)r    fr   r   r   r!   k   s     z'FilesOption.__str__.<locals>.<listcomp>(,))rE   r&   )r   	the_filesr   r   r   __str__j   s   zFilesOption.__str__N)r2   r3   r4   __doc__r   r"   r   rN   r   r   r   r   rD   b   s    rD   c                   @   sZ   e Zd ZdZdZdZdddZdd Zdd	 Zd
d Z	dd Z
dd Zdd Zdd ZdS )CopyIntozCopy Into Command base class, for documentation see:
    https://docs.snowflake.net/manuals/sql-reference/sql/copy-into-location.html	copy_intoNc                 C   s"   || _ || _|| _i | _|| _d S r   )from_into	formattercopy_optionspartition_by)r   rR   rS   rV   rT   r   r   r   r   v   
   
zCopyInto.__init__c                 C   sP   d| j  dt| j }| jdur|d| j 7 }|dt| j d| j d S )
        repr for debugging / logging purposes only. For compilation logic, see
        the corresponding visitor in base.py
        z
COPY INTO z FROM Nz PARTITION BY r7    (rL   )rS   r8   rR   rV   rT   rU   )r   valr   r   r   r+   }   s   
zCopyInto.__repr__c                 C   s   d S r   r   r   r   r   r   bind   s   zCopyInto.bindc                 C   *   t |ts	td| jdt|i | S )Nz)Parameter force should be a boolean valueFORCE
isinstancebool	TypeErrorrU   updater   )r   forcer   r   r   rd         
zCopyInto.forcec                 C   r]   )Nz0Parameter single_file should  be a boolean valueSINGLEr_   )r   single_filer   r   r   single   re   zCopyInto.singlec                 C   s&   t |ts	td| jd|i | S )Nz-Parameter max_size should be an integer valueMAX_FILE_SIZE)r`   intrb   rU   rc   )r   max_sizer   r   r   maxfilesize   s   
zCopyInto.maxfilesizec                 C   s   | j dt|i | S )NFILES)rU   rc   rD   rF   r   r   r   files   s   zCopyInto.filesc                 C   s   | j d|i | S )NPATTERN)rU   rc   )r   patternr   r   r   rp      s   zCopyInto.pattern)NN)r2   r3   r4   rO   r5   rC   r   r+   r\   rd   rh   rl   rn   rp   r   r   r   r   rP   o   s    
rP   c                   @   s2   e Zd ZdZdZd
ddZdd Zedd	 ZdS )CopyFormatterz~
    Base class for Formatter specifications inside a COPY INTO statement. May also
    be used to create a named format.
    copy_formatterNc                 C   s   t  | _|r|| jd< d S d S )Nformat_name)dictoptions)r   rs   r   r   r   r      s   zCopyFormatter.__init__c                 C   s   d| j  dS )rX   zFILE_FORMAT=(rL   )ru   r[   r   r   r   r+      s   zCopyFormatter.__repr__c                 C   sP   | dkr|S t |trd| dS t |tr$t|dkr$d|d  dS t|S )a$  
        Make a SQL-suitable representation of "value". This is called from
        the corresponding visitor function (base.py/visit_copy_formatter())
        - in case of a format name: return it without quotes
        - in case of a string: enclose in quotes: "value"
        - in case of a tuple of length 1: enclose the only element in brackets: (value)
            Standard stringification of Python would append a trailing comma: (value,)
            which is not correct in SQL
        - otherwise: just convert to str as is: value
        rs   rG   r
   z('r   z'))r`   r"   tuplelen)namevaluer   r   r   
value_repr   s   
zCopyFormatter.value_reprr   )	r2   r3   r4   rO   r5   r   r+   staticmethodrz   r   r   r   r   rq      s    
rq   c                   @   s   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"S )#CSVFormattercsvc                 C   >   t |tr	| }g d}||vrtd| || jd< | S zqString (constant) that specifies to compresses the unloaded data files using the specified compression algorithm.)autogzipbz2brotlizstddeflateraw_deflateNz$Compression type should be one of : COMPRESSIONr`   r   lowerrb   ru   r   	comp_type_available_optionsr   r   r   compression      


zCSVFormatter.compressionc                 C   sR   t |trdS t |tr| d}t|dkrdS t |tr"dS t| d)z
        Check if a delimiter is either a string of length 1 or an integer. In case of
        a string delimiter, take into account that the actual string may be longer,
        but still evaluate to a single character (like "\n" or r"
"
        Nunicode_escaper
   zC should be a single character, that is either a string, or a number)r`   NoneTyper   encodedecoderw   rj   rb   )r   	delimiterdelimiter_txtdelimiter_processedr   r   r   _check_delimiter   s   


zCSVFormatter._check_delimiterc                 C   6   |  |d t|trt|| jd< | S || jd< | S )z5Character that separates records in an unloaded file.zRecord delimiterRECORD_DELIMITERr   r`   rj   hexru   r   	deli_typer   r   r   record_delimiter      

zCSVFormatter.record_delimiterc                 C   r   )z4Character that separates fields in an unloaded file.zField delimiterFIELD_DELIMITERr   r   r   r   r   field_delimiter  r   zCSVFormatter.field_delimiterc                 C   $   t |ttfstd|| jd< | S zString that specifies the extension for files unloaded to a stage. Accepts any extension. The user is
        responsible for specifying a valid file extension that can be read by the desired software or service.
        z!File extension should be a stringFILE_EXTENSIONr`   r   r   rb   ru   r   extr   r   r   file_extension
     
zCSVFormatter.file_extensionc                 C       t |ts	td|| jd< | S )zIString that defines the format of date values in the unloaded data files.zDate format should be a stringDATE_FORMATr`   r   rb   ru   )r   dt_frmtr   r   r   date_format     

zCSVFormatter.date_formatc                 C   r   )zIString that defines the format of time values in the unloaded data files.zTime format should be a stringTIME_FORMATr   )r   tm_frmtr   r   r   time_format  r   zCSVFormatter.time_formatc                 C   r   )zNString that defines the format of timestamp values in the unloaded data files.z#Timestamp format should be a stringTIMESTAMP_FORMATr   )r   tmstmp_frmtr   r   r   timestamp_format!  r   zCSVFormatter.timestamp_formatc                 C   r~   )zCharacter used as the escape character for any field values. The option can be used when unloading data
        from binary columns in a table.)r   base64utf8z!Binary format should be one of : BINARY_FORMATr   )r   bin_fmtr   r   r   r   binary_format(  s   

zCSVFormatter.binary_formatc                 C   r   )z<Character used as the escape character for any field values.EscapeESCAPEr   r   escr   r   r   escape3  r   zCSVFormatter.escapec                 C   r   )zVSingle character string used as the escape character for unenclosed field values only.zEscape unenclosed fieldESCAPE_UNENCLOSED_FIELDr   r   r   r   r   escape_unenclosed_field<  r   z$CSVFormatter.escape_unenclosed_fieldc                 C   s,   g d}||vrt d| || jd< | S )z8Character used to enclose strings. Either None, ', or ".)NrG   "z$Enclosing string should be one of : FIELD_OPTIONALLY_ENCLOSED_BY)rb   ru   )r   encr   r   r   r   field_optionally_enclosed_byE  s
   
z)CSVFormatter.field_optionally_enclosed_byc                 C   $   t |ts	tdt|| jd< | S )zCopying into a table these strings will be replaced by a NULL, while copying out of Snowflake will replace
        NULL values with the first stringz*Parameter null_value should be an iterableNULL_IF)r`   r   rb   rv   ru   )r   
null_valuer   r   r   null_ifM  s   
zCSVFormatter.null_ifc                 C   r   )zR
        Number of header rows to be skipped at the beginning of the file
        zskip_header  should be an intSKIP_HEADER)r`   rj   rb   ru   )r   skip_headerr   r   r   r   U     

zCSVFormatter.skip_headerc                 C   r   )z9
        Remove leading or trailing white spaces
        ztrim_space should be a bool
TRIM_SPACEr`   ra   rb   ru   )r   
trim_spacer   r   r   r   ^  r   zCSVFormatter.trim_spacec                 C   r   )z
        Generate a parsing error if the number of delimited columns (i.e. fields) in
        an input data file does not match the number of columns in the corresponding table.
        zskip_header  should be a boolERROR_ON_COLUMN_COUNT_MISMATCHr   )r   error_on_col_count_mismatchr   r   r   error_on_column_count_mismatchg  s   

z+CSVFormatter.error_on_column_count_mismatchN)r2   r3   r4   file_formatr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r|      s$    							r|   c                   @   s$   e Zd ZdZdZdd Zdd ZdS )JSONFormatterFormat specific functionsjsonc                 C   r~   r   r   r   r   r   r   r   w  r   zJSONFormatter.compressionc                 C   r   r   r   r   r   r   r   r     r   zJSONFormatter.file_extensionN)r2   r3   r4   rO   r   r   r   r   r   r   r   r   r  s
    r   c                   @   s,   e Zd ZdZdZdd Zdd Zdd Zd	S )
PARQUETFormatterr   parquetc                 C   r   )z%Enable, or disable snappy compressionzComp should be a Boolean valueSNAPPY_COMPRESSIONr`   ra   rb   r   ru   r   compr   r   r   snappy_compression     
z#PARQUETFormatter.snappy_compressionc                 C   r   )z&
        Set compression type
        zComp should be a str valuer   )r`   r"   rb   ru   r   r   r   r   r     r   zPARQUETFormatter.compressionc                 C   r   )z!Enable, or disable binary as textz(binary_as_text should be a Boolean valueBINARY_AS_TEXTr   )r   ry   r   r   r   binary_as_text  r   zPARQUETFormatter.binary_as_textN)r2   r3   r4   rO   r   r   r   r   r   r   r   r   r     s    	r   c                   @   sP   e Zd ZdZdZdZedd Zedd Zdd	d
Z	dd Z
edddZdS )ExternalStagezExternal Stage descriptorexternal_stager   c                 C   s   |  ds
|  dS | S )N.)endswith)	namespacer   r   r   prepare_namespace     zExternalStage.prepare_namespacec                 C   s   |  ds
d|  S | S )N/)
startswith)pathr   r   r   prepare_path  r   zExternalStage.prepare_pathNc                 C   s8   || _ |r
| |nd| _|r| |nd| _|| _d S )Nr   )rx   r   r   r   r   r   )r   rx   r   r   r   r   r   r   r     s   
zExternalStage.__init__c                 C   s"   d| j  | j | j d| j dS )N@rY   rL   )r   rx   r   r   r[   r   r   r   r+     s   "zExternalStage.__repr__c                 C   s   | |j |j d| |j|S )zl
        Extend an existing parent stage (with or without path) with an
        additional sub-path
        r   )rx   r   r   )clsparent_stager   r   r   r   r   from_parent_stage  s   zExternalStage.from_parent_stage)NNNr   )r2   r3   r4   rO   r5   _hide_fromsr{   r   r   r   r+   classmethodr   r   r   r   r   r     s    


r   c                       s&   e Zd ZdZdZd fdd	Z  ZS )CreateFileFormatz
    Encapsulates a CREATE FILE FORMAT statement; using a format description (as in
    a COPY INTO statement) and a format name.
    create_file_formatFc                    s    t    || _|| _|| _d S r   )superr   rs   rT   replace_if_exists)r   rs   rT   r   	__class__r   r   r     s   

zCreateFileFormat.__init__Fr2   r3   r4   rO   r5   r   __classcell__r   r   r   r   r     s    r   c                       s,   e Zd ZdZdZddd fddZ  ZS )CreateStagez
    Encapsulates a CREATE STAGE statement, using a container (physical base for the
    stage) and the actual ExternalStage object.
    create_stageF)	temporaryc                   s&   t    || _|| _|| _|| _d S r   )r   r   	containerr   stager   )r   r   r   r   r   r   r   r   r     s
   

zCreateStage.__init__r   r   r   r   r   r   r     s    r   c                   @   sX   e Zd ZdZdZdddZedd Zdd	 Z	dd
dZ	dd Z
dd ZdddZdS )	AWSBucketzAWS S3 bucket descriptor
aws_bucketNc                 C   s   || _ || _i | _i | _d S r   )bucketr   encryption_usedcredentials_used)r   r  r   r   r   r   r     r   zAWSBucket.__init__c                 C   s`   |dd dkrt d| |dd  dd}t|dkr'|d d }}n|\}}| ||S )Nr      zs3://zInvalid AWS bucket URI: r   r
   
ValueErrorsplitrw   )r   uribr  r   r   r   r   from_uri   s   
zAWSBucket.from_uric                 C   s   d ddd | j D }d ddd | j D }d | j| jr-d| j nd	}d
 || jr;d| nd	| jrEd| S d	S )NCREDENTIALS=({})r7   c                 s   $    | ]\}}| d | dV  qdS ='rG   Nr   r    nvr   r   r   	<genexpr>     " z%AWSBucket.__repr__.<locals>.<genexpr>ENCRYPTION=({})c                 s   <    | ]\}}t |tr| d | dn| d| V  qdS r  rG   =Nr`   r   r  r   r   r   r    
    &
z's3://{}{}'r   r   {}{}{})r%   r&   r  r$   r  r  r   r   credentials
encryptionr  r   r   r   r+     s    
 zAWSBucket.__repr__c                 C   sP   |d u r|d u r|d u rt d|rd|i| _| S ||d| _|r&|| jd< | S )NzFEither 'aws_role', or aws_key_id and aws_secret_key has to be suppliedAWS_ROLE)AWS_SECRET_KEY
AWS_KEY_ID	AWS_TOKEN)r  r  )r   aws_role
aws_key_idaws_secret_key	aws_tokenr   r   r   r    s   

zAWSBucket.credentialsc                 C      d|d| _ | S )NAWS_CSETYPE
MASTER_KEYr  r   
master_keyr   r   r   encryption_aws_cse.     zAWSBucket.encryption_aws_csec                 C   s   ddi| _ | S )Nr)  
AWS_SSE_S3r+  r[   r   r   r   encryption_aws_sse_s32     
zAWSBucket.encryption_aws_sse_s3c                 C   s   ddi| _ |r|| j d< | S )Nr)  AWS_SSE_KMS
KMS_KEY_IDr+  )r   
kms_key_idr   r   r   encryption_aws_sse_kms6  s   

z AWSBucket.encryption_aws_sse_kmsr   )NNNN)r2   r3   r4   rO   r5   r   r   r
  r+   r  r.  r1  r6  r   r   r   r   r     s    



r   c                   @   sB   e Zd ZdZdZdddZedd Zdd	 Zd
d Z	dd Z
dS )AzureContainerz$Microsoft Azure Container descriptorazure_containerNc                 C   s"   || _ || _|| _i | _i | _d S r   )accountr   r   r  r  )r   r9  r   r   r   r   r   r   B  rW   zAzureContainer.__init__c                 C   s   |dd dkrt d| |dd  dd\}}|dd dkr*t d| |dd  d	d}t|dkrB|d d }}n|\}}| |||S )
Nr      zazure://zInvalid Azure Container URI: r   r
      zblob.core.windows.net/r   r  )r   r  r9  r	  r   r   r   r   r   r
  I  s   zAzureContainer.from_uric                 C   s   d ddd | j D }d ddd | j D }d | j| j| jr/d| j nd	}d
 || jr=d| nd	| jrGd| S d	S )Nr  r7   c                 s   r  r  r   r  r   r   r   r  Y  r  z*AzureContainer.__repr__.<locals>.<genexpr>r  c                 s   r  r  r  r  r   r   r   r  \  r  z''azure://{}.blob.core.windows.net/{}{}'r   r   r  )r%   r&   r  r$   r  r9  r   r   r  r   r   r   r+   W  s$   
zAzureContainer.__repr__c                 C   s   d|i| _ | S )NAZURE_SAS_TOKEN)r  )r   azure_sas_tokenr   r   r   r  j  r2  zAzureContainer.credentialsc                 C   r&  )N	AZURE_CSEr(  r+  r,  r   r   r   encryption_azure_csen  r/  z#AzureContainer.encryption_azure_cser   )r2   r3   r4   rO   r5   r   r   r
  r+   r  r?  r   r   r   r   r7  =  s    

r7  )!collections.abcr   typingr   
sqlalchemyr   r   sqlalchemy.sql.ddlr   sqlalchemy.sql.dmlr   sqlalchemy.sql.elementsr   sqlalchemy.sql.rolesr	   compatr   typer   r   r   rD   rP   rq   r|   r   r   r   r   r   r   r7  CopyIntoStorager   r   r   r   <module>   s0   I7* #"%H6