o
    ѷ6ic                     @  sx  d dl mZ d dlZd dlZ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 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 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' 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. eddd Z/ed!ed"ef d Z0G d#d$ d$eZ1eed%  Z2edee3e3f ed& f Z4ed' Z5dKd*d+Z6G d,d dej7Z8G d-d. d.e8ej7Z7dLd1d2Z9e%dMd6d7Z:G d8d9 d9e3Z;G d:d; d;Z<G d<d= d=e<Z=G d>d? d?e<Z>dNdAdBZ?dOdDdEZ@dPdQdIdJZAdS )R    )annotationsN)nullcontext)copy)wraps)Any)Callable)	Generator)Literal)Optional)Tuple)	TypedDict)TypeVar)Union)cast)settings)connections)models)
ExtraWhere)atomic)cached_property)gettext)cacheREWRITE_MARKER)GlobalStatus)	StopWatch)WeightedAverageRate)format_duration)settings_to_cmd_args_QQuerySetMixin)boundQueryRewriteFunc.c                   @  s&   e Zd ZU ded< ded< ded< dS )_CountTriesApproxDictbool	fall_backreturn_approx_intintmin_sizeN)__name__
__module____qualname____annotations__ r-   r-   ^/var/www/hoanhtaovolam_webdjango/env/lib/python3.10/site-packages/django_mysql/models/query.pyr#   )   s   
 r#   JOINzORDER BYzGROUP BYall)   funcreturnc                   s    t  d fdd}tt|S )Nargsr   kwargsr5   c                    s   t jstd | i |S )NzXYou need to set DJANGO_MYSQL_REWRITE_QUERIES = True in your settings to use query hints.)r   DJANGO_MYSQL_REWRITE_QUERIESRuntimeError)r6   r7   r4   r-   r.   wrapper6   s
   z'requires_query_rewrite.<locals>.wrapperr6   r   r7   r   r5   r   )r   r   r"   )r4   r;   r-   r:   r.   requires_query_rewrite5   s   
r=   c                
      s  e Zd ZU ded< df fdd	Zdg fddZdh fddZ				didjddZ			dkdl fddZe	dmddZ
e	dnd d!Ze	dnd"d#Ze	dnd$d%Ze	dnd&d'Ze	dnd(d)Ze	dnd*d+Ze	dnd,d-Zedhd.d/Zdo fd0d1Zedpd2d3Zejdqd5d3Zd6d6d7drd=d>Zd6d6d7drd?d@Zd6d6d7drdAdBZe	d6d6dCdsdEdFZdd6d6dGdHdIdJdKd6dL	dtd[d\Zdd6d6dGdHdIdJdKd6dL	dud^d_Zdd6d6dGdHdIdJdKd6dL	dvdadbZdwdxdddeZ  ZS )yr    z_CountTriesApproxDict | None_count_tries_approxr6   r   r7   r5   Nonec                   s   t  j|i | d | _d S N)super__init__r>   selfr6   r7   	__class__r-   r.   rB   E   s   
zQuerySetMixin.__init__rD   r   c                   s8   t  j|i |}tt| dd |_t| drd |_|S )Nr>   _found_rows)rA   _cloner   getattrr>   hasattrrG   )rD   r6   r7   clonerE   r-   r.   rH   I   s
   
zQuerySetMixin._cloner'   c                   s&   | j d ur| jdi | j S t  S )Nr-   )r>   approx_countrA   countrD   rE   r-   r.   rM   V   s   

zQuerySetMixin.countT  activater$   r%   r&   r(   c                 C  s(   |   }|r|||d|_|S d |_|S )N)r%   r&   r(   )rH   r>   )rD   rP   r%   r&   r(   rK   r-   r-   r.   count_tries_approx[   s   z QuerySetMixin.count_tries_approxc                   s\   zt | }W n ty   |stdt   Y S w |r&||k r&t  S |r,t|S |S )Nz)Cannot use approx_count on this queryset.)rL   
ValueErrorrA   rM   ApproximateInt)rD   r%   r&   r(   numrE   r-   r.   rL   o   s   
zQuerySetMixin.approx_countstringstrc                 C  s&   d|v rt d| jd| dgdS )z
        Adds an arbitrary user-defined comment that will appear after
        SELECT/UPDATE/DELETE which can be used to identify where the query was
        generated, etc.
        z*/z-Bad label - cannot be embedded in SQL commentz/*QueryRewrite':label=z*/1where)rR   extra)rD   rU   r-   r-   r.   label   s   zQuerySetMixin.labelc                 C     | j dgdS )Nz /*QueryRewrite':STRAIGHT_JOIN*/1rW   rY   rN   r-   r-   r.   straight_join      zQuerySetMixin.straight_joinc                 C  r[   )Nz#/*QueryRewrite':SQL_SMALL_RESULT*/1rW   r\   rN   r-   r-   r.   sql_small_result   r^   zQuerySetMixin.sql_small_resultc                 C  r[   )Nz!/*QueryRewrite':SQL_BIG_RESULT*/1rW   r\   rN   r-   r-   r.   sql_big_result   r^   zQuerySetMixin.sql_big_resultc                 C  r[   )Nz$/*QueryRewrite':SQL_BUFFER_RESULT*/1rW   r\   rN   r-   r-   r.   sql_buffer_result   r^   zQuerySetMixin.sql_buffer_resultc                 C  r[   )Nz/*QueryRewrite':SQL_CACHE*/1rW   r\   rN   r-   r-   r.   	sql_cache   r^   zQuerySetMixin.sql_cachec                 C  r[   )Nz/*QueryRewrite':SQL_NO_CACHE*/1rW   r\   rN   r-   r-   r.   sql_no_cache   r^   zQuerySetMixin.sql_no_cachec                 C  s   | j dgd}d |_|S )Nz&/*QueryRewrite':SQL_CALC_FOUND_ROWS*/1rW   )rY   rG   )rD   qsr-   r-   r.   sql_calc_found_rows   s   z!QuerySetMixin.sql_calc_found_rowsc                 C  s*   t | ds	td| jd u rtd| jS )NrG   z=found_rows can only be used if you call sql_calc_found_rows()zVA QuerySet with sql_calc_found_rows must be iterated before found_rows can be accessed)rJ   rR   rG   r9   rN   r-   r-   r.   
found_rows   s   

zQuerySetMixin.found_rowsc                   s*   t | ddd u rtdt j|i |S )NrG   r   z2sql_calc_found_rows() doesn't work with iterator())rI   rR   rA   iteratorrC   rE   r-   r.   rg      s   zQuerySetMixin.iteratorc                 C  s
   | j d S )N_result_cache)__dict__rN   r-   r-   r.   rh      s   
zQuerySetMixin._result_cachevaluec                 C  sj   || j d< t| ddd u r3t| j  }|d | d | _W d    d S 1 s,w   Y  d S d S )Nrh   rG   r   zSELECT FOUND_ROWS())ri   rI   r   dbcursorexecutefetchonerG   )rD   rj   rl   r-   r-   r.   rh      s   

"N)for_
table_nameindex_namesro   _IndexHintForTyperp   
str | Nonec                G     | j |d||dS )NUSEhintro   rp   _index_hintrD   ro   rp   rq   r-   r-   r.   	use_index      zQuerySetMixin.use_indexc                G  rt   )NFORCErv   rx   rz   r-   r-   r.   force_index   r|   zQuerySetMixin.force_indexc                G  rt   )NIGNORErv   rx   rz   r-   r-   r.   ignore_index   r|   zQuerySetMixin.ignore_index)rp   ro   rw   c                G  s   |dkrt |st|  d|d u r| jjj}|dv r%d| d}n|d u r,d}ntdt |dkr9d	}n	d
d| d
 }dj||||d}| j|gdS )Nru   z'_index requires at least one index namer/   zFOR   z9for_ must be one of: None, 'JOIN', 'ORDER BY', 'GROUP BY'r   NONE`z`,`zA/*QueryRewrite':index=`{table_name}` {hint} {for_bit}{indexes}*/1)rp   rw   for_bitindexesrW   )	lenrR   lowermodel_metadb_tablejoinformatrY   )rD   rw   rp   ro   rq   r   r   r-   r-   r.   ry      s$   

zQuerySetMixin._index_hint      ?   r3   '  F	
atomicallystatus_thresholdspk_range
chunk_time
chunk_size	chunk_min	chunk_maxreport_progresstotalr   r   dict[str, int | float] | Noner   _SmartPkRangeTyper   floatr   r   r   r   r   
int | NoneSmartIteratorc       	   
      C     t | |||||||||	d
S N)
querysetr   r   r   r   r   r   r   r   r   )r   
rD   r   r   r   r   r   r   r   r   r   r-   r-   r.   
iter_smart     zQuerySetMixin.iter_smartSmartChunkedIteratorc       	   
      C  r   r   )r   r   r-   r-   r.   iter_smart_chunks.  r   zQuerySetMixin.iter_smart_chunksSmartPKRangeIteratorc       	   
      C  r   r   )r   r   r-   r-   r.   iter_smart_pk_rangesH  r   z"QuerySetMixin.iter_smart_pk_rangesdisplayc                 C  s
   t | |S r@   )pt_visual_explain)rD   r   r-   r-   r.   r   b  s   
zQuerySetMixin.pt_visual_explain)r6   r   r7   r   r5   r?   )rD   r   r6   r   r7   r   r5   r   )r5   r'   )TTTrO   )rD   r   rP   r$   r%   r$   r&   r$   r(   r'   r5   r   )TTrO   )r%   r$   r&   r$   r(   r'   r5   r'   )rU   rV   r5   r    )rD   r   r5   r   r<   )r5   r   )rj   r   r5   r?   )
rD   r   rq   rV   ro   rr   rp   rs   r5   r   )rD   r   rq   rV   rw   rV   rp   rs   ro   rr   r5   r   )r   r$   r   r   r   r   r   r   r   r'   r   r'   r   r'   r   r$   r   r   r5   r   )r   r$   r   r   r   r   r   r   r   r'   r   r'   r   r'   r   r$   r   r   r5   r   )r   r$   r   r   r   r   r   r   r   r'   r   r'   r   r'   r   r$   r   r   r5   r   T)r   r$   r5   rV   ) r)   r*   r+   r,   rB   rH   rM   rQ   rL   r=   rZ   r]   r_   r`   ra   rb   rc   re   propertyrf   rg   rh   setterr{   r~   r   ry   r   r   r   r   __classcell__r-   r-   rE   r.   r    B   s   
 


%c                   @     e Zd ZdS )QuerySetNr)   r*   r+   r-   r-   r-   r.   r   f      r   r   models.QuerySetc                 C  s   |   }t| j|_|S r@   )rH   _make_mixin_classrF   )r   	queryset2r-   r-   r.   add_QuerySetMixinj  s   r   klasstype[models.QuerySet]type[QuerySetMixin]c                 C  s"   G dd dt | }d| j |_|S )Nc                   @  r   )z*_make_mixin_class.<locals>.MixedInQuerySetNr   r-   r-   r-   r.   MixedInQuerySetr  r   r   MySQL)r    r)   )r   r   r-   r-   r.   r   p  s   r   c                      "   e Zd ZdZd fddZ  ZS )rS   z}
    An int subclass purely for displaying the fact that this represents an
    approximate value, for in e.g. the admin
    r5   rV   c                   s   t ddt  i S )NzApproximately %(number)snumber)_rA   __str__rN   rE   r-   r.   r     s   zApproximateInt.__str__r5   rV   )r)   r*   r+   __doc__r   r   r-   r-   rE   r.   rS   z  s    rS   c                
   @  s   e Zd ZU ded< dddddddd	dd
	d:ddZd;d d!Zd<d"d#Zejej	fZ
d=d%d&Zd>d'd(Zd?d+d,Zd@d/d0Z		dAdBd3d4ZdCd5d6ZedDd8d9ZdS )Er   zint | Literal['???']objects_doneTNr   r   r3   r   Fr   r   r   r   r$   r   r   r   r   r   r   r   r'   r   r   r   r   r   c       	         C  s   |  || _|rt| jjd| _nt | _|| _|| _t|| _	d|  k r-|ks2J d J d|| _
|| _| || _|	| _|
| _d S )N)usingr   zAMinimum chunk size should not be greater than maximum chunk size.)sanitize_querysetr   r   rk   maybe_atomicr   r   r   r   rater   r   constrain_sizer   r   r   )rD   r   r   r   r   r   r   r   r   r   r   r-   r-   r.   rB     s"   

zSmartChunkedIterator.__init__r5   Generator[QuerySet, None, None]c              	   c  sL   |   \}}||krtj}d}ntj}d}|}t| jj}| | |||r|| j	 |}|| j
|  }|dkrCt||d }nt||d }t ?}	| j, |dkr_| jj||d}
n| jj||d}
||f|
_|
V  | ||
| W d    n1 sw   Y  W d    n1 sw   Y  | |
|	j |||s(|   d S )Nr3   r2   )pk__gtepk__lt)pk__ltepk__gt)get_first_and_lastoperatorleger   r   rk   init_progresswait_until_load_lowr   r   minmaxr   r   filter_smart_iterator_pksupdate_progressadjust_chunk_size
total_timeend_progress)rD   first_pklast_pkcomp	direction
current_pkstatusstart_pkend_pktimerchunkr-   r-   r.   __iter__  s<   


 
zSmartChunkedIterator.__iter__c                 C  s   |j rtd| jj |jjs|jjrtd| jj |jjj	}t
|| jp4t
|tjo4t
|jd | j}|s?td| jj |dS )Nz0You can't use %s on a QuerySet with an ordering.z&You can't use %s on a sliced QuerySet.r   z;You can't use %s on a model with a non-integer primary key.pk)orderedrR   rF   r)   querylow_mark	high_markr   r   r   
isinstanceALLOWED_PK_FIELD_CLASSESr   
ForeignKeyforeign_related_fieldsorder_by)rD   r   r   allowed_fieldr-   r-   r.   r     s,   


z&SmartChunkedIterator.sanitize_querysettuple[int, int]c                 C  s2  t | jtr't| jdkr'| jd | jd k o| jjj}|r$| j | _| jS | jdkr9| jjj	
| jj }n| jd u rB| j}ntd| j |jjsR| }|djddd}|d	jddd}z|d }W n tyy   d }}Y nw z|d }W n ty   |}Y nw | jjjr||fS ||fS )
Nr   r3   r   r1   z!Unrecognized value for pk_range: r   T)flatz-pk)r   r   tupler   r   r   standard_orderingreverser   objectsr   rk   r1   rR   r   values_list
IndexError)rD   should_be_reversedbase_qsmin_qsmax_qsmin_pkmax_pkr-   r-   r.   r     s:   


z'SmartChunkedIterator.get_first_and_lastc                 C  s   t t|| j| jS r@   )r   r   r   r   )rD   r   r-   r-   r.   r     s   z#SmartChunkedIterator.constrain_sizer   r?   c                 C  sT   |j d u r	| j}nt|}|dkr| j||}n| j}|dk r"d}| || _d S )Nr   r3   )rh   r   r   r   updater   )rD   r   r   num_processednew_chunk_sizer-   r-   r.   r     s   
z&SmartChunkedIterator.adjust_chunk_sizer   _SmartDirectionTypec                 C  s   | j sd S t | _d| _d| _d| _| jd u r;zt| j| _| jdk r*| j	 | _W n t
y:   | j	 | _Y nw | | d S )Nr   r   rO   )r   time
start_time
old_reportr   chunks_doner   rL   r   rM   rR   r   )rD   r   r-   r-   r.   r   2  s    


z"SmartChunkedIterator.init_progressmodels.QuerySet | Noner   c           	      C  s  | j sd S |d ur/|  jd7  _| jdkr/t| jtsJ |jd u r&d| _n	|  jt|7  _| jdkr7d}n%t| jts?J | jd usFJ z
d| j| j  }W n ty[   d}Y nw d	| j
| jj| j| j|| j}|d ur|dj	|dkrydnd|d	7 }| jdkr| jjrt| jtsJ | jd usJ | j| j }td
t|| jj }|dt| d7 }dtd
t| jt|  }| jrtjd tj| tj| tj  || _d S )Nr3   z???g        d   z4{} {} processed {}/{} objects ({:.2f}%) in {} chunksz; {dir} pk so far {end_pk}highestlowest)dirr   r   z, z
 remainingr   )r   r  r   r   r'   rh   r   r   ZeroDivisionErrorr   
model_namerF   r)   r   avg_rater   r   r  sysstdoutwriteflush)	rD   r   r   r   percent_completereportn_remainings_remainingspacingr-   r-   r.   r   D  sV   


	

z$SmartChunkedIterator.update_progressc                 C  sL   | j sd S tt | j }tjdj| j| jdkrdndt	|d d S )Nz6
Finished! Iterated over {n} object{s} in {duration}.
r3   sr   )nr  duration)
r   r'   r  r  r  r  r  r   r   r   )rD   r   r-   r-   r.   r     s   z!SmartChunkedIterator.end_progressrV   c                 C  s
   | j jjS r@   )r   r   r)   rN   r-   r-   r.   r    s   
zSmartChunkedIterator.model_name)r   r   r   r$   r   r   r   r   r   r   r   r'   r   r'   r   r'   r   r$   r   r   )r5   r   r   r   r5   r   )r5   r   )r   r'   r5   r'   )r   r   r   r   r5   r?   )r   r  r5   r?   )NN)r   r  r   r  r   r   r5   r?   )r5   r?   r   )r)   r*   r+   r,   rB   r   r   r   IntegerField	AutoFieldr   r   r   r   r   r   r   r   r  r-   r-   r-   r.   r     s6   
 
%
(

(


Ar   c                      r   )r   zB
    Subclass of SmartChunkedIterator that unpacks the chunks
    r5   #Generator[models.Model, None, None]c                 #  s     t   D ]}|E d H  qd S r@   )rA   r   )rD   r   rE   r-   r.   r     s   zSmartIterator.__iter__)r5   r   )r)   r*   r+   r   r   r   r-   r-   rE   r.   r     s    r   c                      s   e Zd Zd fddZ  ZS )r   r5   &Generator[tuple[int, int], None, None]c                 #  s*    t   D ]}|j\}}||fV  qd S r@   )rA   r   r   )rD   r   r   r   rE   r-   r.   r     s
   
zSmartPKRangeIterator.__iter__)r5   r!  )r)   r*   r+   r   r   r-   r-   rE   r.   r     s    r   r'   c                 C  sn   t | stdt| j }| }| jjj}|d|f |	 d }|W  d    S 1 s0w   Y  d S )Nz-This QuerySet cannot be approximately countedzSELECT TABLE_ROWS
               FROM INFORMATION_SCHEMA.TABLES
               WHERE TABLE_SCHEMA = DATABASE() AND
                     TABLE_NAME = %s
            r   )
can_approx_countrR   r   rk   rl   r   r   r   rm   rn   )r   
connectionrl   rp   rL   r-   r-   r.   rL     s   



$rL   r$   c                 C  sp   | j }|js|js|jrdS |jd us|jdkrdS |jjD ]}t|t	s( dS t
dd |jD r5 dS qdS )NFr   c                 s  s    | ]}t |vV  qd S r@   r   ).0sqlr-   r-   r.   	<genexpr>  s    z#can_approx_count.<locals>.<genexpr>T)r   selectgroup_bydistinctr   r   rX   childrenr   r   anysqls)r   r   childr-   r-   r.   r"    s   
r"  Tr   rV   c              	   C  s  ddl m} t| j }||}|+ | }| j \}}|d| | W d    n1 s0w   Y  W d    n1 s?w   Y  dd |jD }|d }	t	|j
d|	g }
tj|
tjd}tjd	d
g|jtjd}|jd ustJ |j  | d jdd}|  |rt| |S )Nr   )CaptureQueriesContextzEXPLAIN c                 S  s   g | ]}|d  qS )r%  r-   )r$  qr-   r-   r.   
<listcomp>  s    z%pt_visual_explain.<locals>.<listcomp>r2   z-e)r  zpt-visual-explain-)stdinr  zutf-8)encoding)django.test.utilsr.  r   rk   rl   r   sql_with_paramsrm   captured_queriesr   settings_dict
subprocessPopenPIPEr  closecommunicatedecodewaitprint)r   r   r.  r#  capturerrl   r%  paramsqueriesexplain_querymysql_commandmysqlvisual_explainexplanationr-   r-   r.   r     s4   
 
r   )r4   r"   r5   r"   r  )r   r   r5   r   )r   r   r5   r'   )r   r    r5   r$   r   )r   r   r   r$   r5   rV   )B
__future__r   r   r8  r  r  
contextlibr   r   	functoolsr   typingr   r   r   r	   r
   r   r   r   r   r   django.confr   	django.dbr   r   django.db.models.sql.wherer   django.db.transactionr   django.utils.functionalr   django.utils.translationr   r   django_mysql.compatr   django_mysql.rewrite_queryr   django_mysql.statusr   django_mysql.utilsr   r   r   r   r   r"   r#   rr   r'   r   r  r=   r   r    r   r   rS   r   r   r   rL   r"  r   r-   r-   r-   r.   <module>   sn    
  &
	
  

	
