o
    [hQ                     @   st   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mZ G d	d
 d
eZdS )    N)Decimal)Apps)NotSupportedError)BaseDatabaseSchemaEditor)	Statement)strip_quotes)CompositePrimaryKeyUniqueConstraintc                       s   e Zd ZdZdZdZeZdZdZdZ	dZ
dZ fddZ fd	d
Zdd Zdd Z	d#ddZd$ fdd	Z fddZ f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 DEFERREDz,ALTER TABLE %(table)s DROP COLUMN %(column)sz7CREATE 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.)
connectionZdisable_constraint_checkingr   super	__enter__self	__class__ /home/ubuntu/experiments/live_experiments/Pythonexperiments/Otree/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   Zcheck_constraintsr   __exit__Z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''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_valuec                 C   s
   |  |S r   )r)   )r   r(   r   r   r   prepare_defaultJ   s   
z$DatabaseSchemaEditor.prepare_defaultc              	      s  fddfddj jD }j j}t|tr!| ||j< fddj jD }i d}|p3g }t|ddsCtd	d
 |D rkt	|
 D ]!\}	|	jrjtfdd
|D sjd|	_|	}|	jrj|= ||	j= qI|r|||j< | s|js|js|jr|||j< |D ]W}
|
\}}||jd ||jd |||j< |j|j< |jrq|jr|js| s|}n|\}}d|j|d }|||j< q|j||j< q r| j= | jd  jr jjj jr jjS t }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&|} r j(|j jj(kr|j j}t)||j( |j j*+| d|_,| -d|j j"d.fdd
|D d.|/ j j"f  jdd 0||j j"j j" j1D ]}-| qg _1|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   )Zis_relationremote_fieldmodel)f)r,   r   r   is_self_referentialc   s   z?DatabaseSchemaEditor._remake_table.<locals>.is_self_referentialc                    s$   i | ]}|j  |r| n|qS r   )nameclone.0r-   )r.   r   r   
<dictcomp>g   s    z6DatabaseSchemaEditor._remake_table.<locals>.<dictcomp>c                    s&   i | ]}|j d u r|j |jqS F)	generatedcolumn
quote_namer1   r   r   r   r3   t   s
    
Nprimary_keyFc                 s   s     | ]\}}t |d dV  qdS )r8   FN)getattrr2   _	new_fieldr   r   r   	<genexpr>   s    
z5DatabaseSchemaEditor._remake_table.<locals>.<genexpr>c                 3   s    | ]
\}} |j kV  qd S r   r/   r:   r>   r   r   r=      s
    
zcoalesce(%(col)s, %(default)s))coldefaultc                    s   g | ]} fd d|D qS )c                    s   g | ]}  ||qS r   )get)r2   nrename_mappingr   r   
<listcomp>   s    zADatabaseSchemaEditor._remake_table.<locals>.<listcomp>.<listcomp>r   )r2   uniquerC   r   r   rE      s    z6DatabaseSchemaEditor._remake_table.<locals>.<listcomp>c                    s   g | ]
} j |jvr|qS r   )r/   fields)r2   indexdelete_fieldr   r   rE      s    )	app_labeldb_tableunique_togetherindexesconstraintsappsZMetar   
__module__znew__%szNew%s%INSERT INTO %s (%s) SELECT %s FROM %s, c                 3   s    | ]}  |V  qd S r   )r7   )r2   xr   r   r   r=     s    )handle_autom2mT)2_metaZlocal_concrete_fieldspkr   r   r0   r/   r9   anylistitemsr8   auto_createdr6   has_db_defaultmany_to_manyr5   Zconcreter*   effective_defaultpopnullZdb_default_sqlr7   r+   throughdelete_modelr   rM   rN   rO   copydeepcopyrK   rL   r'   rQ   Zobject_name	__bases__r   ZattnamedelattrZlocal_fieldsremovecreate_modelexecutejoinvaluesZalter_db_tabledeferred_sql)r   r,   create_fieldrJ   alter_fieldsbodyrW   mappingZrestore_pk_fieldfieldZalter_field	old_fieldr<   r@   r;   Zcase_sqlrP   rM   rN   rO   Z	body_copyZmeta_contentsmetaZ	new_modelZauto_pksqlr   )rJ   r.   r,   r/   rD   r   r   _remake_tableM   s   
















z"DatabaseSchemaEditor._remake_tableTc                    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   rb   ri   sql_delete_tabler7   rV   rL   rY   rl   r   r   Zreferences_tablerg   )r   r,   rU   rt   r   r   r   rb     s   z!DatabaseSchemaEditor.delete_modelc                    s   ddl m} |jr|jjjjr| |jj dS t|t	rdS |j
s9|js9|jr9| |dus9| rBt|j|sB| j||d dS t || dS )zCreate a field on a model.r   )ValueN)rm   )Zdjango.db.models.expressionsrx   r]   r+   ra   rV   r[   rh   r   r   r8   rF   r`   r^   r\   Z
db_defaultru   r   	add_field)r   r,   rq   rx   r   r   r   ry   +  s$   
	
zDatabaseSchemaEditor.add_fieldc                    s   |j r|jjjjr| |jj dS dS | jjjr1|j	s1|j
s1|js1|jr(|js1t || 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'   NrI   )r]   r+   ra   rV   r[   rb   r   featuresZcan_alter_table_drop_columnr8   rF   Zdb_indexdb_constraintr   remove_fieldZdb_parametersru   )r   r,   rq   r   r   r   r|   J  s(   	z!DatabaseSchemaEditor.remove_fieldFc	                 C   sN  |j |j kr+| ||| ||kr+|jr|js+|jr|js+| | |jj|||S | j|||fgd |	d}	|	d}
|j
r||ksJ|	|
krt }|jj}|jD ]&}|j|kr\qT|jsl|j|jkrk||j qT|jrz|jjjrz||j qT|jr|jD ]}|j|krq|jjjjr||jj q|D ]}| | qdS dS dS )z3Perform a "physical" (non-ManyToMany) field update.rn   	collationN)r6   Z
column_sqlr+   r{   ri   Z_rename_field_sqlrV   rL   ru   rA   rF   setr,   Zrelated_objectsrelated_modelr]   
field_namer/   addr8   ra   r[   )r   r,   rr   r<   Zold_typenew_typeZold_db_paramsZnew_db_paramsstrictZold_collationZnew_collationZrelated_modelsoptsr+   r]   r   r   r   r   _alter_fieldf  sX   





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|j jj| |j jj| fg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}   NrR   rS   id)r+   ra   rV   rL   ru   	get_fieldZm2m_reverse_field_nameZm2m_field_namerh   ri   r7   rj   Zm2m_column_nameZm2m_reverse_namerb   )r   r,   rr   r<   r   r   r   r   _alter_many_to_many  sV   





z(DatabaseSchemaEditor._alter_many_to_manyc                    B   t |tr|js|js|js|jrt || d S | | d S r   )	r   r	   	conditioncontains_expressionsinclude
deferrabler   add_constraintru   r   r,   
constraintr   r   r   r        
z#DatabaseSchemaEditor.add_constraintc                    r   r   )	r   r	   r   r   r   r   r   remove_constraintru   r   r   r   r   r     r   z&DatabaseSchemaEditor.remove_constraintc                 C   s   d| S )NzCOLLATE r   )r   r~   r   r   r   _collate_sql  s   z!DatabaseSchemaEditor._collate_sql)NNN)Tr4   )__name__rQ   __qualname__rw   Zsql_create_fkZsql_create_inline_fkZsql_create_column_inline_fkZsql_delete_columnZsql_create_uniqueZsql_delete_uniqueZsql_alter_table_commentZsql_alter_column_commentr   r   r)   r*   ru   rb   ry   r|   r   r   r   r   r   __classcell__r   r   r   r   r
      s6    
 M%
:@r
   )rc   decimalr   Zdjango.apps.registryr   Z	django.dbr   Zdjango.db.backends.base.schemar   Z!django.db.backends.ddl_referencesr   Zdjango.db.backends.utilsr   Zdjango.db.modelsr   r	   r
   r   r   r   r   <module>   s    