3
[;C                 @   sl   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 d dlmZ G dd	 d	eZdS )
    N)Decimal)Apps)BaseDatabaseSchemaEditor)	Statement)atomic)NotSupportedErrorc                   s   e Zd ZdZdZdZdZdZ fddZ fdd	Z	d
d Z
d ddZd! fdd	Zd" fdd	Zd#ddZd$ fdd	Zdd Zdd Zd%ddZdd Z  ZS )&DatabaseSchemaEditorzDROP TABLE %(table)sNzEREFERENCES %(to_table)s (%(to_column)s) DEFERRABLE INITIALLY DEFERREDz7CREATE UNIQUE INDEX %(name)s ON %(table)s (%(columns)s)zDROP INDEX %(name)sc                s   | j j  t j S )N)
connectiondisable_constraint_checkingsuper	__enter__)self)	__class__ E/tmp/pip-install-j7i95hgp/django/django/db/backends/sqlite3/schema.pyr      s    
zDatabaseSchemaEditor.__enter__c                s   t  j||| | jj  d S )N)r   __exit__r	   enable_constraint_checking)r   exc_type	exc_value	traceback)r   r   r   r      s    zDatabaseSchemaEditor.__exit__c             C   s   ydd l }|j|}W n( tk
r*   Y n |jk
r>   Y nX t|trVtt|S t|tt	tfrnt|S t|trd|j
dd S |d krdS t|tttfrd|j  S td|t|f d S )Nr   z'%s''z''ZNULLzX'%s'z*Cannot quote parameter value %r of type %s)sqlite3ZadaptImportErrorZProgrammingError
isinstanceboolstrintr   floatreplacebytes	bytearray
memoryviewhex
ValueErrortype)r   valuer   r   r   r   quote_value   s$    

z DatabaseSchemaEditor.quote_valueFc       
      C   s   | j j z}xr| j jj|D ]`}|r0|j|kr0q| j jj||j}x8|j D ],}|d \}}	||krL|dkst|	|krLdS qLW qW W dQ R X dS )a  
        Return whether or not the provided table name is referenced by another
        one. If `column_name` is specified, only references pointing to that
        column are considered. If `ignore_self` is True, self-referential
        constraints are ignored.
        Zforeign_keyNTF)r	   cursorZintrospectionZget_table_listnameZ_get_foreign_key_constraintsvalues)
r   
table_nameZcolumn_nameignore_selfr'   Zother_tableconstraints
constraintZconstraint_tableZconstraint_columnr   r   r   _is_referenced_by_fk_constraint:   s    z4DatabaseSchemaEditor._is_referenced_by_fk_constraintTc                s\   |rH| j |rH| jjr"td| | jj  t j||| | jj  nt j||| d S )NzRenaming the %r table while in a transaction is not supported on SQLite because it would break referential integrity. Try adding `atomic = False` to the Migration class.)r.   r	   in_atomic_blockr   r   r   alter_db_tabler
   )r   modelZold_db_tableZnew_db_tabledisable_constraints)r   r   r   r0   M   s    
z#DatabaseSchemaEditor.alter_db_tablec                sD  |j }|jj}|j \}}|j |ko2| j||ddr,| jjrRtd|jj|f t| jj	 t
 j||||d | jj |}	|	jdj d }
|	jd d| }|j d	 }|| }|| }|	jd
||f |	jd|
d	   |	jd |	jd W d Q R X W d Q R X | jj }	|	jd W d Q R X nt
 j||||d d S )NT)r+   zRenaming the %r.%r column while in a transaction is not supported on SQLite because it would break referential integrity. Try adding `atomic = False` to the Migration class.)strictzPRAGMA schema_versionr   zPRAGMA writable_schema = 1z REFERENCES "%s" ("%%s")    z3UPDATE sqlite_master SET sql = replace(sql, %s, %s)zPRAGMA schema_version = %dzPRAGMA writable_schema = 0zPRAGMA integrity_checkZVACUUM)r(   _metadb_tableZget_attname_columnr.   r	   r/   r   r   aliasr   alter_fieldr'   executeZfetchone)r   r1   	old_field	new_fieldr3   Zold_field_namer*   _Zold_column_namer'   Zschema_versionZreferences_templateZnew_column_namesearchreplacement)r   r   r   r8   [   s2    


z DatabaseSchemaEditor.alter_fieldc                s,  fddfddj jD }fddj jD }i d}t|dds`|rt|d	 ddrx<t|j D ],\}}	|	jrnd|	_|	}|	jrn||= ||	j= qnW |r|||j< |j	 r|j
rЈjj|||j< |rb|\}
}|j|
jd |j|
jd |||j< |
jrD|j rDd
j|
jjj|d }|||j< nj|
j||j< |j|
j<  r| j= | j=  j	r jjj jrj jjS t }tj|}fddj jD }fddj jD }j j} r fdd|D }j jj j||||d}tdf |}||d< j|d< tj jj|}tj dd }|j jd  j!|j jj jdd j"| t|j }j#dj|j jdj$fdd|D dj$dd |D jj jf  jdd W dQ R X xj%D ]}j#| qW g _%|r(d|_dS )a  
        Shortcut to transform a model from old_model into new_model

        The essential steps are:
          1. rename the model's existing table, e.g. "app_model" to "app_model__old"
          2. create a table with the updated definition called "app_model"
          3. copy the data from the old renamed table to the new table
          4. delete the "app_model__old" table
        c                s   | j o| jj kS )N)Zis_relationremote_fieldr1   )f)r1   r   r   is_self_referential   s    z?DatabaseSchemaEditor._remake_table.<locals>.is_self_referentialc                s$   i | ]} |r|j  n||jqS r   )cloner(   ).0r@   )rA   r   r   
<dictcomp>   s   z6DatabaseSchemaEditor._remake_table.<locals>.<dictcomp>c                s   i | ]} j |j|jqS r   )
quote_namecolumn)rC   r@   )r   r   r   rD      s    Nprimary_keyFr4   zcoalesce(%(col)s, %(default)s))coldefaultc                s   g | ]} fd d|D qS )c                s   g | ]} j ||qS r   )get)rC   n)rename_mappingr   r   
<listcomp>   s    zADatabaseSchemaEditor._remake_table.<locals>.<listcomp>.<listcomp>r   )rC   unique)rL   r   r   rM      s   z6DatabaseSchemaEditor._remake_table.<locals>.<listcomp>c                s   g | ]} fd d|D qS )c                s   g | ]} j ||qS r   )rJ   )rC   rK   )rL   r   r   rM      s    zADatabaseSchemaEditor._remake_table.<locals>.<listcomp>.<listcomp>r   )rC   index)rL   r   r   rM      s   c                s   g | ]} j |jkr|qS r   )r(   fields)rC   rO   )delete_fieldr   r   rM      s    )	app_labelr6   unique_togetherindex_togetherindexesappsZMeta
__module__c             s   s"   | j j}|| j _d V  || j _d S )N)r5   r6   )r1   Ztemporary_table_nameZoriginal_table_namer   r   r   altered_table_name   s    z>DatabaseSchemaEditor._remake_table.<locals>.altered_table_nameZ__old)r2   z%INSERT INTO %s (%s) SELECT %s FROM %sz, c             3   s   | ]\}} j |V  qd S )N)rE   )rC   xy)r   r   r   	<genexpr>  s    z5DatabaseSchemaEditor._remake_table.<locals>.<genexpr>c             s   s   | ]\}}|V  qd S )Nr   )rC   rY   rZ   r   r   r   r[     s    )handle_autom2mT)&r5   Zlocal_concrete_fieldsgetattrlistitemsrG   auto_createdrF   r(   many_to_manyZconcreter&   Zeffective_defaultpopnullrE   r?   throughdelete_modelr   copydeepcopyrS   rT   rU   rR   r6   r$   rW   Zobject_name	__bases__
contextlibcontextmanagerr0   create_modelr9   joindeferred_sql)r   r1   create_fieldrQ   r8   bodymappingZrestore_pk_fieldr(   fieldr:   r;   Zcase_sqlrV   rS   rT   rU   Zmeta_contentsmetaZ
temp_modelrX   Z
field_mapssqlr   )rQ   rA   r1   rL   r   r   _remake_table   s    








z"DatabaseSchemaEditor._remake_tablec                sl   |rt  j| nV| j| jd| j|jji  x6t| jD ](}t	|t
r<|j|jjr<| jj| q<W d S )Ntable)r   re   r9   sql_delete_tablerE   r5   r6   r^   rm   r   r   Zreferences_tableremove)r   r1   r\   rs   )r   r   r   re     s    z!DatabaseSchemaEditor.delete_modelc             C   s2   |j r |jjjjr | j|jjS | j||d dS )z
        Create a field on a model. Usually involves adding a column, but may
        involve adding a table instead (for M2M fields).
        )rn   N)ra   r?   rd   r5   r`   rk   rt   )r   r1   rq   r   r   r   	add_field$  s    zDatabaseSchemaEditor.add_fieldc             C   sN   |j r"|jjjjrJ| j|jj n(|j| jdd dkr<dS | j||d dS )z
        Remove a field from a model. Usually involves deleting a column,
        but for M2Ms may involve deleting a table.
        )r	   r$   N)rQ   )	ra   r?   rd   r5   r`   re   Zdb_parametersr	   rt   )r   r1   rq   r   r   r   remove_field.  s    z!DatabaseSchemaEditor.remove_fieldc	       
      C   sP   | j |||fd |jrL|jrL||krLx$|jjjD ]}	|	js2| j |	j q2W dS )z3Perform a "physical" (non-ManyToMany) field update.)r8   N)rt   rG   r1   r5   Zrelated_objectsra   Zrelated_model)
r   r1   r:   r;   Zold_typeZnew_typeZold_db_paramsZnew_db_paramsr3   relr   r   r   _alter_field@  s
    z!DatabaseSchemaEditor._alter_fieldc             C   s   |j jjj|j jjjkrR| j|j j|j jjj|j |j jjj|j fd dS | j|j j | jd| j	|j jjjdj
d|j |j gdj
d|j |j g| j	|j jjjf  | j|j j dS )z*Alter M2Ms to repoint their to= endpoints.)r8   Nz%INSERT INTO %s (%s) SELECT %s FROM %sz, id)r?   rd   r5   r6   rt   	get_fieldZm2m_reverse_field_namerk   r9   rE   rl   Zm2m_column_nameZm2m_reverse_namere   )r   r1   r:   r;   r3   r   r   r   _alter_many_to_manyK  s&    

z(DatabaseSchemaEditor._alter_many_to_many)NF)T)F)NNN)T)F)__name__rW   __qualname__rv   Zsql_create_fkZsql_create_inline_fkZsql_create_uniqueZsql_delete_uniquer   r   r&   r.   r0   r8   rt   re   rx   ry   r{   r~   __classcell__r   r   )r   r   r      s$   
&
 


r   )ri   rf   decimalr   Zdjango.apps.registryr   Zdjango.db.backends.base.schemar   Z!django.db.backends.ddl_referencesr   Zdjango.db.transactionr   Zdjango.db.utilsr   r   r   r   r   r   <module>   s   