o
    ;Di+                     @   s  d Z ddlZddl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mZmZmZmZmZ eeZejZdd	d
dddddddd
ZdZdZdZd0ddZ		d1ddZ		d2ddZ		d3ddZd4d 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 )5aC  
Module providing some convenience functions for working with SQL databases.
SQLAlchemy is required, try ``apt-get install python-sqlalchemy``
or ``pip install SQLAlchemy``.

Acknowledgments: much of the code of this module is based on the ``csvsql``
utility in the `csvkit <https://github.com/onyxfish/csvkit>`_ package.

    N)long	text_type)ArgumentError)columns)head)_is_dbapi_connection_is_dbapi_cursor_is_sqlalchemy_engine_is_sqlalchemy_session_is_sqlalchemy_connection_quotezaccess.basezfirebird.kinterbasdbzinformix.informixdbzmaxdb.sapdbzmssql.pyodbczmysql.mysqlconnectorzoracle.cx_oraclezpostgresql.psycopg2zsqlite.pysqlitezsybase.pyodbc)
accessfirebirdinformixmaxdbmssqlmysqloracle
postgresqlsqlitesybaseii      Tc                 C   s  ddl }dd | D }i }i }t|dkr|j}|rt|d< ntdd |D r,|j}ntdd |D rIt|tksAt|t	k rE|j
}no|j}nktd	d |D rV|j
}n^td
d |D rc|j
}nQtdd |D rp|j}nDtdd |D r}|j}n7tdd |D r|j}n*tdd |D r|j}ntdd |D r|j}n|j}|rtdd | D |d< |rt|t| k |d< |j||di |fi |S )a7  
    Infer an appropriate SQLAlchemy column type based on a sequence of values.

    Keyword arguments:

    col : sequence
        A sequence of values to use to infer type, length etc.
    colname : string
        Name of column
    constraints : bool
        If True use length and nullable constraints

    r   Nc                 S   s   g | ]}|d ur|qS N .0vr   r   J/var/www/Datamplify/venv/lib/python3.10/site-packages/petl/io/db_create.py
<listcomp>B       z*make_sqlalchemy_column.<locals>.<listcomp>lengthc                 s       | ]}t |tV  qd S r   )
isinstanceboolr   r   r   r   	<genexpr>K       z)make_sqlalchemy_column.<locals>.<genexpr>c                 s   r!   r   )r"   intr   r   r   r   r$   N   r%   c                 s   r!   r   )r"   r   r   r   r   r   r$   U   r%   c                 s       | ]
}t |ttfV  qd S r   )r"   r&   r   r   r   r   r   r$   X       c                 s   s     | ]}t |tttfV  qd S r   )r"   r&   r   floatr   r   r   r   r$   [   s    c                 s   s    | ]	}t |tjV  qd S r   )r"   datetimer   r   r   r   r$   ^       c                 s       | ]	}t |tjV  qd S r   )r"   r*   dater   r   r   r   r$   a   r+   c                 s   r,   r   )r"   r*   timer   r   r   r   r$   d   r+   c                 s   r'   r   )r"   dictlistr   r   r   r   r$   g   r(   c                 S   s   g | ]}t t|qS r   )lenr   r   r   r   r   r   m   r   nullabler   )
sqlalchemyr1   StringNULL_COLUMN_MAX_LENGTHallBooleanmaxSQL_INTEGER_MAXminSQL_INTEGER_MIN
BigIntegerIntegerFloatDateTimeDateTimeJSONColumn)colcolnameconstraintsr3   col_not_nonesql_column_kwargssql_type_kwargssql_column_typer   r   r   make_sqlalchemy_column1   sL   rK   c                 C   sb   ddl }|s
| }|j|||d}t| }t| }|D ]}	t||	 |	|d}
||
 q|S )a  
    Create an SQLAlchemy table definition based on data in `table`.

    Keyword arguments:

    table : table container
        Table data to use to infer types etc.
    tablename : text
        Name of the table
    schema : text
        Name of the database schema to create the table in
    constraints : bool
        If True use length and nullable constraints
    metadata : sqlalchemy.MetaData
        Custom table metadata

    r   N)schema)rF   )r3   MetaDataTabler   r0   keysrK   append_column)table	tablenamerL   rF   metadatar3   	sql_tablecolsfldsf
sql_columnr   r   r   make_sqlalchemy_tablev   s   
rY   c           
      C   s^   ddl }t| ||||d}|rtdt|  dgd}| }	nd}	t|j|j|	d	 S )aE  
    Generate a CREATE TABLE statement based on data in `table`.

    Keyword arguments:

    table : table container
        Table data to use to infer types etc.
    tablename : text
        Name of the table
    schema : text
        Name of the database schema to create the table in
    constraints : bool
        If True use length and nullable constraints
    metadata : sqlalchemy.MetaData
        Custom table metadata
    dialect : text
        One of {'access', 'sybase', 'sqlite', 'informix', 'firebird', 'mysql',
        'oracle', 'maxdb', 'postgresql', 'mssql'}

    r   N)rL   rF   rS   zsqlalchemy.dialects.%sdialect)fromlist)rZ   )
r3   rY   
__import__DIALECTSrZ   r   rL   CreateTablecompilestrip)
rQ   rR   rL   rF   rS   rZ   r3   rT   modulesql_dialectr   r   r   make_create_table_statement   s    
rc     c	           
      C   s8   |dkr	t | |} t| |||||d}	t|	||d dS )a}  
    Create a database table based on a sample of data in the given `table`.

    Keyword arguments:

    table : table container
        Table data to load
    dbo : database object
        DB-API 2.0 connection, callable returning a DB-API 2.0 cursor, or
        SQLAlchemy connection, engine or session
    tablename : text
        Name of the table
    schema : text
        Name of the database schema to create the table in
    commit : bool
        If True commit the changes
    constraints : bool
        If True use length and nullable constraints
    metadata : sqlalchemy.MetaData
        Custom table metadata
    dialect : text
        One of {'access', 'sybase', 'sqlite', 'informix', 'firebird', 'mysql',
        'oracle', 'maxdb', 'postgresql', 'mssql'}
    sample : int
        Number of rows to sample when inferring types etc., set to 0 to use
        the whole table

    r   )rL   rF   rS   rZ   )commitN)r   rc   _execute)
rQ   dborR   rL   re   rF   rS   rZ   samplesqlr   r   r   create_table   s   
rj   c                 C   s8   t |}|durt |d | }d| }t|| | dS )ay  
    Drop a database table.

    Keyword arguments:

    dbo : database object
        DB-API 2.0 connection, callable returning a DB-API 2.0 cursor, or
        SQLAlchemy connection, engine or session
    tablename : text
        Name of the table
    schema : text
        Name of the database schema the table is in
    commit : bool
        If True commit the changes

    N.zDROP TABLE %s)r   rf   )rg   rR   rL   re   ri   r   r   r   
drop_table   s
   rl   c                 C   s   t |  t|rt d| t| || d S t|r%t d t| || d S t|r6t d| t| || d S t|rGt d| t| || d S t	|rXt d| t
| || d S t|rit d| t| || d S td| )Nz-assuming %r is standard DB-API 2.0 connectionz)assuming %r is standard DB-API 2.0 cursorz;assuming %r is an instance of sqlalchemy.engine.base.Enginez<assuming %r is an instance of sqlalchemy.orm.session.Sessionz?assuming %r is an instance of sqlalchemy.engine.base.ConnectionzFassuming %r is a function returning standard DB-API 2.0 cursor objectsz$unsupported database object type: %r)debugr   _execute_dbapi_connectionr   _execute_dbapi_cursorr	   _execute_sqlalchemy_enginer
   _execute_sqlalchemy_sessionr   _execute_sqlalchemy_connectioncallable_execute_dbapi_mkcursr   )ri   rg   re   r   r   r   rf     s8   
rf   c                 C   sN   t d | }t d ||  t d |  |r%t d |  d S d S )Nobtain a cursorexecute SQLclose the cursorcommit transaction)rm   cursorexecuteclosere   )ri   
connectionre   ry   r   r   r   rn   1  s   
rn   c                 C   sd   t d | }t d ||  t d |  |r0t d t|ds'J d|j}|  d S d S )Nru   rv   rw   rx   r|   &could not obtain connection via cursor)rm   rz   r{   hasattrr|   re   )ri   mkcursre   ry   r|   r   r   r   rt   A  s   
rt   c                 C   sF   t d ||  |r!t d t|dsJ d|j}|  d S d S )Nrv   rx   r|   r}   )rm   rz   r~   r|   re   )ri   ry   re   r|   r   r   r   ro   V  s   
ro   c                 C   sB   |r
t d | }t d ||  |rt d |  d S d S )Nzbegin transactionrv   rx   )rm   beginrz   re   )ri   r|   re   transr   r   r   rr   g  s   
rr   c                 C      t | | | d S r   )rr   connect)ri   enginere   r   r   r   rp   w     rp   c                 C   r   r   )rr   r|   )ri   sessionre   r   r   r   rq   {  r   rq   )T)NTN)NTNN)NTTNNrd   )NT)'__doc__r*   loggingpetl.compatr   r   petl.errorsr   petl.util.materialiser   petl.transform.basicsr   petl.io.db_utilsr   r   r	   r
   r   r   	getLogger__name__loggerrm   r]   r9   r;   r5   rK   rY   rc   rj   rl   rf   rn   rt   ro   rr   rp   rq   r   r   r   r   <module>   sT    

E
$
'

'.