o
    uvXj€L  ã                   @   sp   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 G d	d
„ d
eƒZdS )é    N)ÚDecimal)ÚApps)ÚBaseDatabaseSchemaEditor)Ú	Statement)Ú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„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‡  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 )NzüSQLite 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__© ú^/var/www/html/myproject/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_selfr0   Úother_tableÚconstraintsÚ
constraintÚconstraint_tableÚconstraint_columnr   r   r   Ú_is_referenced_by_fk_constraintB   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 )Nz°Renaming 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   rB   U   s   
ÿÿü
z#DatabaseSchemaEditor.alter_db_tablec              	      sŒ  |j }|jj}| ¡ \}}|j |krº| jjjsº| j||dd�rº| jjr-t	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 s‰w   Y  W d   ƒ n1 s˜w   Y  | j ¡ �}	|	 d¡ W d   ƒ d S 1 s³w   Y  d S tƒ j||||d� d S )NT)r8   z´Renaming 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)r3   Ú_metaÚdb_tableÚget_attname_columnr
   r?   r@   r>   rA   r   r   Úaliasr   Úalter_fieldr0   ÚexecuteÚfetchone)r   rC   Ú	old_fieldÚ	new_fieldrG   Úold_field_namer6   Ú_Úold_column_namer0   Úschema_versionÚreferences_templateÚnew_column_nameÚsearchÚreplacementr   r   r   rN   d   sB   
ÿþ
ü

ó€û"ÿz DatabaseSchemaEditor.alter_fieldc              	      sD  ‡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s›d
ˆ |
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ˆ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 ]}ˆ !|¡ �qŒg ˆ_%|�r d|_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_fieldrC   )Úf)rC   r   r   Úis_self_referentialž   s   z?DatabaseSchemaEditor._remake_table.<locals>.is_self_referentialc                    s$   i | ]}|j ˆ |ƒr| ¡ n|“qS r   )r3   Úclone©Ú.0r]   )r^   r   r   Ú
<dictcomp>¡   s    ÿÿz6DatabaseSchemaEditor._remake_table.<locals>.<dictcomp>c                    s   i | ]
}|j ˆ  |j ¡“qS r   )ÚcolumnÚ
quote_namer`   r   r   r   rb   §   s    NÚprimary_keyFrH   zcoalesce(%(col)s, %(default)s))ÚcolÚdefaultc                    ó   g | ]}‡ fd d„|D ƒ‘qS )c                    ó   g | ]}ˆ   ||¡‘qS r   ©Úget©ra   Ún©Úrename_mappingr   r   Ú
<listcomp>Ú   ó    úADatabaseSchemaEditor._remake_table.<locals>.<listcomp>.<listcomp>r   )ra   Úuniquern   r   r   rp   Ù   ó    ÿÿz6DatabaseSchemaEditor._remake_table.<locals>.<listcomp>c                    rh   )c                    ri   r   rj   rl   rn   r   r   rp   á   rq   rr   r   ©ra   Úindexrn   r   r   rp   à   rt   c                    s   g | ]
}ˆ j |jvr|‘qS r   )r3   Úfieldsru   ©Údelete_fieldr   r   rp   ç   s
    ÿ)Ú	app_labelrK   Ú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   )rd   )ra   Úxr   r   r   Ú	<genexpr>  s   € z5DatabaseSchemaEditor._remake_table.<locals>.<genexpr>)Úhandle_autom2m)rF   T)&rJ   Úlocal_concrete_fieldsÚgetattrÚlistÚitemsre   Úauto_createdrc   r3   Úmany_to_manyÚconcreter.   Úeffective_defaultÚpopÚnullrd   r\   ÚthroughÚdelete_modelr   r{   r|   r}   r:   ÚcopyÚdeepcopyrz   rK   r,   r€   Úobject_nameÚ	__bases__Úcreate_modelrO   Újoinr5   rB   Údeferred_sql)r   rC   Úcreate_fieldry   rN   ÚbodyÚmappingÚrestore_pk_fieldr3   ÚfieldrQ   rR   Úcase_sqlr~   r{   r|   r}   r:   Ú	body_copyÚmeta_contentsÚmetaÚ	new_modelÚsqlr   )ry   r^   rC   ro   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‘   rO   Úsql_delete_tablerd   rJ   rK   rˆ   r˜   r!   r   Úreferences_tableÚremove)r   rC   r…   r£   r   r   r   r‘   2  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�   rJ   rŠ   r–   r¤   ©r   rC   r�   r   r   r   Ú	add_field?  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,   Nrx   )	r‹   r\   r�   rJ   rŠ   r‘   Údb_parametersr
   r¤   r©   r   r   r   Úremove_fieldI  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rT|jrV||krX|jj	jD ]}	|	jsS|  |	j¡ qHdS dS dS dS )z3Perform a "physical" (non-ManyToMany) field update.©rN   N)r
   r?   Úcan_alter_table_rename_columnrc   Ú
column_sqlr\   Údb_constraintrO   Ú_rename_field_sqlrJ   rK   r¤   re   rC   Úrelated_objectsr‹   Úrelated_model)
r   rC   rQ   rR   Úold_typeÚnew_typeÚold_db_paramsÚnew_db_paramsrG   Úrelr   r   r   Ú_alter_field[  s(   
ÿÿþþ€ý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�   rJ   rK   r¤   Ú	get_fieldÚm2m_reverse_field_namer–   rO   rd   r—   Úm2m_column_nameÚm2m_reverse_namer‘   )r   rC   rQ   rR   rG   r   r   r   Ú_alter_many_to_manyn  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   rC   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_constraint)NF)T)F)NNN)Ú__name__r€   Ú__qualname__r¦   Úsql_create_fkÚsql_create_inline_fkÚsql_create_uniqueÚsql_delete_uniquer   r   r.   r>   rB   rN   r¤   r‘   rª   r¬   r¹   r¿   rÂ   rÅ   Ú__classcell__r   r   r   r   r	      s,    

' (

ÿ#r	   )r’   Údecimalr   Údjango.apps.registryr   Údjango.db.backends.base.schemar   Ú!django.db.backends.ddl_referencesr   Údjango.db.modelsr   Údjango.db.transactionr   Údjango.db.utilsr   r	   r   r   r   r   Ú<module>   s    