U
    a±d´ù  ã                   @   sH  d Z ddlZddlZddlZddl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 ddl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dddZe e!ffdd„Z"dd„ 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(e(e(e(e&e'e%dœZ)G dd „ d eƒZ*dS )!ae  
sqldiff.py - Prints the (approximated) difference between models and database

TODO:
 - better support for relations
 - better support for constraints (mainly postgresql?)
 - support for table spaces with postgresql
 - when a table is not managed (meta.managed==False) then only do a one-way
   sqldiff ? show differences from db->table but not the other way around since
   it's not managed.

KNOWN ISSUES:
 - MySQL has by far the most problems with introspection. Please be
   carefull when using MySQL with sqldiff.
   - Booleans are reported back as Integers, so there's no way to know if
     there was a real change.
   - Varchar sizes are reported back without unicode support so their size
     may change in comparison to the real length of the varchar.
   - Some of the 'fixes' to counter these problems might create false
     positives or false negatives.
é    N)ÚDictÚUnionÚCallableÚOptional)Úapps)ÚBaseCommandÚCommandError)ÚOutputWrapper)Úno_style)Ú
connectionÚtransactionÚmodels)ÚUniqueConstraint)Ú	AutoFieldÚIntegerField)Únormalize_together)ÚsignalcommandÚ_orderT)Únullc                 C   st   t | ƒ}t| ƒ} d}|t| ƒk rlt| | |ƒrb| | sL|  |¡ |d8 }qbq | | | ||d …< q |d7 }q|| ƒS )Nr   é   )ÚtypeÚlistÚlenÚ
isinstanceÚpop)ÚlstZltypesZltypeÚi© r   úQ/tmp/pip-unpacked-wheel-portabvm/django_extensions/management/commands/sqldiff.pyÚflatten*   s    

r   c                 C   sX   g }| j r(| jD ]}| t|jƒ¡ qn,| jD ]$}|jtd}|d krHq.| |¡ q.|S ©N©r   )	ÚproxyÚparentsÚextendÚall_local_fieldsÚ_metaZlocal_fieldsÚdb_typer   Úappend)ÚmetaZ
all_fieldsÚparentÚfZcol_typer   r   r   r%   :   s    

r%   c                   @   sð  e Zd Zi ZdgZdddddddd	d
ddddddgZddddddddddddd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)d"„ Zd*d"„ Zd+d"„ Zd,d"„ Zd-d"„ Zd.d"„ Zd/d"„ Zd0Zd0Zd1Zd2d3„ Zd4d5„ Zd6d7„ Zd8d9„ Zd:d;„ Zd<d=„ Zd>d?„ Zd@dA„ ZdBdC„ Z dDdE„ Z!dtdFdG„Z"dudHdI„Z#dJdK„ Z$dLdM„ Z%dNdO„ Z&dPdQ„ Z'dRdS„ Z(dTdU„ Z)dVdW„ Z*dvdXdY„Z+dZd[„ Z,d\d]„ Z-d^d_„ Z.d`da„ Z/dbdc„ Z0dwddde„Z1dxdfdg„Z2dhdi„ Z3djdk„ Z4dldm„ Z5e6ƒ fdndo„Z7dpdq„ Z8drds„ Z9d1S )yÚSQLDiffZdjango_migrationsÚerrorÚcommentútable-missing-in-dbútable-missing-in-modelúfield-missing-in-dbúfield-missing-in-modelúfkey-missing-in-dbúfkey-missing-in-modelúindex-missing-in-dbúindex-missing-in-modelúunique-missing-in-dbúunique-missing-in-modelúfield-type-differúfield-parameter-differúnotnull-differzerror: %(0)szcomment: %(0)sz!table '%(0)s' missing in databaseztable '%(0)s' missing in modelsz6field '%(1)s' defined in model but missing in databasez6field '%(1)s' defined in database but missing in modelzBfield '%(1)s' FOREIGN KEY defined in model but missing in databasezBfield '%(1)s' FOREIGN KEY defined in database but missing in modelzJfield '%(1)s' INDEX named '%(2)s' defined in model but missing in databasezCfield '%(1)s' INDEX defined in database schema but missing in modelzKfield '%(1)s' UNIQUE named '%(2)s' defined in model but missing in databasezDfield '%(1)s' UNIQUE defined in database schema but missing in modelz9field '%(1)s' not of same type: db='%(3)s', model='%(2)s'z:field '%(1)s' parameters differ: db='%(3)s', model='%(2)s'z?field '%(1)s' null constraint should be '%(2)s' in the database©r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   c                    sZ   dˆ   d¡ˆ  ||d ƒ¡ˆ   d¡ˆ  ||d ƒ¡d ‡ fdd„t|d	d … ƒD ƒ¡f S )
Nú%s %s
	%s %s %s;úALTER TABLEr   ú
ADD COLUMNr   ú c                 3   s.   | ]&\}}|d krˆ   |¡nˆ  |¡V  qdS ©r   N©ÚSQL_COLTYPEÚSQL_KEYWORD©Ú.0r   Úa©Ústyler   r   Ú	<genexpr>w   s     ú#SQLDiff.<lambda>.<locals>.<genexpr>é   )rD   Ú	SQL_TABLEÚ	SQL_FIELDÚjoinÚ	enumerate©ÚselfrI   ÚqnÚargsr   rH   r   Ú<lambda>r   s   "ûzSQLDiff.<lambda>c              	   C   s8   d|  d¡| ||d ƒ¡|  d¡| ||d ƒ¡f S )Nz%s %s
	%s %s;r>   r   zDROP COLUMNr   ©rD   rM   rN   rQ   r   r   r   rU   y   s
   üc                    sŠ   dˆ   d¡ˆ  ||d ƒ¡ˆ   d¡ˆ  ||d ƒ¡d ‡ fdd„t|d	d … ƒD ƒ¡ˆ   d
¡ˆ  ||d ƒ¡ˆ  ||d ƒ¡tj ¡ f	 S )Nz%s %s
	%s %s %s %s %s (%s)%s;r>   r   r?   r   r@   c                 3   s.   | ]&\}}|d krˆ   |¡nˆ  |¡V  qdS rA   rB   rE   rH   r   r   rJ   „   s     rK   é   Z
REFERENCESrL   é   )rD   rM   rN   rO   rP   r   ÚopsZdeferrable_sqlrQ   r   rH   r   rU      s   "÷c                    sd   d|  d¡| ˆ |d ƒ¡|  d¡| ˆ |d ƒ¡| d ‡ fdd„|d	 D ƒ¡¡|  |d
 ¡f S )Nz%s %s
	%s %s (%s%s);zCREATE INDEXrL   ÚONr   ú, c                 3   s   | ]}ˆ |ƒV  qd S ©Nr   ©rF   Úe©rS   r   r   rJ      s     rK   r   rX   ©rD   rM   rN   rO   rQ   r   r_   r   rU   Š   s     úc                 C   s    d|  d¡| ||d ƒ¡f S )Nz%s %s;z
DROP INDEXr   ©rD   rM   rQ   r   r   r   rU   ’   s   þc                    s`   d|  d¡| ˆ |d ƒ¡|  d¡| ˆ |d ƒ¡|  d¡| d ‡ fdd	„|d
 D ƒ¡¡f S )Nz%s %s
	%s %s %s (%s);r>   r   zADD CONSTRAINTrL   ZUNIQUEr[   c                 3   s   | ]}ˆ |ƒV  qd S r\   r   r]   r_   r   r   rJ   œ   s     rK   r   r`   rQ   r   r_   r   rU   –   s    úc              
   C   s@   d|  d¡| ||d ƒ¡|  d¡|  d¡| ||d ƒ¡f S )Nr=   r>   r   ÚDROPZ
CONSTRAINTr   ra   rQ   r   r   r   rU   ž   s   ûc              	   C   sD   d|  d¡| ||d ƒ¡|  d¡| ||d ƒ¡| |d ¡f S ©Nr=   r>   r   ÚMODIFYr   rL   ©rD   rM   rN   rC   rQ   r   r   r   rU   ¥   s   ûc              	   C   sD   d|  d¡| ||d ƒ¡|  d¡| ||d ƒ¡| |d ¡f S rc   re   rQ   r   r   r   rU   ¬   s   ûc              	   C   sL   d|  d¡| ||d ƒ¡|  d¡| ||d ƒ¡|  |d ¡|  d¡f S )Nú%s %s
	%s %s %s %s;r>   r   rd   r   rL   úNOT NULLrV   rQ   r   r   r   rU   ³   s   úc                 C   s   |  d| |d ¡ ¡S )Nz-- Error: %sr   )ÚNOTICEÚERRORrQ   r   r   r   rU   »   ó    c                 C   s   |  d| |d ¡ ¡S )Nz-- Comment: %sr   )rh   rM   rQ   r   r   r   rU   ¼   rj   c                 C   s   |  d|d  ¡S )Nz-- Table missing: %sr   ©rh   rQ   r   r   r   rU   ½   rj   c                 C   s   |  d|d  ¡S )Nz-- Model missing for table: %sr   rk   rQ   r   r   r   rU   ¾   rj   FNc                 C   sš   d | _ || _|| _|d | _|| _|| _tj| _g | _i | _	t
ƒ | _i | _t
ƒ | _| j| j| j| j| j| j| j| j| j| j| j| j| j| j| jdœ| _d S )NÚdense_outputr<   )Úhas_differencesÚ
app_modelsÚoptionsÚdenseÚstdoutÚstderrr   ÚintrospectionÚdifferencesÚunknown_db_fieldsÚsetÚnew_db_fieldsr   ÚunsignedÚ	SQL_ERRORÚSQL_COMMENTÚSQL_TABLE_MISSING_IN_DBÚSQL_TABLE_MISSING_IN_MODELÚSQL_FIELD_MISSING_IN_DBÚSQL_FIELD_MISSING_IN_MODELÚSQL_FKEY_MISSING_IN_DBÚSQL_INDEX_MISSING_IN_DBÚSQL_INDEX_MISSING_IN_MODELÚSQL_UNIQUE_MISSING_IN_DBÚSQL_UNIQUE_MISSING_IN_MODELÚSQL_FIELD_TYPE_DIFFERÚSQL_FIELD_PARAMETER_DIFFERÚSQL_NOTNULL_DIFFERÚDIFF_SQL)rR   rn   ro   rq   rr   r   r   r   Ú__init__Ä   s8    
ñzSQLDiff.__init__c                 C   sZ   t  ¡ | _| jj| jd d| _dd„ | j | j¡D ƒ| _| jrH|  	¡  | j
rV|  ¡  d S )NÚonly_existing)r‰   c                 S   s   g | ]
}|j ‘qS r   ©Úname)rF   Ú
table_infor   r   r   Ú
<listcomp>ê   s     z SQLDiff.load.<locals>.<listcomp>)r   Úcursorrs   Zdjango_table_namesro   Údjango_tablesZget_table_listÚ	db_tablesÚcan_detect_notnull_differÚ	load_nullÚcan_detect_unsigned_differÚload_unsigned©rR   r   r   r   Úloadæ   s    
zSQLDiff.loadc                 C   s   t dƒ‚d S )Nzcload_null functions must be implemented if diff backend has 'can_detect_notnull_differ' set to True©ÚNotImplementedErrorr•   r   r   r   r’   ò   s    zSQLDiff.load_nullc                 C   s   t dƒ‚d S )Nzgload_unsigned function must be implemented if diff backend has 'can_detect_unsigned_differ' set to Truer—   r•   r   r   r   r”   õ   s    zSQLDiff.load_unsignedc                 C   s   | j  ||g f¡ d S r\   )rt   r(   )rR   Ú	app_labelÚ
model_namer   r   r   Úadd_app_model_markerø   s    zSQLDiff.add_app_model_markerc                 G   s.   || j kstdƒ‚| jd d  ||f¡ d S )NzUnknown difference typeéÿÿÿÿ)Ú
DIFF_TYPESÚAssertionErrorrt   r(   )rR   Ú	diff_typerT   r   r   r   Úadd_differenceû   s    zSQLDiff.add_differencec                 C   s   | j S r\   )ÚDATA_TYPES_REVERSE_OVERRIDEr•   r   r   r   Úget_data_types_reverse_overrideÿ   s    z'SQLDiff.get_data_types_reverse_overridec                 C   s   |S r\   r   ©rR   Úfield_namesr   r   r   Úformat_field_names  s    zSQLDiff.format_field_namesc           	      C   sp   t  ¡ }| ||¡ dd„ |jD ƒ}|  |¡}g }| ¡ D ]0}g }t||ƒD ]}| |¡ qL| t|ƒ¡ q:|S )z°
        Execute query and return a dict

        sql_to_dict(query, param) -> list of dicts

        code from snippet at http://www.djangosnippets.org/snippets/1383/
        c                 S   s   g | ]}|d  ‘qS ©r   r   )rF   r‹   r   r   r   r     s     z'SQLDiff.sql_to_dict.<locals>.<listcomp>)	r   rŽ   ÚexecuteÚdescriptionr¥   ÚfetchallÚzipr(   Údict)	rR   ÚqueryÚparamrŽ   Ú
fieldnamesÚresultÚrowZrowsetÚfieldr   r   r   Úsql_to_dict  s    
zSQLDiff.sql_to_dictc                 C   s   |j tdS r    )r'   r   )rR   r±   r   r   r   Úget_field_model_type  s    zSQLDiff.get_field_model_typec                 C   s   i S r\   r   )rR   Zcurrent_kwargsr¨   r±   Ú
table_nameÚreverse_typer   r   r   Úget_field_db_type_kwargs  s    z SQLDiff.get_field_db_type_kwargsc              	   C   sl  |d }|   ¡ }||kr"|| }n†z| j ||¡}W nr tk
r¦   |  |¡}|s¢| jd d d… |d d… f}|| jkrœd| j|< |  dd|d |f ¡ Y d S Y nX t|ƒr¶|ƒ }i }t	|t
ƒrÚ| |d ¡ |d }|d	krú|rút|d
d ƒdkrúd}t	|tƒr| |d ¡ |d }|dkr<|d r<|d |d< |dkrv|d |d< |d rjt|d ƒpp|d |d< |d ršd|d< |dkršd|d< |r¶t|ddƒr¶d|d< |dkrò|d }	| j ||	¡\}}
|
rê| |
¡ d| }|  |||||¡}| |¡ |  |¡}|f |Žjtd}|j}|s:d}|||jf| jkrh| j|krhd || jf }|S )!Nr   rœ   rL   r.   z)Unknown database type for field '%s' (%s)r   Úkwargsr‹   i2B  Z	geom_typeZPOINTz.django.contrib.gis.db.models.fields.PointFieldÚ	CharFieldrX   Ú
max_lengthÚDecimalFieldrW   Z
max_digitsé   Zdecimal_placesé   TZblank)Z	TextFieldr¸   r   Z	geographyFZGeometryFieldz&django.contrib.gis.db.models.fields.%sr!   Úpublicú%s %s)r¢   rs   Zget_field_typeÚKeyErrorÚget_field_db_type_lookuprt   ru   r    Úcallabler   r«   ÚupdateÚgetattrÚtupleÚabsZget_geometry_typer¶   Úget_field_classr'   r   Údb_tablespaceÚcolumnrx   Úunsigned_suffix)rR   r¨   r±   r´   Ú	type_coder¡   rµ   Úkeyr·   Zgeo_colZ
geo_paramsÚextra_kwargsZfield_classZfield_db_typeÚ
tablespacer   r   r   Úget_field_db_type   sh    





$





 zSQLDiff.get_field_db_typec                 C   s   d S r\   r   )rR   rÊ   r   r   r   rÀ   j  s    z SQLDiff.get_field_db_type_lookupc                 C   s6   d|kr,|  dd¡\}}t |¡}t||ƒS tt|ƒS )NÚ.r   )ÚrsplitÚ	importlibÚimport_modulerÃ   r   )rR   Z
class_pathÚmodule_pathÚpackage_nameÚmoduler   r   r   rÆ   m  s
    

zSQLDiff.get_field_classc                 C   s2   |j }|dkrd}|jp|j}| j |||fd¡S )NÚ r½   Zfixme)rÇ   Ú	db_columnÚattnamer   Úget)rR   r±   r´   rÍ   rØ   r   r   r   Úget_field_db_nullableu  s
    zSQLDiff.get_field_db_nullablec                 C   s,   |r(|dkr(|  d¡d   d¡d  ¡ S |S )Nzdouble precisionr@   r   ú()ÚsplitÚlower)rR   Ú
field_typer   r   r   Ústrip_parameters|  s    zSQLDiff.strip_parametersc                 C   s2   t t|jƒƒ}|jD ]}| |j¡ q|  ||¡S r\   )r   r   Úindex_togetherÚindexesr(   ÚfieldsÚexpand_together)rR   r)   Zindexes_normalizedÚidxr   r   r   Úget_index_together  s    
zSQLDiff.get_index_togetherc                 C   s<   t t|jƒƒ}|jD ]}t|tƒr| |j¡ q|  ||¡S r\   )	r   r   Úunique_togetherÚconstraintsr   r   r(   râ   rã   )rR   r)   Zunique_normalizedÚ
constraintr   r   r   Úget_unique_together‰  s
    

zSQLDiff.get_unique_togetherc                    s2   g }t |ƒD ] }| t‡ fdd„|D ƒƒ¡ q|S )Nc                 3   s   | ]}ˆ   |¡jV  qd S r\   )Ú	get_fieldrØ   ©rF   r±   ©r)   r   r   rJ   –  s     z*SQLDiff.expand_together.<locals>.<genexpr>)r   r(   rÄ   )rR   Ztogetherr)   Znew_togetherrâ   r   rì   r   rã   ’  s    ÿzSQLDiff.expand_togetherc                    sh  t  t ¡}t|ƒD ]â}|r&|j|kr&q|jr|jr|jp<|j‰ | ˆ i ¡ d¡}|sr|rrt‡ fdd„| 	¡ D ƒƒ}ˆ |kr€|r€q| 
|ˆ g¡}	|  d|ˆ g|	d ¡ |jt d}
|
 d¡rÒ|  d|ˆ g|	d	 d
¡ |
 d¡r|  d|ˆ g|	d	 d¡ q|  |¡}tdd„ | ¡ D ƒƒ}|D ]H}||kr,q|r@||kr@q| 
||¡}	|  d|||	d ¡ qd S )NÚuniquec                 3   s(   | ] \}}ˆ g|d  kr|d V  qdS ©Úcolumnsrí   Nr   ©rF   Úcontraint_namerè   ©rØ   r   r   rJ   £  s      z4SQLDiff.find_unique_missing_in_db.<locals>.<genexpr>r7   Ú_uniqr!   Úvarcharr5   Ú_likeú varchar_pattern_opsÚtextú text_pattern_opsc                 S   s$   g | ]}|d  r|d s|d ‘qS )rí   Úindexrï   r   ©rF   Úvr   r   r   r   ±  s       z5SQLDiff.find_unique_missing_in_db.<locals>.<listcomp>©r   ÚSchemaEditorClassr%   rØ   rí   Zmanagedr×   rÙ   ÚanyÚitemsÚ_create_index_namer    r'   Ú
startswithré   r   Úvalues©rR   r)   Útable_indexesÚtable_constraintsr´   Ú	skip_listÚschema_editorr±   Zdb_field_uniqueÚ
index_namer'   ræ   Údb_unique_columnsÚunique_columnsr   rò   r   Úfind_unique_missing_in_dbš  s6    




z!SQLDiff.find_unique_missing_in_dbc                 C   sœ   t dd„ t|ƒD ƒƒ}|  |¡}| ¡ D ]n\}}|d s:q(|d rDq(|d }	t|	ƒdkrz| |	d ¡}
|
d krpqˆ|
jrˆq(nt|	ƒ|krˆq(|  d||¡ q(d S )	Nc                 S   s   g | ]}|j |f‘qS r   ©rÈ   rë   r   r   r   r   ¿  s     z8SQLDiff.find_unique_missing_in_model.<locals>.<listcomp>rí   rù   rï   r   r   r8   )	r«   r%   ré   rÿ   r   rÙ   rí   rÄ   r    )rR   r)   r  r  r´   râ   ræ   Úconstraint_namerè   rï   r±   r   r   r   Úfind_unique_missing_in_model¾  s"    
z$SQLDiff.find_unique_missing_in_modelc                 C   s.  t  t ¡}t|ƒD ]}|jr|jp&|j}||kr| ||g¡}|  d||g|d¡ |jt d}	|	 	d¡r€|  d||g|d d¡ |	 	d¡r|  d||g|d d¡ q|  
|¡}
td	d
„ | ¡ D ƒƒ}|
D ]0}||krÖqÈ| ||¡}|  d|||d d¡ qÈ|jD ](}|j|kr |  d||j|jd¡ q d S )Nr5   rÖ   r!   rô   rõ   rö   r÷   rø   c                 S   s$   g | ]}|d  r|d s|d ‘qS )rù   rí   rï   r   rú   r   r   r   r   å  s       z4SQLDiff.find_index_missing_in_db.<locals>.<listcomp>Z_idx)r   rý   r%   Údb_indexr×   rØ   r   r    r'   r  rå   r   r  rá   r‹   râ   )rR   r)   r  r  r´   r  r±   rØ   r  r'   rà   Zdb_index_togetherrï   rù   r   r   r   Úfind_index_missing_in_dbÖ  s,    




z SQLDiff.find_index_missing_in_dbc                 C   sl  t dd„ t|ƒD ƒƒ}dd„ |jD ƒ}|  |¡}| ¡ D ],\}}	||krLq8|	d r^|	d s^q8|	d }
| |
d ¡}|	d r„|	d sŒ|d krŽnÊt|
ƒdkr>|	d	 r¬|jr¬q8|	d
 rÈt|t	j
ƒrÈ|jrÈq8|	d rØ|jrØq8|	d rþ|	d dkrþ|	 d¡rþ|jrþq8|	d r|jrq8|	d r,|jtdr,q8t|ddƒrXq8n|	d rXt|
ƒ|krXq8|  d||¡ q8d S )Nc                 S   s   g | ]}|j |f‘qS r   r  rë   r   r   r   r   ñ  s     z7SQLDiff.find_index_missing_in_model.<locals>.<listcomp>c                 S   s   g | ]
}|j ‘qS r   rŠ   ©rF   rä   r   r   r   r   ò  s     rí   rù   rï   r   r   Úprimary_keyÚforeign_keyr   rä   ÚordersÚcheckr!   Úspatial_indexFr6   )r«   r%   rá   rå   rÿ   rÙ   r   r  r   r   Ú
ForeignKeyÚdb_constraintrí   r  Údb_checkr   rÃ   rÄ   r    )rR   r)   r  r  r´   râ   Úmeta_index_namesrà   r  rè   rï   r±   r   r   r   Úfind_index_missing_in_modelð  s<    
$z#SQLDiff.find_index_missing_in_modelc                 C   s,   |D ]"}|d |kr|   d||d ¡ qd S )Nr   r2   )r    )rR   ÚfieldmapÚtable_descriptionr´   r°   r   r   r   Úfind_field_missing_in_model  s    z#SQLDiff.find_field_missing_in_modelc           	      C   sØ   dd„ |D ƒ}|  ¡ D ]¼\}}||krg }|jr^| |jjjj|jjj |jj¡jg¡ d}nd}| 	|j
td¡ | jd rž| ¡ rž| 	d| | ¡ ¡ ¡ |js®| 	d¡ | j|||f|žŽ  | j ||f¡ qd S )	Nc                 S   s   g | ]}|d  ‘qS r¦   r   ©rF   r°   r   r   r   r     s     z4SQLDiff.find_field_missing_in_db.<locals>.<listcomp>r3   r1   r!   Úinclude_defaultsz
DEFAULT %srg   )rÿ   Zremote_fieldr$   Úmodelr&   Údb_tablerê   Ú
field_namerÈ   r(   r'   r   ro   Zhas_defaultZget_prep_valueÚget_defaultr   r    rw   Úadd)	rR   r  r  r´   Ú	db_fieldsr#  r±   Zfield_outputÚopr   r   r   Úfind_field_missing_in_db  s    (
z SQLDiff.find_field_missing_in_dbc           
      C   s   t dd„ |D ƒƒ}t|ƒD ]p}|j|kr*q||j }|  |¡}|  |||¡}	|rb|||||	ƒ\}}	|  |	¡|  |¡ks|  d||j||	¡ qd S )Nc                 S   s   g | ]}|d  |f‘qS r¦   r   r  r   r   r   r   1  s     z2SQLDiff.find_field_type_differ.<locals>.<listcomp>r9   )r«   r%   r‹   r³   rÎ   rß   r    )
rR   r)   r  r´   Úfuncr&  r±   r¨   Ú
model_typer'   r   r   r   Úfind_field_type_differ0  s    


zSQLDiff.find_field_type_differc                 C   sä   t dd„ |D ƒƒ}t|ƒD ]Ä}|j|kr*q||j }|  |¡}|  |||¡}	|  |¡|  |	¡ksbq|rx|||||	ƒ\}}	|jtdd }
d|	kr¶|	 dd¡\}	}| 	¡  
d¡ d¡}nd }||	krÊ|
|ks|  d	||j||	¡ qd S )
Nc                 S   s   g | ]}|d  |f‘qS r¦   r   r  r   r   r   r   B  s     z7SQLDiff.find_field_parameter_differ.<locals>.<listcomp>r!   r  z CHECKr   rÛ   ú)r:   )r«   r%   r‹   r³   rÎ   rß   Zdb_parametersr   rÜ   ÚstripÚlstripÚrstripr    )rR   r)   r  r´   r)  r&  r±   r¨   r*  r'   Zmodel_checkr  r   r   r   Úfind_field_parameter_differA  s$    


z#SQLDiff.find_field_parameter_differc                 C   sl   | j s
d S t|ƒD ]T}|jp |j}||f| jkr2q|  ||¡}|j|kr|jrRdpTd}|  d|||¡ qd S )Nrb   ZSETr;   )r‘   r%   r×   rØ   rw   rÚ   r   r    )rR   r)   r  r´   r±   rØ   r   Úactionr   r   r   Úfind_field_notnull_differ\  s    
z!SQLDiff.find_field_notnull_differc                 C   s   i S r\   r   )rR   rŽ   r´   rs   r   r   r   Úget_constraintsi  s    zSQLDiff.get_constraintsc                 C   sN  | j d rB|  d d ¡ | jD ]$}|| jkr|| jkr|  d|¡ qd }| jD ]ä}|j}|j}|j	}| j d sv|j
rvqL||krŒ|  ||j¡ || jkr¤|  d|¡ qLt| jdƒrÂ| j | j|¡}n|  | j|| j¡}tdd„ t|ƒD ƒƒ}|jrøt|d< z| j | j|¡}	W nL tk
rX }
 z,|  d	d
t|
ƒ ¡  ¡ t ¡  W Y ¢qLW 5 d }
~
X Y nX i }| ¡ D ]D\}}|d }t|ƒdkrf|d |d | d¡|dœ||d < qf|  ||||¡ |  ||||¡ |  ||	|¡ |   ||	|¡ |  !||||¡ |  "||||¡ |  #||	|¡ |  $||	|¡ |  %||	|¡ qLt&dd„ | j'D ƒƒ| _(d S )NÚall_applicationsr0   Úinclude_proxy_modelsr/   r3  c                 S   s   g | ]}|j p| ¡ |f‘qS r   )r×   Zget_attnamerë   r   r   r   r   Š  s     z,SQLDiff.find_differences.<locals>.<listcomp>r   r-   zunable to introspect table: %srï   r   r  rí   r   )r  rí   r   rñ   r   c                 S   s   g | ]\}}}t |ƒ‘qS r   )r   )rF   Z
_app_labelZ_model_nameÚdiffsr   r   r   r   »  s     ))ro   r›   r   r   ÚIGNORE_MISSING_TABLESr    rn   r&   r"  r™   r"   Ú__name__Úhasattrrs   r3  rŽ   r«   r%   Zorder_with_respect_toÚORDERING_FIELDZget_table_descriptionÚ	ExceptionÚstrr-  r   Úrollbackrÿ   r   rÙ   r  r  r  r(  r  r  r+  r0  r2  Úmaxrt   rm   )rR   ÚtableÚcur_app_labelZ	app_modelr)   r´   r™   r  r  r  r^   r  rñ   Údctrï   r   r   r   Úfind_differencesl  s`    


ü	zSQLDiff.find_differencesc                 C   s$   | j d r|  |¡ n
|  |¡ dS )z Print differences to stdout ÚsqlN)ro   Úprint_diff_sqlÚprint_diff_text)rR   rI   r   r   r   Ú
print_diff½  s    
zSQLDiff.print_diffc           
         sŒ  | j s$| j ˆ  d¡¡ | j d¡ | jsH| j ˆ  d¡¡ | j d¡ d }| jD ]2\}}}|sdqR| jsš|rš||krš| j dˆ  d¡ˆ  |¡f ¡ |}| jsÄ|rÄ| j dˆ  d¡ˆ  |¡f ¡ |D ]¼}|\}}| j| t	‡ fdd„t
|ƒD ƒƒ }	d	 ‡ fd
d„t
|	 d	¡ƒD ƒ¡}	| js>| j dˆ  d¡|	f ¡ qÈ|rx| j dˆ  d¡ˆ  |¡ˆ  d¡ˆ  |¡|	f ¡ qÈ| j |	¡ qÈqRd S )NzE# Detecting notnull changes not implemented for this database backendrÖ   zF# Detecting unsigned changes not implemented for this database backendr¾   z+ Application:z|-+ Differences for model:c                 3   s<   | ]4\}}t |ƒˆ  t|ttfƒr,d  |¡n|¡fV  qdS )r[   N)r<  rM   r   r   rÄ   rO   ©rF   r   r^   rH   r   r   rJ   Ø  s   ÿz*SQLDiff.print_diff_text.<locals>.<genexpr>ú'c                 3   s,   | ]$\}}|d  dkr ˆ   |¡p"|V  qdS )rL   r   N)ri   rG  rH   r   r   rJ   Ü  s     z|--+z%s %s %s %s %sZAppZModel)r‘   rq   Úwriterh   r“   rt   rp   rM   Ú
DIFF_TEXTSr«   rP   rO   rÜ   )
rR   rI   r@  r™   rš   r6  ÚdiffrŸ   Ú	diff_argsr÷   r   rH   r   rE  Ä  s4     
 þ
"4zSQLDiff.print_diff_textc              	   C   s(  | j s$| j | d¡¡ | j d¡ d }tjj}| jsP| jsN| j | 	d¡¡ nÔ| j | 	d¡¡ | j
D ]¨\}}}|sxqh| js¦||kr¦| j | d| |¡ ¡¡ |}| jsÌ|rÌ| j | d| |¡ ¡¡ |D ]>}|\}}	| j| |||	ƒ}
| jr|
 dd¡}
| j |
¡ qÐqh| j | 	d	¡¡ d S )
NzF-- Detecting notnull changes not implemented for this database backendrÖ   z-- No differenceszBEGIN;z-- Application: %sz-- Model: %sz
	r@   zCOMMIT;)r‘   rq   rI  rh   r   rY   Z
quote_namerm   rp   rD   rt   rM   r‡   Úreplace)rR   rI   r@  rS   r™   rš   r6  rK  rŸ   rL  r÷   r   r   r   rD  å  s0    
zSQLDiff.print_diff_sql)NNN)NN)N)N)N):r8  Ú
__module__Ú__qualname__r¡   r7  r   rJ  r}   r~   r   r€   r   r‚   rƒ   r„   r…   r†   ry   rz   r{   r|   r‘   r“   rÉ   rˆ   r–   r’   r”   r›   r    r¢   r¥   r²   r³   r¶   rÎ   rÀ   rÆ   rÚ   rß   rå   ré   rã   r  r  r  r  r  r(  r+  r0  r2  r3  rB  r
   rF  rE  rD  r   r   r   r   r,   H   sª   ÿññ"

J	
$(

Q!r,   c                   @   s$   e Zd ZdZdZdd„ Zdd„ ZdS )ÚGenericSQLDiffFc                 C   s   d S r\   r   r•   r   r   r   r’     s    zGenericSQLDiff.load_nullc                 C   s   d S r\   r   r•   r   r   r   r”   	  s    zGenericSQLDiff.load_unsignedN)r8  rN  rO  r‘   r“   r’   r”   r   r   r   r   rP    s   rP  c                       sh   e Zd ZdZdZdZ‡ fdd„Zdd„ Zdd„ Zd	d
„ Z	dd„ Z
d‡ fdd„	Zdd„ Zddd„Z‡  ZS )Ú	MySQLDiffTZUNSIGNEDc                    s   t ƒ  ¡  tƒ | _|  ¡  d S r\   )Úsuperr–   rv   Úauto_incrementÚload_auto_incrementr•   ©Ú	__class__r   r   r–     s    
zMySQLDiff.loadc                 C   s   dd„ |D ƒS )Nc                 S   s   g | ]}|  ¡ ‘qS r   )rÝ   )rF   r+   r   r   r   r     s     z0MySQLDiff.format_field_names.<locals>.<listcomp>r   r£   r   r   r   r¥     s    zMySQLDiff.format_field_namesc                 C   sL   d}| j D ]<}|  d|g¡}|D ]$}|||d f}|d dk| j|< q q
d S )Nr½   z¸
                SELECT column_name, is_nullable
                FROM information_schema.columns
                WHERE table_schema = DATABASE()
                    AND table_name = %sÚcolumn_nameZis_nullableZYES©r   r²   r   ©rR   rÍ   r´   r¯   rŒ   rË   r   r   r   r’     s    
üzMySQLDiff.load_nullc                 C   sF   d}| j D ]6}|  d|g¡}|D ]}|||d f}| j |¡ q q
d S )Nr½   zá
                SELECT column_name
                FROM information_schema.columns
                WHERE table_schema = DATABASE()
                    AND table_name = %s
                    AND column_type LIKE '%%unsigned'rW  )r   r²   rx   r%  rY  r   r   r   r”   &  s    
ûzMySQLDiff.load_unsignedc                 C   s@   | j D ]4}|  d|g¡}|D ]}||d f}| j |¡ qqd S )NzÚ
                SELECT column_name
                FROM information_schema.columns
                WHERE table_schema = DATABASE()
                   AND table_name = %s
                   AND extra = 'auto_increment'rW  )r   r²   rS  r%  )rR   r´   r¯   rŒ   rË   r   r   r   rT  3  s    
ûzMySQLDiff.load_auto_incrementNc                    sŠ   t ƒ  |||¡}|sd S |r†|  |¡}|  |¡dkrL|  |¡dkrL| d¡}|  |¡dkrf|dkrfd}||jf| jkr†d|kr†|d7 }|S )NÚcharrô   ÚvarÚboolÚintegerZAUTO_INCREMENTz AUTO_INCREMENT)rR  rÎ   r³   rß   r.  rÈ   rS  ©rR   r¨   r±   r´   r'   rÞ   rU  r   r   rÎ   B  s    

zMySQLDiff.get_field_db_typec                 C   sœ  t dd„ t|ƒD ƒƒ}dd„ |jD ƒ}|  |¡}|  |¡}| ¡ D ]R\}	}
|	|krVqB|
d rh|
d shqB|
d }| |d ¡}t|ƒdkrJ|s |  d	||	¡ qB|
d
 r°|j	r°qB|
d rÌt
|tjƒrÌ|jrÌqB|
d rÜ|jrÜqB|
d r
|
d dkr
|
 d¡r
|jr
qB|
d r|jrqB|
d r8|jtdr8qBt|ddƒrˆqBn>|
d rdt|ƒ|krdqB|
d rˆ|
d rˆt|ƒ|krˆqB|  d	||	¡ qBd S )Nc                 S   s   g | ]}|j |f‘qS r   r  rë   r   r   r   r   Y  s     z9MySQLDiff.find_index_missing_in_model.<locals>.<listcomp>c                 S   s   g | ]
}|j ‘qS r   rŠ   r  r   r   r   r   Z  s     rí   rù   rï   r   r   r6   r  r  r   rä   r  r  r!   r  F)r«   r%   rá   rå   ré   rÿ   rÙ   r   r    r  r   r   r  r  rí   r  r  r   rÃ   rÄ   )rR   r)   r  r  r´   râ   r  rà   ræ   r  rè   rï   r±   r   r   r   r  X  sD    

,"z%MySQLDiff.find_index_missing_in_modelc                    sh  t  t ¡}t|ƒD ]â}|r&|j|kr&q|jr|jr|jp<|j‰ | ˆ i ¡ d¡}|sr|rrt‡ fdd„| 	¡ D ƒƒ}ˆ |kr€|r€q| 
|ˆ g¡}	|  d|ˆ g|	d ¡ |jt d}
|
 d¡rÒ|  d|ˆ g|	d	 d
¡ |
 d¡r|  d|ˆ g|	d	 d¡ q|  |¡}tdd„ | ¡ D ƒƒ}|D ]H}||kr,q|r@||kr@q| 
||¡}	|  d|||	d ¡ qd S )Nrí   c                 3   s(   | ] \}}ˆ g|d  kr|d V  qdS rî   r   rð   rò   r   r   rJ     s      z6MySQLDiff.find_unique_missing_in_db.<locals>.<genexpr>r7   ró   r!   rô   r5   rõ   rö   r÷   rø   c                 S   s   g | ]}|d  r|d ‘qS ©rí   rï   r   rú   r   r   r   r      s      z7MySQLDiff.find_unique_missing_in_db.<locals>.<listcomp>rü   r  r   rò   r   r  †  s6    




z#MySQLDiff.find_unique_missing_in_db)NN)N)r8  rN  rO  r‘   r“   rÉ   r–   r¥   r’   r”   rT  rÎ   r  r  Ú__classcell__r   r   rU  r   rQ    s   .rQ  c                       sT   e Zd ZdZdZdd„ Zdd„ Zd‡ fdd	„	Zd
d„ Zdd„ Z	d‡ fdd„	Z
‡  ZS )ÚSqliteSQLDiffTFc                 C   sH   | j D ]<}d}|  d| g ¡D ]"}|||d f}|d  | j|< qqd S )Nr½   zPRAGMA table_info('%s');r‹   ZnotnullrX  )rR   r´   rÍ   rŒ   rË   r   r   r   r’   ±  s
    
zSqliteSQLDiff.load_nullc                 C   s   d S r\   r   r•   r   r   r   r”   »  s    zSqliteSQLDiff.load_unsignedNc                    sÀ   |d krg }dd„ t |ƒD ƒ}| ¡ D ]B}|d }t|ƒdkr&|d }	|	|kr&|d s^|d r&| |	¡ q&|  |¡}
tdd„ | ¡ D ƒƒ}|
D ]}||krŽ| |¡ qŽtƒ j|||||d	 d S )
Nc                 S   s   g | ]}|j r|jp|j‘qS r   )rí   r×   rØ   rë   r   r   r   r   Å  s      z;SqliteSQLDiff.find_unique_missing_in_db.<locals>.<listcomp>rï   r   r   rí   r  c                 S   s   g | ]}|d  r|d ‘qS r_  r   rú   r   r   r   r   Ï  s      )r  )r%   r  r   r(   ré   r   rR  r  )rR   r)   r  r  r´   r  r
  rè   rï   rÈ   ræ   r	  rU  r   r   r  Á  s    
z'SqliteSQLDiff.find_unique_missing_in_dbc                 C   s   d S r\   r   ©rR   r)   r  r  r´   r   r   r   r  Ù  s    z&SqliteSQLDiff.find_index_missing_in_dbc                 C   s   d S r\   r   rb  r   r   r   r  Ü  s    z)SqliteSQLDiff.find_index_missing_in_modelc                    sP   t ƒ  |||¡}|sd S |rL|  |¡}|  |¡dkrL|  |¡dkrL| d¡}|S )NrZ  rô   r[  )rR  rÎ   r³   rß   r.  r^  rU  r   r   rÎ   ß  s    

zSqliteSQLDiff.get_field_db_type)N)NN)r8  rN  rO  r‘   r“   r’   r”   r  r  r  rÎ   r`  r   r   rU  r   ra  ­  s   
ra  c                       s”   e Zd ZdZdZdddœZdZdZdd„ Zd	d„ Z	d
d„ Z
‡ fdd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd‡ fdd„	Zdd„ Z‡  ZS )ÚPostgresqlSQLDiffTz*django.contrib.postgres.fields.HStoreFieldú(django.contrib.postgres.fields.JSONField)ZhstoreZjsonbaÚ  
        SELECT nspname, relname, conname, attname, pg_get_constraintdef(pg_constraint.oid)
        FROM pg_constraint
        INNER JOIN pg_attribute ON pg_constraint.conrelid = pg_attribute.attrelid AND pg_attribute.attnum = any(pg_constraint.conkey)
        INNER JOIN pg_class ON conrelid=pg_class.oid
        INNER JOIN pg_namespace ON pg_namespace.oid=pg_class.relnamespace
        ORDER BY CASE WHEN contype='f' THEN 0 ELSE 1 END,contype,nspname,relname,conname;
    zÔ
        SELECT nspname, relname, attname, attnotnull
        FROM pg_attribute
        INNER JOIN pg_class ON attrelid=pg_class.oid
        INNER JOIN pg_namespace ON pg_namespace.oid=pg_class.relnamespace;
    c              
   C   sL   d|  d¡| ||d ƒ¡|  d¡| ||d ƒ¡|  d¡| |d ¡f S ©Nrf   r>   r   ZALTERr   ZTYPErL   re   rQ   r   r   r   rU     rj   zPostgresqlSQLDiff.<lambda>c              
   C   sL   d|  d¡| ||d ƒ¡|  d¡| ||d ƒ¡|  d¡| |d ¡f S re  re   rQ   r   r   r   rU     rj   c              	   C   sL   d|  d¡| ||d ƒ¡|  d¡| ||d ƒ¡|  |d ¡|  d¡f S )Nrf   r>   r   zALTER COLUMNr   rL   rg   rV   rQ   r   r   r   rU     rj   c                    s   t ƒ  ¡  i | _|  ¡  d S r\   )rR  r–   Úcheck_constraintsÚload_constraintsr•   rU  r   r   r–   	  s    
zPostgresqlSQLDiff.loadc                 C   s>   |   | jg ¡D ]*}|d |d |d f}|d  | j|< qd S )NÚnspnameÚrelnamerØ   Z
attnotnull)r²   ÚSQL_LOAD_NULLr   ©rR   rA  rË   r   r   r   r’     s    zPostgresqlSQLDiff.load_nullc                 C   s   d S r\   r   r•   r   r   r   r”     s    zPostgresqlSQLDiff.load_unsignedc                 C   sD   |   | jg ¡D ]0}|d |d |d f}d|d kr|| j|< qd S )Nrh  ri  rØ   ZCHECKÚpg_get_constraintdef)r²   ÚSQL_LOAD_CONSTRAINTSrf  rk  r   r   r   rg    s    z"PostgresqlSQLDiff.load_constraintsc                 C   s   dd|   |¡ƒ idœS )Nz)django.contrib.postgres.fields.ArrayFieldÚ
base_field)r‹   r·   )rÆ   )rR   rn  r   r   r   Úget_data_type_arrayfield  s
     
ÿþz*PostgresqlSQLDiff.get_data_type_arrayfieldc                    s¶   d‡ fdd„‡ fdd„‡ fdd„‡ fdd„‡ fdd„‡ fdd„‡ fd	d„‡ fd
d„‡ fdd„‡ fdd„‡ fdd„‡ fdd„‡ fdd„‡ fdd„‡ fdd„‡ fdd„‡ fdd„dddœS )Nr¸   c                      s   ˆ j ddS )NZBooleanField©rn  ©ro  r   r•   r   r   rU   )  rj   zCPostgresqlSQLDiff.get_data_types_reverse_override.<locals>.<lambda>c                      s   ˆ j ddS )NZBinaryFieldrp  rq  r   r•   r   r   rU   *  rj   c                      s   ˆ j ddS ©Nr¸   rp  rq  r   r•   r   r   rU   +  rj   c                      s   ˆ j ddS ©Nr   rp  rq  r   r•   r   r   rU   ,  rj   c                      s   ˆ j ddS rs  rq  r   r•   r   r   rU   -  rj   c                      s   ˆ j ddS rs  rq  r   r•   r   r   rU   .  rj   c                      s   ˆ j ddS rr  rq  r   r•   r   r   rU   /  rj   c                      s   ˆ j ddS rr  rq  r   r•   r   r   rU   0  rj   c                      s   ˆ j ddS rr  rq  r   r•   r   r   rU   1  rj   c                      s   ˆ j ddS )NZBigIntegerFieldrp  rq  r   r•   r   r   rU   2  rj   c                      s   ˆ j ddS ©NZ
FloatFieldrp  rq  r   r•   r   r   rU   3  rj   c                      s   ˆ j ddS rt  rq  r   r•   r   r   rU   4  rj   c                      s   ˆ j ddS rt  rq  r   r•   r   r   rU   5  rj   c                      s   ˆ j ddS ©NZDateTimeFieldrp  rq  r   r•   r   r   rU   6  rj   c                      s   ˆ j ddS ru  rq  r   r•   r   r   rU   7  rj   c                      s   ˆ j ddS )Nrº   rp  rq  r   r•   r   r   rU   8  rj   c                      s   ˆ j ddS )NZDurationFieldrp  rq  r   r•   r   r   rU   :  rj   z0django.contrib.postgres.search.SearchVectorFieldrd  )i  iè  ié  iê  ií  iî  iï  iñ  iö  i÷  iø  iù  iý  iþ  i[  i¡  iÏ  i¢  i  iÚ  r   r•   r   r•   r   r¢   &  s*    
















êz1PostgresqlSQLDiff.get_data_types_reverse_overridec              	   C   s&  i }|  dd|g¡ | ¡ D ]l\}}}}||krvg | ¡ dk| ¡ dk| ¡ dkrft|d  dd¡ƒnd	d
d
dœ||< || d  |¡ q|  dd|g¡ | ¡ D ]8\}}||krÈg d
d
d	dd
dœ||< || d  |¡ q¢|  d|g¡ | ¡ D ].\}	}
}}|	|kròt|
ƒ||d	d
ddœ||	< qò|S )zm
        Find constraints for table

        Backport of django's introspection.get_constraints(...)
        a  
            SELECT
                kc.constraint_name,
                kc.column_name,
                c.constraint_type,
                array(SELECT table_name::text || '.' || column_name::text FROM information_schema.constraint_column_usage WHERE constraint_name = kc.constraint_name)
            FROM information_schema.key_column_usage AS kc
            JOIN information_schema.table_constraints AS c ON
                kc.table_schema = c.table_schema AND
                kc.table_name = c.table_name AND
                kc.constraint_name = c.constraint_name
            WHERE
                kc.table_schema = %s AND
                kc.table_name = %s
        r½   úprimary key)rv  rí   zforeign keyr   rÏ   r   NF)rï   r  rí   r  r  rù   rï   aê  
            SELECT kc.constraint_name, kc.column_name
            FROM information_schema.constraint_column_usage AS kc
            JOIN information_schema.table_constraints AS c ON
                kc.table_schema = c.table_schema AND
                kc.table_name = c.table_name AND
                kc.constraint_name = c.constraint_name
            WHERE
                c.constraint_type = 'CHECK' AND
                kc.table_schema = %s AND
                kc.table_name = %s
        Ta  
            SELECT
                c2.relname,
                ARRAY(
                    SELECT (SELECT attname FROM pg_catalog.pg_attribute WHERE attnum = i AND attrelid = c.oid)
                    FROM unnest(idx.indkey) i
                ),
                idx.indisunique,
                idx.indisprimary
            FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
                pg_catalog.pg_index idx
            WHERE c.oid = idx.indrelid
                AND idx.indexrelid = c2.oid
                AND c.relname = %s
        )r§   r©   rÝ   rÄ   rÜ   r(   r   )rR   rŽ   r´   rs   rç   rè   rÈ   ÚkindZ	used_colsrù   rï   rí   Zprimaryr   r   r   r3  @  sP    ò

"ú
	õú
	òúz!PostgresqlSQLDiff.get_constraintsNc           	         s  t ƒ  |||¡}|sd S |r| d¡rf|jp2|j}|  d||f¡d d }| d¡rb| dd¡}|S |jrt	|t
ƒr|dkr„d}n|d	krd
}|r|j}|dkr¨d}|jp²|j}| j |||fi ¡ dd ¡}|r| dd¡}| dd¡}d dd„ | d¡D ƒ¡}|d| 7 }|S )Nz[]a`  SELECT attname, format_type(atttypid, atttypmod) AS type
                        FROM   pg_attribute
                        WHERE  attrelid = %s::regclass
                        AND    attname = %s
                        AND    attnum > 0
                        AND    NOT attisdropped
                        ORDER  BY attnum;
                    r   r   zcharacter varyingrô   r]  ÚserialZbigintZ	bigserialrÖ   r½   rl  z((rÛ   z))r,  z("c              	   S   s4   g | ],}d |kr,d  dd„ | dd¡D ƒ¡p.|‘qS )r,  z" c                 s   s   | ]}|  d ¡V  qdS )ú"N)r-  )rF   Úpr   r   r   rJ   Þ  s     zAPostgresqlSQLDiff.get_field_db_type.<locals>.<listcomp>.<genexpr>r@   r   )rO   rÜ   r]   r   r   r   r   Þ  s     z7PostgresqlSQLDiff.get_field_db_type.<locals>.<listcomp>r@   )rR  rÎ   Úendswithr×   rØ   r²   r  rM  r  r   r   rÇ   rf  rÙ   rO   rÜ   )	rR   r¨   r±   r´   r'   rØ   Zintrospect_db_typerÍ   Zcheck_constraintrU  r   r   rÎ   ³  sD    
÷
ö
ö
z#PostgresqlSQLDiff.get_field_db_typec              	   C   sH   z*|   d|g¡d d }| j | d¡¡W S  ttfk
rB   Y nX d S )Nz-SELECT typname FROM pg_type WHERE typelem=%s;r   ZtypnameÚ_)r²   ÚDATA_TYPES_REVERSE_NAMErÙ   r-  Ú
IndexErrorr¿   )rR   rÊ   r‹   r   r   r   rÀ   ã  s
    z*PostgresqlSQLDiff.get_field_db_type_lookup)NN)r8  rN  rO  r‘   r“   r}  rm  rj  r„   r…   r†   r–   r’   r”   rg  ro  r¢   r3  rÎ   rÀ   r`  r   r   rU  r   rc  ë  s(   þs0rc  )ZpostgisZpostgresql_psycopg2Z
postgresqlZmysqlZsqlite3Úoraclec                       sT   e Zd ZdZdZ‡ fdd„Z‡ fdd„Zedd„ ƒZ‡ fd	d
„Z	‡ fdd„Z
‡  ZS )ÚCommanda£  Prints the (approximated) difference between models and fields in the database for the given app name(s).

It indicates how columns in the database are different from the sql that would
be generated by Django. This command is not a database migration tool. (Though
it can certainly help) It's purpose is to show the current differences as a way
to check/debug ur models compared to the real database tables and columns.Fc                    s´   t ƒ  |¡ |jddd |jdddddd	d
 |jddddddd
 |jddddddd |jddddddd |jdddddd |jdddddd |jd dd!dtjd d S )"Nr™   Ú*)Únargsz--all-applicationsz-aÚ
store_trueFr4  z8Automaticly include all application from INSTALLED_APPS.)r1  ÚdefaultÚdestÚhelpz--not-only-existingz-eÚstore_falseTr‰   z_Check all tables that exist in the database, not only tables that should exist based on models.z--dense-outputz-drl   zRShows the output in dense format, normally output is spreaded over multiple lines.)r1  r…  r„  r†  z--output_textz-trC  z:Outputs the differences as descriptive text instead of SQLz--include-proxy-modelsr5  z!Include proxy models in the graphz--include-defaultsr   z3Include default values in SQL output (beta feature)z--migrate-for-testsÚmigrate_for_tests)rR  Úadd_argumentsÚadd_argumentÚargparseÚSUPPRESS)rR   ÚparserrU  r   r   r‰    sn      ü  ü   ý   ý  ý  ý  ýzCommand.add_argumentsc                    s   t ƒ j||Ž d| _d S )Nr   )rR  rˆ   Ú	exit_code)rR   rT   r·   rU  r   r   rˆ   1  s    zCommand.__init__c                 O   s\  ddl m} |d }d }t|dƒr2|jd d }n|j}|dkrHtdƒ‚|d	 r^tjd
d}nL|sjtdƒ‚t|t	t
tfƒs€|g}g }|D ] }t |¡}| |jd
d¡ qˆ|s¶tdƒ‚|d }	|	râddlm}
 |
d|žd
d
dœŽ |sötj d¡d }d|kr| d¡d }t |t¡}|||| j| jd}| ¡  | ¡  |jsLd| _| | j¡ d S )Nr   )Úsettingsr™   Ú	DATABASESr„  ZENGINEÚdummyzÙDjango doesn't know which syntax to use for your SQL statements,
because you haven't specified the DATABASE_ENGINE setting.
Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.r4  T)Zinclude_auto_createdzEnter at least one appname.z+Unable to execute sqldiff no models founds.rˆ  )Úcall_commandÚmigrate)Úno_inputZ
run_syncdbrÏ   éþÿÿÿrœ   )rq   rr   )r“  )Zdjango.confr  r9  r  ZDATABASE_ENGINEr   r   Z
get_modelsr   r   rÄ   rv   Zget_app_configr$   Údjango.core.managementr’  r   rN  rÜ   ÚDATABASE_SQLDIFF_CLASSESrÙ   rP  rq   rr   r–   rB  rm   rŽ  rF  rI   )rR   rT   ro   r  Z
app_labelsZenginern   r™   Z
app_configrˆ  r’  ÚclsZsqldiff_instancer   r   r   Úhandle5  sF    


zCommand.handlec              
      s„   zt ƒ j||Ž W nl tk
r~ } zN|d r.‚ t| dd ƒ}|sNttj| jjƒ}| 	d|j
j|f ¡ t d¡ W 5 d }~X Y nX d S )NÚ	tracebackrr   z%s: %srL   )rR  r§   r   rÃ   r	   Úsysrr   rI   ri   rI  rV  r8  Úexit)rR   rT   ro   r^   rr   rU  r   r   r§   k  s    zCommand.executec                    s   t ƒ  |¡ t | j¡ d S r\   )rR  Úrun_from_argvr›  rœ  rŽ  )rR   ÚargvrU  r   r   r  y  s    zCommand.run_from_argv)r8  rN  rO  r†  Zoutput_transactionr‰  rˆ   r   r™  r§   r  r`  r   r   rU  r   r€  þ  s   )
5r€  )+Ú__doc__rÑ   r›  r‹  Útypingr   r   r   r   Zdjango.appsr   r–  r   r   Zdjango.core.management.baser	   Zdjango.core.management.colorr
   Z	django.dbr   r   r   Zdjango.db.modelsr   Zdjango.db.models.fieldsr   r   Zdjango.db.models.optionsr   Z"django_extensions.management.utilsr   r:  r   rÄ   r   r%   r,   rP  rQ  ra  rc  r—  r€  r   r   r   r   Ú<module>   sJ        ? !>  ú
