
v^L                 @   s   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 d  d l m Z d  d	 l m Z Gd
 d   d e  Z d S)    N)Decimal)Apps)BaseDatabaseSchemaEditor)	Statement)strip_quotes)UniqueConstraint)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 d  Z d   f d d  Z d   f d d  Z d d d d d  Z d   f d d  Z d d   Z d d   Z d d d  Z d d   Z   f d  d!   Z   f d" d#   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   s t d   t   j   S)NzSQLite schema editor cannot be used while foreign key constraint checks are enabled. Make sure to disable them before entering a transaction.atomic() context because SQLite does not support disabling them in the middle of a multi-statement transaction.)
connectiondisable_constraint_checkingr	   super	__enter__)self)	__class__ C/tmp/pip-build-8lau8j11/django/django/db/backends/sqlite3/schema.pyr      s    	zDatabaseSchemaEditor.__enter__c                s4   |  j  j   t   j | | |  |  j  j   d  S)N)r   Zcheck_constraintsr   __exit__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 |  } Wn& t k
 r3 Yn | j k
 rG Yn Xt | t  rg t t |   St | t t	 t f  r t |  St | t  r d | j
 d d  S| d  k r d St | t t t f  r d | j   St 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    } x |  j  j j |  D] } | rF | j | k rF q( |  j  j j | | j  } xL | j   D]> } | d \ } }	 | | k rn | d k s |	 | k rn d Sqn Wq( WWd QRXd 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_constraintC   s    z4DatabaseSchemaEditor._is_referenced_by_fk_constraintTc                s   |  j  j j rt | rt |  j |  rt |  j  j rA 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 < 3.26 because it would break referential integrity. Try adding `atomic = False` to the Migration class.)
r   features!supports_atomic_references_renamer0   in_atomic_blockr	   r   r   alter_db_tabler   )r   modelZold_db_tableZnew_db_tabledisable_constraints)r   r   r   r4   V   s    
z#DatabaseSchemaEditor.alter_db_tablec                s  | j  } | j j } | j   \ } } | j  | k r|  j j j r|  j | | d d r|  j j r t	 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  Wd  QRXWd  QRX|  j j    }	 |	 j d  Wd  QRXn t   j | | | d | d  S)Nr-   TzRenaming the %r.%r column while in a transaction is not supported on SQLite < 3.26 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   r1   r2   r0   r3   r	   r   aliasr   alter_fieldr)   executeZfetchone)r   r5   	old_field	new_fieldr7   Zold_field_namer,   _Zold_column_namer)   Zschema_versionZreferences_templateZnew_column_namesearchreplacement)r   r   r   r<   e   s4    	


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 | r t | d	 d d  r xR t | j    D]> \ } }	 |	 j r d |	 _ |	 } |	 j r | | =| |	 j =q W| r$| | | j <| j	 r$| j
 r$ j  j |   | | j <| r| \ }
 } | j |
 j d  | j |
 j d  | | | j <|
 j r| j rd
 d  j |
 j  d  j  j |   i } | | | j <n  j |
 j  | | j <| j  |
 j <  r1|   j =|   j =  j	 r1  j j j  j r1 j   j j  St   }  f d d    j  j D }  f d d    j  j D }  j  j }   r  f d d   | D } t  j  j  } t j |  } d  j  j d  j  j d | d | d | d | d | i } t d f  |  } | | d < j | d <t  j  j  j |  t j |  } d  j  j d d t   j  j  d | d | d | d | d | i } t d f  |  } | | d < j | d <t d  j  j  j |  }  j! |   j" d  j | j  j  d j#  f d d   | D  d j# | j$     j  j  j  f   j  d  d  j% | | j  j  j  j d! d x  j& D] }  j" |  qWg   _& | rd" | _ d S)#a|  
        Shortcut to transform a model from old_model into new_model

        This follows the correct procedure to perform non-rename or column
        addition operations based on SQLite's documentation

        https://www.sqlite.org/lang_altertable.html#caution

        The essential steps are:
          1. Create a table with the updated definition called "new__app_model"
          2. Copy the data from the existing "app_model" table to the new table
          3. Drop the "app_model" table
          4. Rename the "new__app_model" table to "app_model"
          5. Restore any index of the previous "app_model" table.
        c                s   |  j  o |  j j   k S)N)Zis_relationremote_fieldr5   )f)r5   r   r   is_self_referential   s    z?DatabaseSchemaEditor._remake_table.<locals>.is_self_referentialc                s4   i  |  ]* }   |  r$ | j    n | | j  q Sr   )cloner*   ).0rD   )rE   r   r   
<dictcomp>   s   	z6DatabaseSchemaEditor._remake_table.<locals>.<dictcomp>c                s(   i  |  ] }   j  | j  | j  q Sr   )
quote_namecolumn)rG   rD   )r   r   r   rH      s   	 Nprimary_keyFr8   zcoalesce(%(col)s, %(default)s)coldefaultc                s)   g  |  ] }   f d  d   | D  q S)c                s"   g  |  ] }   j  | |   q Sr   )get)rG   n)rename_mappingr   r   
<listcomp>   s   	 zADatabaseSchemaEditor._remake_table.<locals>.<listcomp>.<listcomp>r   )rG   unique)rP   r   r   rQ      s   	z6DatabaseSchemaEditor._remake_table.<locals>.<listcomp>c                s)   g  |  ] }   f d  d   | D  q S)c                s"   g  |  ] }   j  | |   q Sr   )rN   )rG   rO   )rP   r   r   rQ      s   	 zADatabaseSchemaEditor._remake_table.<locals>.<listcomp>.<listcomp>r   )rG   index)rP   r   r   rQ      s   	c                s(   g  |  ] }   j  | j k r |  q Sr   )r*   fields)rG   rS   )delete_fieldr   r   rQ      s   	 	app_labelr:   unique_togetherindex_togetherindexesr.   appsZMeta
__module__znew__%szNew%sz%INSERT INTO %s (%s) SELECT %s FROM %sz, c             3   s   |  ] }   j  |  Vq d  S)N)rI   )rG   x)r   r   r   	<genexpr>  s    z5DatabaseSchemaEditor._remake_table.<locals>.<genexpr>handle_autom2mr6   T)'r9   Zlocal_concrete_fieldsgetattrlistitemsrK   auto_createdrJ   r*   many_to_manyZconcreter(   Zeffective_defaultpopnullrI   rC   throughdelete_modelr   rW   rX   rY   r.   copydeepcopyrV   r:   r&   r[   Zobject_name	__bases__r   create_modelr=   joinr+   r4   deferred_sql)r   r5   create_fieldrU   r<   bodymappingZrestore_pk_fieldr*   fieldr>   r?   Zcase_sqlrZ   rW   rX   rY   r.   Z	body_copyZmeta_contentsmetaZ	new_modelsqlr   )rU   rE   r5   rP   r   r   _remake_table   s    			

	

		z"DatabaseSchemaEditor._remake_tablec                s   | r t    j |  nw |  j |  j d |  j | j j  i  xK t |  j  D]: } t	 | t
  rR | j | j j  rR |  j j |  qR Wd  S)Ntable)r   rg   r=   sql_delete_tablerI   r9   r:   r`   rm   r   r   Zreferences_tableremove)r   r5   r^   rs   )r   r   r   rg   3  s    $z!DatabaseSchemaEditor.delete_modelc             C   sE   | 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)rc   rC   rf   r9   rb   rk   rt   )r   r5   rq   r   r   r   	add_field@  s    zDatabaseSchemaEditor.add_fieldc             C   sk   | j  r1 | j j j j rg |  j | j j  n6 | j d |  j  d d k rT 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&   NrU   )	rc   rC   rf   r9   rb   rg   Zdb_parametersr   rt   )r   r5   rq   r   r   r   remove_fieldJ  s    	z!DatabaseSchemaEditor.remove_fieldc	       
      C   s   |  j  j j r | j | j k r |  j | |  |  j | |  k r | j rW | j pf | j of | j r |  j |  j | j	 j
 | | |   S|  j | d | | f | j r | j r | | k r x0 | j j	 j D] }	 |	 j s |  j |	 j  q Wd S)z3Perform a "physical" (non-ManyToMany) field update.r<   N)r   r1   Zcan_alter_table_rename_columnrJ   Z
column_sqlrC   Zdb_constraintr=   Z_rename_field_sqlr9   r:   rt   rK   r5   Zrelated_objectsrc   Zrelated_model)
r   r5   r>   r?   Zold_typeZnew_typeZold_db_paramsZnew_db_paramsr7   relr   r   r   _alter_field\  s    $%	z!DatabaseSchemaEditor._alter_fieldc             C   s$  | j  j j j | j  j j j k rw |  j | j  j d | j  j j j | j    | j  j j j | j    f 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.r<   Nz%INSERT INTO %s (%s) SELECT %s FROM %sz, id)rC   rf   r9   r:   rt   	get_fieldZm2m_reverse_field_namerk   r=   rI   rl   Zm2m_column_nameZm2m_reverse_namerg   )r   r5   r>   r?   r7   r   r   r   _alter_many_to_manyo  s&    $"			 z(DatabaseSchemaEditor._alter_many_to_manyc                s?   t  | t  r. | j r. t   j | |  n |  j |  d  S)N)r   r   	conditionr   add_constraintrt   )r   r5   r/   )r   r   r   r     s    z#DatabaseSchemaEditor.add_constraintc                s?   t  | t  r. | j r. t   j | |  n |  j |  d  S)N)r   r   r   r   remove_constraintrt   )r   r5   r/   )r   r   r   r     s    z&DatabaseSchemaEditor.remove_constraint)__name__r[   __qualname__rv   Zsql_create_fkZsql_create_inline_fkZsql_create_uniqueZsql_delete_uniquer   r   r(   r0   r4   r<   rt   rg   rx   ry   r{   r~   r   r   r   r   )r   r   r
      s&   '
#r
   )rh   decimalr   Zdjango.apps.registryr   Zdjango.db.backends.base.schemar   Z!django.db.backends.ddl_referencesr   Zdjango.db.backends.utilsr   Zdjango.db.modelsr   Zdjango.db.transactionr   Zdjango.db.utilsr	   r
   r   r   r   r   <module>   s   