o
    ^"<fQ                     @   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 G d
d deZdS )    N)Decimal)Apps)NotSupportedError)BaseDatabaseSchemaEditor)	Statement)strip_quotes)UniqueConstraint)atomicc                       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 fd d!Z f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  s	tdt  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__ X/var/www/html/kck/venv/lib/python3.10/site-packages/django/db/backends/sqlite3/schema.pyr      s
   

zDatabaseSchemaEditor.__enter__c                    s(   | j   t ||| | j   d S N)r   check_constraintsr   __exit__enable_constraint_checking)r   exc_type	exc_value	tracebackr   r   r   r   "   s   
zDatabaseSchemaEditor.__exit__c                 C   s   zdd l }||}W n ty   Y n
 |jy   Y nw t|tr)tt|S t|tt	tfr5t|S t|trBd|
dd S |d u rHdS t|tttfrVd|  S td|t|f )Nr   z'%s''z''NULLzX'%s'z*Cannot quote parameter value %r of type %s)sqlite3adaptImportError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  G}| j j|D ]6}|r|j|krq| j j||j}| D ]}|d \}}	||krB|du s8|	|krB  W d   dS q$qW d   dS 1 sOw   Y  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.
        foreign_keyNTF)r   cursorintrospectionget_table_listname_get_foreign_key_constraintsvalues)
r   
table_namecolumn_nameignore_selfr1   other_tableconstraints
constraintconstraint_tableconstraint_columnr   r   r   _is_referenced_by_fk_constraintC   s$   


z4DatabaseSchemaEditor._is_referenced_by_fk_constraintTc                    sh   | j jjs*|r*| |r*| j jrtd| | j   t ||| | j 	  d S t ||| 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_renamer?   in_atomic_blockr   r   r   alter_db_tabler   )r   modelold_db_tablenew_db_tabledisable_constraintsr   r   r   rC   V   s   

z#DatabaseSchemaEditor.alter_db_tablec              	      s  |  ||sd S |j}|jj}| \}}|j|kr| jjjs| j||ddr| jj	r5t
d|jj|f t| jjb t j||||d | j C}	|	d d }
|	d d| }| d	 }|| }|| }|	d
||f |	d|
d	   |	d |	d W d    n1 sw   Y  W d    n1 sw   Y  | j }	|	d W d    d S 1 sw   Y  d S t j||||d d S )NT)r9   zRenaming 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_checkVACUUM)_field_should_be_alteredr4   _metadb_tableget_attname_columnr   r@   rA   r?   rB   r   r	   aliasr   alter_fieldr1   executefetchone)r   rD   	old_field	new_fieldrH   old_field_namer7   _old_column_namer1   schema_versionreferences_templatenew_column_namesearchreplacementr   r   r   rP   e   sF   



"z DatabaseSchemaEditor.alter_fieldc              	      sH  fddfddj jD }fddj jD }i d}t|dds0|rMt|d	 ddrMt| D ]\}}	|	jrLd|	_|	}|	jrL||= ||	j= q6|re|||j< |j	se|j
re|||j< |r|\}
}||
jd ||
jd |||j< |
jr|jsd
|
j|d }|||j< n	|
j||j< |j|
j<  r| j= | j=  j	rĈ jjj jrĈ jjS t }fddj jD }fddj jD }j j} r fdd|D }tj j}t|}j jj j|||||d}tdd|}||d< j|d< tj jj| t|}j jdt j j |||||d}tdd|}||d< j|d< tdj j j|}!| "d|j jd#fdd|D d#|$ j jf  jdd j%||j jj jdd j&D ]}"| qg _&|rd|_dS 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 u S r   )is_relationremote_fieldrD   )f)rD   r   r   is_self_referential   s   z?DatabaseSchemaEditor._remake_table.<locals>.is_self_referentialc                    s$   i | ]}|j  |r| n|qS r   )r4   clone.0r_   )r`   r   r   
<dictcomp>   s    z6DatabaseSchemaEditor._remake_table.<locals>.<dictcomp>c                    s   i | ]
}|j  |j qS r   )column
quote_namerb   r   r   r   rd      s    Nprimary_keyFrI   zcoalesce(%(col)s, %(default)s))coldefaultc                       g | ]} fd d|D qS )c                       g | ]}  ||qS r   getrc   nrename_mappingr   r   
<listcomp>       ADatabaseSchemaEditor._remake_table.<locals>.<listcomp>.<listcomp>r   )rc   uniquerp   r   r   rr          z6DatabaseSchemaEditor._remake_table.<locals>.<listcomp>c                    rj   )c                    rk   r   rl   rn   rp   r   r   rr      rs   rt   r   rc   indexrp   r   r   rr      rv   c                    s   g | ]
} j |jvr|qS r   )r4   fieldsrw   delete_fieldr   r   rr      s
    )	app_labelrM   unique_togetherindex_togetherindexesr;   appsMetar   
__module__znew__%szNew%s%INSERT INTO %s (%s) SELECT %s FROM %s, c                 3   s    | ]}  |V  qd S r   )rf   )rc   xr   r   r   	<genexpr>  s    z5DatabaseSchemaEditor._remake_table.<locals>.<genexpr>)handle_autom2m)rG   T)'rL   local_concrete_fieldsgetattrlistitemsrg   auto_createdre   r4   many_to_manyconcreter/   effective_defaultpopnullrf   r^   throughdelete_modelr   r}   r~   r   r;   copydeepcopyr|   rM   r-   r   object_name	__bases__r   create_modelrQ   joinr6   rC   deferred_sql)r   rD   create_fieldr{   rP   bodymappingrestore_pk_fieldr4   fieldrS   rT   case_sqlr   r}   r~   r   r;   	body_copymeta_contentsmeta	new_modelsqlr   )r{   r`   rD   rq   r   r   _remake_table   s   








	

	



z"DatabaseSchemaEditor._remake_tablec                    sj   |r
t  | d S | | jd| |jji  t| jD ]}t	|t
r2||jjr2| j| qd S )Ntable)r   r   rQ   sql_delete_tablerf   rL   rM   r   r   r"   r   references_tableremove)r   rD   r   r   r   r   r   r   5  s   z!DatabaseSchemaEditor.delete_modelc                 C   s2   |j r|jjjjr| |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).
        )r   N)r   r^   r   rL   r   r   r   r   rD   r   r   r   r   	add_fieldB  s   zDatabaseSchemaEditor.add_fieldc                 C   sT   |j r|jjjjr| |jj dS dS |j| jdd du 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-   Nrz   )	r   r^   r   rL   r   r   db_parametersr   r   r   r   r   r   remove_fieldL  s   z!DatabaseSchemaEditor.remove_fieldc	                 C   s:  | j jjr0|j|jkr0| ||| ||kr0|jr|js0|jr#|js0| | |j	j
|||S | j|||fd |jr||krt }	|jj	}
|
jD ]&}|j|krRqJ|jsb|j|jkra|	|j qJ|jrp|jj	jrp|	|j qJ|jr|
jD ]}|j|krqw|jjj	jr|	|jj qw|	D ]}| | qdS dS dS )z3Perform a "physical" (non-ManyToMany) field update.rP   N)r   r@   can_alter_table_rename_columnre   
column_sqlr^   db_constraintrQ   _rename_field_sqlrL   rM   r   ru   setrD   related_objectsrelated_modelr   
field_namer4   addrg   r   r   )r   rD   rS   rT   old_typenew_typeold_db_paramsnew_db_paramsrH   related_modelsoptsr^   r   r   r   r   r   _alter_field^  sJ   




z!DatabaseSchemaEditor._alter_fieldc                 C   s   |j jjj|j jjjkr)| j|j j|j jj| |j jj| fd dS | |j j | d| 	|j jjjd
d| | gd
d| | g| 	|j jjjf  | |j j dS )z*Alter M2Ms to repoint their to= endpoints.r   Nr   r   id)r^   r   rL   rM   r   	get_fieldm2m_reverse_field_namer   rQ   rf   r   m2m_column_namem2m_reverse_namer   )r   rD   rS   rT   rH   r   r   r   _alter_many_to_many  s0   	z(DatabaseSchemaEditor._alter_many_to_manyc                    0   t |tr|jrt || d S | | d S r   )r"   r   	conditionr   add_constraintr   r   rD   r<   r   r   r   r        z#DatabaseSchemaEditor.add_constraintc                    r   r   )r"   r   r   r   remove_constraintr   r   r   r   r   r     r   z&DatabaseSchemaEditor.remove_constraintc                 C   s   d| S )Nz	 COLLATE r   )r   	collationr   r   r   _collate_sql  s   z!DatabaseSchemaEditor._collate_sql)NF)T)F)NNN)__name__r   __qualname__r   sql_create_fksql_create_inline_fksql_create_uniquesql_delete_uniquer   r   r/   r?   rC   rP   r   r   r   r   r   r   r   r   r   __classcell__r   r   r   r   r
      s.    

) (

$#r
   )r   decimalr   django.apps.registryr   	django.dbr   django.db.backends.base.schemar   !django.db.backends.ddl_referencesr   django.db.backends.utilsr   django.db.modelsr   django.db.transactionr	   r
   r   r   r   r   <module>   s    