U
    4Je=x                     @   s<  d Z ddlZddlZddlZddlZddl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Zddl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!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z' ddl(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4 G dd de3Z5dS )z.Use to transfer an SQLite 3 database to MySQL.    N)	timedelta)Decimal)chain)ceil)isfilerealpath)stdout)CharacterSet)__version__)	errorcode)version)tqdmtrange)adapt_decimaladapt_timedelta check_sqlite_table_xinfo_supportconvert_dateconvert_decimalconvert_timedeltaunicase_compare   )	MYSQL_BLOB_COLUMN_TYPESMYSQL_COLUMN_TYPES"MYSQL_COLUMN_TYPES_WITHOUT_DEFAULTMYSQL_INSERT_METHODMYSQL_TEXT_COLUMN_TYPES!MYSQL_TEXT_COLUMN_TYPES_WITH_JSONcheck_mysql_fulltext_supportcheck_mysql_json_supportsafe_identifier_length)SQLite3toMySQLAttributesSQLite3toMySQLParamsc                	   @   s  e Zd ZU dZedZeje	 e
d< edZeje	 e
d< eeZeje
d< eje ddd	Zed6ejeje	df  eejdddZe	dddZe	dddZe	edddZd
dddZee	ejej e	  dddZ!e	e	dddZ"ed7e	ejeje	e#e$f  e	dd d!Z%d8e	ed
d"d#d$Z&e	d
d%d&d'Z'e	d
d%d(d)Z(d9e	e	ej)e	ej*f e	ej+ej)e	ej*f d+f e#d
d,d-d.Z,e	d
d%d/d0Z-d:e	e#d
d1d2d3Z.d
dd4d5Z/d
S );SQLite3toMySQLz9Use this class to transfer an SQLite 3 database to MySQL.z^[^(]+COLUMN_PATTERNz\(\d+\)$COLUMN_LENGTH_PATTERNMYSQL_CONNECTOR_VERSION)kwargsc              
   K   s*  | ddkrtdn0tt| ds4tdntt| d| _| ddk	rht| d| _ntdt| dpd| _| dpd	| _	| d
pd| _
| dpt | _t| jdkp| dpd| _| dpd| _| dpd| _| dpd| _| j| dpd| jd| _| dp2d| _t| dpFd | _| jtkrbd| _| dppd| _t| dpd | _t| dpd | _t| dpd | _| jtkrd| _| dpd | _| d!pt| j  d | _!| d!s&| j!d"kr&d#| _!| d$p4d| _"| d%pFd| _#| d&pXd| _$t%&t't( t%)d't* t%&t+t, t%)d(t- t%)d)t. t%j/t| jt%j0d*| _1t%j2| j1_3| j14d+t5 | j16 | _7| 8 | _9t:| j9| _;zt<j=j/| j| j| j	| j
| jd,d-}t>|t<j=j?r(|| _@ntAd.| j@B sDtAd.| j@j6d,d/| _Cz| j| j@_DW nN t<j=jEk
r } z*|jFtGjHkr| I  n| jJ|  W 5 d}~X Y nX | K | _LtM| jL| _NtO| jL| _P| j#r| jPstd0W n6 t<j=jEk
r$ } z| jJ|  W 5 d}~X Y nX dS )1zConstructor.Zsqlite_fileNzPlease provide an SQLite filezSQLite file does not existZ
mysql_userzPlease provide a MySQL userZmysql_passwordZ
mysql_host	localhostZ
mysql_porti  Zsqlite_tablesr   Zwithout_foreign_keysFZmysql_ssl_disabledchunkquietlog_file)r*   r)   Zmysql_databasetransferZmysql_integer_typeIGNOREZmysql_truncate_tableszINT(11)Zmysql_string_typezVARCHAR(255)Zmysql_text_typeTEXTZmysql_charsetZutf8mb4Zmysql_collationZutf8mb4_0900_ai_ciZutf8mb4_general_ciZignore_duplicate_keysZuse_fulltextZ
with_rowidZDECIMALZDATEZTIME)Zdetect_typesZunicaseT)userpasswordhostportZssl_disabledZuse_purezUnable to connect to MySQLpreparedz<Your MySQL version does not support InnoDB FULLTEXT indexes!)Qget
ValueErrorr   strFileNotFoundErrorr   Z_sqlite_fileZ_mysql_userZ_mysql_passwordZ_mysql_hostZ_mysql_porttuple_sqlite_tableslen_without_foreign_keysZ_mysql_ssl_disabled_chunk_size_quiet_setup_logger_logger_mysql_databaseupper_mysql_insert_methodr   _mysql_truncate_tables_mysql_integer_type_mysql_string_type_mysql_text_typer   _mysql_charsetr	   Zget_default_collationlower_mysql_collation_ignore_duplicate_keys_use_fulltext_with_rowidsqlite3Zregister_adapterr   r   Zregister_converterr   r   r   r   r   connectZPARSE_DECLTYPESZ_sqliteZRowZrow_factoryZcreate_collationr   cursor_sqlite_cur_get_sqlite_versionZ_sqlite_versionr   _sqlite_table_xinfo_supportmysql	connector
isinstanceZMySQLConnection_mysqlConnectionErrorZis_connected
_mysql_curdatabaseErrorerrnor   ZER_BAD_DB_ERROR_create_databaseerror_get_mysql_versionZ_mysql_versionr   Z_mysql_json_supportr   _mysql_fulltext_support)selfr&   Z_mysql_connectionerr rb   @/tmp/pip-unpacked-wheel-6qcj4cmz/sqlite3_to_mysql/transporter.py__init__7   s    





zSQLite3toMySQL.__init__NFzos.PathLike[t.Any])r*   r)   returnc                 C   sx   t jddd}t | j}|t j |sJt jtd}|| |	| |rtt j
t|dd}|| |	| |S )Nz'%(asctime)s %(levelname)-8s %(message)sz%Y-%m-%d %H:%M:%S)fmtdatefmt)streamw)mode)logging	Formatter	getLogger__name__setLevelDEBUGStreamHandlerr   setFormatter
addHandlerFileHandlerr   )clsr*   r)   	formatterloggerZscreen_handlerZfile_handlerrb   rb   rc   r>      s    



zSQLite3toMySQL._setup_logger)re   c              
   C   s   zD| j d | j  }|r*t|d W S | jd tjdW n: t	tjjfk
r~ } z| jd|  W 5 d }~X Y nX d S )NzSHOW VARIABLES LIKE 'version'r   z(MySQL failed checking for InnoDB versionz,MySQL failed checking for InnoDB version: %s)
rX   executefetchoner6   r?   r]   rS   rT   rZ   
IndexError)r`   rowra   rb   rb   rc   r^      s    
z!SQLite3toMySQL._get_mysql_versionc              
   C   s^   z | j d t| j  d W S  ttjfk
rX } z| jd|  W 5 d }~X Y nX d S )NzSELECT sqlite_version()r   z-SQLite failed checking for InnoDB version: %s)	rP   rx   r6   ry   rz   rM   rZ   r?   r]   r`   ra   rb   rb   rc   rQ      s    z"SQLite3toMySQL._get_sqlite_version)tablere   c                 C   sB   z$| j d| d | j   W dS  tjk
r<   Y dS X d S )NzSELECT rowid FROM "z	" LIMIT 1TF)rP   rx   fetchallrM   ZOperationalError)r`   r}   rb   rb   rc   _sqlite_table_has_rowid   s    
z&SQLite3toMySQL._sqlite_table_has_rowidc              
   C   s   zX| j d| j d| j d| j d | j   | j  | j| j_| jj	dd| _ W n: t
jjk
r } z| jd| j|  W 5 d }~X Y nX d S )Nz0
                CREATE DATABASE IF NOT EXISTS `z(`
                DEFAULT CHARACTER SET z!
                DEFAULT COLLATE z
            Tr2   z$MySQL failed creating databse %s: %s)rX   rx   r@   rG   rI   closerV   commitrY   rO   rS   rT   rZ   r?   r]   r|   rb   rb   rc   r\      s*    


zSQLite3toMySQL._create_database)column_typere   c                 C   s   | j | S N)r#   matchstrip)ru   r   rb   rb   rc   _valid_column_type   s    z!SQLite3toMySQL._valid_column_typec                 C   st  |  }| |}|std|d  }|dkr:| jS |dkrPd| | S |dkr| jtkrh| jS | |}|s|| jS | | j}|r|d  | S |dkrdS |d	krd
| | d S |dkr| jS |dkr8| |}|s| jS | | j}|r8| j	dr&|d  | d S |d  | S |dkrRd
| |d S |dkr`dS |t
krp| jS |S )z@This could be optimized even further, however is seems adequate.zInvalid column_type!r   >   r-   STRINGCLOB>   NATIVE CHARACTERNCHAR	CHARACTERCHAR>   NVARCHARVARYING CHARACTERVARCHARzDOUBLE PRECISIONZDOUBLEzUNSIGNED BIG INTBIGINTz	 UNSIGNED>   INT1INT2>   INTINTEGERZUNSIGNED>   INT64NUMERIC   ZBOOLEANz
TINYINT(1))rA   r   r5   grouprF   _column_type_lengthrE   r   rD   endswithr   )r`   r   Zfull_column_typer   Z	data_typelengthrb   rb   rc   $_translate_type_from_sqlite_to_mysql   sP    







z3SQLite3toMySQL._translate_type_from_sqlite_to_mysql)r   defaultre   c                 C   s.   | j |}|r|dS |r*d| dS dS )Nr   () )r$   searchr   )ru   r   r   suffixrb   rb   rc   r   %  s    
z"SQLite3toMySQL._column_type_length)
table_nametransfer_rowidre   c              
   C   s>  g }dt | d}|r |d7 }| jr<| jd| d n| jd| d | j }ttdd |D d	k}|D ]}t|}t |d
 }	| |d }
d|kr|d d	krqx|d dko|
	do| }|dj
|	|
|d s|d rdnd|rdnd|d r |
tkr |s d|d  ndd7 }|d dkrx|	dd}|
tt ksZ|
	drj| |
d|d< || qx|d}t|dkr|dj
ddd |D d 7 }|r|d!t | d"7 }|d#| j d$| j 7 }z| j| | j  W n> tjjk
r8 } z| jd%t ||  W 5 d }~X Y nX d S )&NzCREATE TABLE IF NOT EXISTS `z` ( z `rowid` BIGINT NOT NULL, zPRAGMA table_xinfo("")PRAGMA table_info("c                 s   s"   | ]}t |d  dkrdV  qdS )pkr   TNdict.0r{   rb   rb   rc   	<genexpr><  s      z/SQLite3toMySQL._create_table.<locals>.<genexpr>r   nametypehiddenr   r   )r   r   z7 `{name}` {type} {notnull} {default} {auto_increment}, notnullzNOT NULLZNULLZAUTO_INCREMENTr   Z
dflt_valuezDEFAULT )r   r   r   auto_incrementr   columnr   )r   r      r   , z, PRIMARY KEY ({columns})c                 s   s   | ]}d j f |V  qdS )`{column}`{length}N)format)r   primary_keyrb   rb   rc   r   g  s     )columnsz, CONSTRAINT `z_rowid` UNIQUE (`rowid`)z! ) ENGINE=InnoDB DEFAULT CHARSET=z	 COLLATE=z"MySQL failed creating table %s: %s)r   rR   rP   rx   r~   r:   r8   r   r   
startswithr   r   r   r   r   appendrstripjoinrG   rI   rX   rV   r   rS   rT   rZ   r?   r]   )r`   r   r   Zprimary_keyssqlZrowsZcompound_primary_keyr{   r   Zmysql_safe_namer   r   r   ra   rb   rb   rc   _create_table.  sv    



zSQLite3toMySQL._create_table)r   re   c                 C   sX   | j d| jt|f t| j  dkrT| jdt| | j dt| d d S )Nz
            SELECT `TABLE_NAME`
            FROM `INFORMATION_SCHEMA`.`TABLES`
            WHERE `TABLE_SCHEMA` = %s
            AND `TABLE_NAME` = %s
            LIMIT 1
            r   zTruncating table %szTRUNCATE TABLE ``)rX   rx   r@   r   r:   r~   r?   info)r`   r   rb   rb   rc   _truncate_tablez  s    
zSQLite3toMySQL._truncate_tablec                    sF  | j d| d i  | j  D ]}t|}|d  |d < q"| j d| d tdd | j  D }|D ]}|d d	krqp| j d
|d  d tdd | j  D }t|d dkrdnd}t fdd|D r(| jr| jrd}d	dd |D }nd	 fdd|D }n|g }	|D ]h}
d} |
d  
 tkrTd}n$| j |
d  }|rx|d}|	dt|
d  d|  q0d	|	}z| j|||||d W qp tjjk
r> } z^|jtjkr,|dkr,| j|t|d dkrdnd|d	 fdd|D |d n W 5 d }~X Y qpX qpd S )Nr   r   r   r   zPRAGMA index_list("c                 s   s   | ]}t |V  qd S r   r   r   rb   rb   rc   r     s     z.SQLite3toMySQL._add_indices.<locals>.<genexpr>originr   zPRAGMA index_info("c                 s   s   | ]}t |V  qd S r   r   r   rb   rb   rc   r     s     uniquer   ZUNIQUEZINDEXc                 3   s"   | ]} |d     tkV  qdS r   N)rA   r   r   
index_infoZtable_columnsrb   rc   r     s   ZFULLTEXT,c                 s   s"   | ]}d t |d  d V  qdS )r   r   Nr   r   rb   rb   rc   r     s    r   c                 3   s<   | ]4}d j t|d  |d   tkr,dnddV  qdS r   r   (255)r   r   Nr   r   rA   r   r   r   rb   rc   r     s   
r   r   r   r   )r   
index_typeindexindex_columnsindex_infosc                 3   s<   | ]4}d j t|d  |d   tkr,dnddV  qdS r   r   r   r   rb   rc   r     s   
)rP   rx   r~   r   r8   intanyrK   r_   r   rA   r   r$   r   r   r   r   
_add_indexrS   rT   rZ   r[   r   ER_BAD_FT_COLUMN)r`   r   r{   r   indicesr   r   r   r   Zcolumn_listr   Zindex_lengthr   ra   rb   r   rc   _add_indices  sp    







"

	zSQLite3toMySQL._add_indicesr   .)r   r   r   r   r   index_iterationre   c           	      C   s  dj t|||dkr t|d nt|d dd d| |d}zV| jdt|d	 d
kr^dndddd |D t| | j| | j	  W n t
jjk
r } z|jtjkr*| js| j||||||d
 d | jdt|d t|t|d |d
  n| jdt|d t| n^|jtjkr`| jdddd |D t|  n(| jdddd |D t||  W 5 d }~X Y nX d S )Nz\
            ALTER TABLE `{table}`
            ADD {index_type} `{name}`({columns})
        r   r   <   )
max_length_)r}   r   r   r   z$Adding %s to column "%s" in table %sr   r   zunique indexr   r   c                 s   s   | ]}t |d  V  qdS r   r   r   rb   rb   rc   r     s     z,SQLite3toMySQL._add_index.<locals>.<genexpr>)r   r   r   r   r   r   zMDuplicate key "%s" in table %s detected! Trying to create new key "%s_%s" ...z(Ignoring duplicate key "%s" in table %s!zVFailed adding FULLTEXT index to column "%s" in table %s. Retrying without FULLTEXT ...c                 s   s   | ]}t |d  V  qdS r   r   r   rb   rb   rc   r     s     z8MySQL failed adding index to column "%s" in table %s: %sc                 s   s   | ]}t |d  V  qdS r   r   r   rb   rb   rc   r      s     )r   r   r?   r   r   r   rX   rx   rV   r   rS   rT   rZ   r[   r   ZER_DUP_KEYNAMErJ   r   warningr   r]   )	r`   r   r   r   r   r   r   r   ra   rb   rb   rc   r     sl    	


zSQLite3toMySQL._add_indexc                 C   sP  | j d| d | j  D ]*}t|}dj|d |d t|t|d t|d t|d |d	  d
kr||d	  nd|d  d
kr|d  ndd}zJ| jdt|t|d t|d t|d  | j	| | j
  W q tjjk
rH } z8| jdt|t|d t|d t|d |  W 5 d }~X Y qX qd S )NzPRAGMA foreign_key_list("r   a  
                ALTER TABLE `{table}`
                ADD CONSTRAINT `{table}_FK_{id}_{seq}`
                FOREIGN KEY (`{column}`)
                REFERENCES `{ref_table}`(`{ref_column}`)
                ON DELETE {on_delete}
                ON UPDATE {on_update}
            idseqfromr}   to	on_deletezSET DEFAULTz	NO ACTION	on_update)r   r   r}   r   Z	ref_tableZ
ref_columnr   r   z-Adding foreign key to %s.%s referencing %s.%sz>MySQL failed adding foreign key to %s.%s referencing %s.%s: %s)rP   rx   r~   r   r   r   rA   r?   r   rX   rV   r   rS   rT   rZ   r]   )r`   r   r{   Zforeign_keyr   ra   rb   rb   rc   _add_foreign_keys&  sJ    








z SQLite3toMySQL._add_foreign_keys)r   total_recordsre   c              	   C   s   | j d k	r\| j dkr\tdtt|| j  | jdD ]&}| j|dd | j| j D  q2n*| j|dd t	| j
 || jdD  | j  d S )Nr   )disablec                 s   s   | ]}t |V  qd S r   r8   r   rb   rb   rc   r   [  s     z6SQLite3toMySQL._transfer_table_data.<locals>.<genexpr>c                 s   s   | ]}t |V  qd S r   r   r   rb   rb   rc   r   `  s   )totalr   )r<   r   r   r   r=   rX   ZexecutemanyrP   Z	fetchmanyr   r~   rV   r   )r`   r   r   r   rb   rb   rc   _transfer_table_dataV  s"    "z#SQLite3toMySQL._transfer_table_datac                 C   s  t | jdkr8| jddt | j d d| j n| jd zBz"| jd | j D ]}t|}| jo| 	|d	 }| j
|d	 |d
 | jr| |d	  | jd|d	  d tt| j d }|dkrF| jd|d	  | jdj|rdnd|d	 d dd | jjD }| j dkrdjt|d	 dt | dj| dt | ddt | djttdd |D  d}nPdj| j dkrdndt|d	 dt | dj| dt | dd}z| j||d  W nB tjjk
rD } z| jd!t|d	 |  W 5 d"}~X Y nX | |d	  | jsb|  |d	  qbW n t!k
r    Y nX W 5 | jd X | jd# d"S )$z@The primary and only method with which we transfer all the data.r   z
                SELECT name FROM sqlite_master
                WHERE type='table'
                AND name NOT LIKE 'sqlite_%'
                AND name IN(z?, z ,z)
                z
                SELECT name FROM sqlite_master
                WHERE type='table'
                AND name NOT LIKE 'sqlite_%'
                zSET FOREIGN_KEY_CHECKS=1zSET FOREIGN_KEY_CHECKS=0r   )r   z'SELECT COUNT(*) AS total_records FROM ""r   zTransferring table %sz$SELECT {rowid} * FROM "{table_name}"zrowid as "rowid",r   )Zrowidr   c                 S   s   g | ]}t |d  qS )r   r   r   r   rb   rb   rc   
<listcomp>  s    z+SQLite3toMySQL.transfer.<locals>.<listcomp>ZUPDATEz
                            INSERT
                            INTO `{table}` ({fields})
                            VALUES ({placeholders}) AS `__new__`
                            ON DUPLICATE KEY UPDATE {field_updates}
                        z`{}`, z%s, z`{}`=`__new__`.`{}`, c                 s   s   | ]}||fV  qd S r   rb   r   rb   rb   rc   r     s     z*SQLite3toMySQL.transfer.<locals>.<genexpr>)r}   fieldsplaceholdersZfield_updatesz
                            INSERT {ignore}
                            INTO `{table}` ({fields})
                            VALUES ({placeholders})
                        r,   )ignorer}   r   r   )r   r   z6MySQL transfer failed inserting data into table %s: %sNzDone!)"r:   r9   rP   rx   r   rX   r~   r   rL   r   r   rC   r   r   ry   r?   r   r   descriptionrB   rA   r   listr   from_iterabler   rS   rT   rZ   r]   r   r;   r   	Exception)r`   r{   r}   r   r   r   r   ra   rb   rb   rc   r+   k  s    




zSQLite3toMySQL.transfer)NF)N)F)r   )r   )0rn   
__module____qualname____doc__recompiler#   tPatternr6   __annotations__r$   r   parsemysql_connector_version_stringr%   VersiontxZUnpackr!   rd   classmethodOptionalUnionboolrk   Loggerr>   r^   rQ   r   r\   Matchr   r   r   floatr   r   r   r   DictAnyTupler   r   r   r+   rb   rb   rb   rc   r"   /   sL   
r    ,(L\ H0r"   )6r   rk   osr   rM   typingr   datetimer   decimalr   	itertoolsr   mathr   os.pathr   r   sysr   Zmysql.connectorrS   Ztyping_extensionsr   r	   r
   r   r   	packagingr   r   r   Zsqlite3_to_mysql.sqlite_utilsr   r   r   r   r   r   r   Zmysql_utilsr   r   r   r   r   r   r   r   r   typesr    r!   r"   rb   rb   rb   rc   <module>   s,   $
,