o
    QDi3                     @  s   d dl mZ d dlZd dl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mZmZ ddlmZ d	d
lmZ er\d dlmZmZmZ d dlmZmZ d dlmZ ddlmZ G dd deZdS )    )annotationsN)datedatetimetimezone)TYPE_CHECKINGAnyDictListType   )platform)FieldSchema)Mapper   )settings)CheckConstraint
ConstraintDialect)ColumnTable)
TypeEngine)Rowc                   @  s   e Zd ZU dZded< d-ddZddd.ddZd/ddZd0ddZdddd1ddZ	ddd2d!d"Z
d3d%d&Zddd4d*d+Zd,S )5	SqlMapperzMetadata mapper Frictionless from/to SQL

    Partially based on unmerged @ezwelty's work:
    - https://github.com/frictionlessdata/framework/pull/862

    r   dialectstrc                 C  s   t jj| | _d S )N)r   sqlalchemy_dialectsregistryloadr   )selfr    r    X/var/www/Datamplify/venv/lib/python3.10/site-packages/frictionless/formats/sql/mapper.py__init__   s   zSqlMapper.__init__F)with_metadatatabler   r#   boolreturnr   c                C  s  t j}t }|jD ]}|r|jtjv rq	| |}|| q	|j	D ] }t
||jrB|jD ]}|r8|jtjv r8q-|jt|j q-q"|j	D ]C}t
||jrd}g }	g }
|jD ]#}|	t|jj |jjj|jkrqt|jjj}|
t|jj qW||
d}|j|	|d qF|S )z/Convert sqlalchemy table to frictionless schema )resourcefields)r)   	reference)r   
sqlalchemyr   columnsnamer   METADATA_IDENTIFIERS
read_field	add_fieldconstraints
isinstancePrimaryKeyConstraintprimary_keyappendr   ForeignKeyConstraintelementsparentcolumnr$   foreign_keys)r   r$   r#   saschemar9   field
constraintr(   
own_fieldsforeign_fieldselementrefr    r    r!   read_schema#   s8   






zSqlMapper.read_schemar9   r   r   c                 C  sh  t j}t j}t j}i |jd|jd|jd|jd|jd|j	d|j
d|jd|jd|jd|jd|jd	|jd|jd|jd|jd}t|j}d}| D ]\}}	t|j|rb|	}qVtt||d
}
t|j|j|jfr|jjr|jj|
jd< t|j|jr|jjr|jj|
jd< t|j|jr|jjr|jj|
jd< |j sd|
_!|j"r|j"|
_#|
S )z/Convert sqlalchemy Column to frictionless Fieldarraystringbooleanr   r   numberintegerobjecttime)r-   type	maxLength	minLengthenumT)$r   r+   sqlalchemy_dialects_postgresqlsqlalchemy_dialects_mysqlARRAYBITBooleanDateDateTimeFloatIntegerJSONBJSONNumericTextTime	VARBINARYVARCHARUUIDr   r-   itemsr2   rK   r   from_descriptordictCHARlengthr1   Enumenumsnullablerequiredcommentdescription)r   r9   r;   sapgsamsmappingr-   rK   
type_classvaluer=   r    r    r!   r/   G   sr   	

zSqlMapper.read_fieldcolumn_typec           	      C  s   t j}t j}t j}i |jd|jd|jd|jd|jd|j	d|j
d|jd|jd|jd|jd|jd	|jd|jd|jd|jd}d}| D ]\}}t||r\|}qQ|S )
z,Convert sqlalchemy type to frictionless typerD   rE   rF   r   r   rG   rH   rI   rJ   )r   r+   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r^   r_   r`   r2   )	r   rp   r;   rk   rl   rm   
field_typern   ro   r    r    r!   	read_typex   sT   	

zSqlMapper.read_type)r#   ignore_constraintsr<   
table_namers   c                  s  t j}g }g }|r"||jtj|jddd ||tj|j |j	D ]}| j
|||d}	||	 q%|jrJ|r=|jn|j}
|
|j }|| |jD ],}|d }|d d }|d d p`|  fdd	}tt||}|||}|| qM|| g|}|s||7 }|j| }|S )
z/Convert frictionless schema to sqlalchemy tableTF)r4   autoincrement)rt   rs   r)   r*   r(   c                   s   d  | gS )N.)join)r=   foreign_table_namer    r!   <lambda>   s    z(SqlMapper.write_schema.<locals>.<lambda>)r   r+   r5   r   r   ROW_NUMBER_IDENTIFIERrW   ROW_VALID_IDENTIFIERrS   r)   write_fieldr4   UniqueConstraintr3   r:   listmapr6   MetaDatar   )r   r<   rt   r#   rs   r;   r,   r1   r=   r9   Classr>   fkr)   r@   composer
table_argsr$   r    rx   r!   write_schema   sF   	




zSqlMapper.write_schema)rs   r=   c                C  sH  t j}| jjj}|j}g }||j}| |j}	|j	 }
|j
dd}| jjdkr0|o/|	|ju}|jdkr|j
dd}|j
dd}|durT|durT||krT||}	|durt|	|ju rc|j|d}	| jjd	krt||d
||f  |durt|	|jr| jjd	kr||d||f  |j
 D ]f\}}|dkr||d||f  q|dkr||d||f  q|dkr| jjdkr||d||f  q| jjdkr|d||f }|| q|dkr|jdkrd||jf }|j|d|i}	q|j|	g}i }|jr|j|d< |s||7 }|
|d< ||d< |j|i |}|S )z/Convert frictionless Field to sqlalchemy ColumnuniqueFmysqlrE   rM   NrL   )rd   sqlitezLENGTH(%s) <= %szLENGTH(%s) >= %sminimumz%s >= %smaximumz%s <= %spattern
postgresqlz	%s ~ '%s'duckdbz%s REGEXP '%s'rN   z
%s_%s_enumr-   ri   rg   )r   r+   r   identifier_preparerquoter   r-   
write_typerK   rh   r1   getr[   rc   r^   r5   r2   r`   re   rj   r   )r   r=   rt   rs   r;   r   Checkchecksquoted_namerp   rg   r   
min_length
max_lengthconstro   check	enum_namecolumn_argscolumn_kwargsr9   r    r    r!   r}      sh   








zSqlMapper.write_fieldrq   Type[TypeEngine]c              
   C  sl   t j}t j}|j|j|j|j|j|j|j|j	|jd	}| j
jdkr/||j|j|j|jd |||jS )z,Convert frictionless type to sqlalchemy type)	anyrF   r   r   rH   rG   rE   rJ   yearr   )rD   geojsonrG   rI   )r   r+   rO   r[   rS   rT   rU   rW   rV   r\   r   r-   updaterX   rZ   r   )r   rq   r;   rk   rm   r    r    r!   r      s*   	zSqlMapper.write_typerowr   Dict[str, Any]c          
      C  s   t j}i }|r|j|d< |j|d< |jD ]e}||j }|durt| |j}|jdkr7||ju r7|	|\}}n=|jdv rBt
|}n2|jdkrY|jdurX|tj}	|	jdd}n|jdkrt|jdurtttj|}	|	tj}	|	 }|||j< q|S )	z;Convert frictionless Row to a sqlalchemy Item for insertion
_rowNumber	_rowValidNrE   )rI   r   r   )tzinforJ   )r   r+   
row_numbervalidr)   r-   r   rK   r[   
write_celljsondumpsr   
astimezoner   utcreplacer   combiner   minrJ   )
r   r   r#   r;   itemr=   cellrp   _dtr    r    r!   	write_row?  s2   








zSqlMapper.write_rowN)r   r   )r$   r   r#   r%   r&   r   )r9   r   r&   r   )rp   r   r&   r   )
r<   r   rt   r   r#   r%   rs   r%   r&   r   )r=   r   rt   r   rs   r%   r&   r   )rq   r   r&   r   )r   r   r#   r%   r&   r   )__name__
__module____qualname____doc____annotations__r"   rC   r/   rr   r   r}   r   r   r    r    r    r!   r      s   
 

$
1(:
Lr   ) 
__future__r   r   r   r   r   typingr   r   r   r	   r
   r   r<   r   r   systemr   r'   r   r+   r   r   r   sqlalchemy.schemar   r   sqlalchemy.typesr   r$   r   r   r    r    r    r!   <module>   s    