o
    ѷ6iU                     @  sh  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 ed ZdZ dZ!dZ"G dd dZ#G dd deZ$e%dZ&d+d"d#Z'd,d'd(Z(G d)d* d*e$Z)dS )-    )annotationsN)random)dedent)time)Any)Callable)Iterable)Literal)Tuple)cast)DEFAULT_TIMEOUT)	BaseCache)default_key_func)connections)router)force_bytes)import_string)collapse_spaces)get_list_sql)ipzl         l    l    c                   @  s   e Zd ZdZd	ddZdS )
Optionsz~A class that will quack like a Django model _meta class.

    This allows cache operations to be controlled by the router
    tablestrreturnNonec                 C  s@   || _ d| _d| _d| _d| _d| _d| _d| _d| _d| _	d S )Ndjango_mysql
cacheentryzcache entryzcache entries
CacheEntryFT)
db_table	app_label
model_nameverbose_nameverbose_name_pluralobject_nameabstractmanagedproxyswapped)selfr    r+   W/var/www/hoanhtaovolam_webdjango/env/lib/python3.10/site-packages/django_mysql/cache.py__init__/   s   
zOptions.__init__N)r   r   r   r   )__name__
__module____qualname____doc__r-   r+   r+   r+   r,   r   )   s    r   c                      s   e Zd Zd	 fddZ  ZS )
BaseDatabaseCacher   r   paramsdict[str, Any]r   r   c                   s.   t  |  | _G  fddd}|| _d S )Nc                      s   e Zd Ze ZdS )z.BaseDatabaseCache.__init__.<locals>.CacheEntryN)r.   r/   r0   r   _metar+   r   r+   r,   r   A   s    r   )superr-   _tablecache_model_class)r*   r   r3   r   	__class__r6   r,   r-   =   s   
zBaseDatabaseCache.__init__r   r   r3   r4   r   r   )r.   r/   r0   r-   __classcell__r+   r+   r:   r,   r2   <   s    r2   z^([^:]*):(\d+):(.*)full_keyr   r   tuple[str, str, int]c                 C  s6   t | }|dusJ |d|dt|dfS )z
    Reverse of Django's default_key_func, i.e. undoing:

        def default_key_func(key, key_prefix, version):
            return '%s:%s:%s' % (key_prefix, version, key)
    N         )reverse_key_rematchgroupint)r>   rD   r+   r+   r,   default_reverse_key_funcJ   s   
 rG   reverse_key_func2str | Callable[[str], tuple[str, str, int]] | None,Callable[[str], tuple[str, str, int]] | Nonec                 C  s:   | durt | r
| S tttgttttf f t| S dS )z
    Function to decide which reverse key function to use

    Defaults to ``None``, as any other value might not apply to the given
    KEY_FUNCTION. Also the user may not use any of the operations that require
    reversing the key_func.
    N)callabler   r   r   r
   rF   r   )rH   r+   r+   r,   get_reverse_key_funcV   s   
rL   c                      s  e Zd ZU ed? ZedZededdZde	d< df fddZ
	dgdhddZedZ	didjddZedZedfdkd!d"Zedfdld$d%Zefdmd'd(Zed)Zed*d+Zed,Zedfdnd/d0Zdidod1d2Zed3Zdidpd4d5Zed6Zdidqd7d8Zed9Zdrdsd;d<Zdrdsd=d>Z dtdAdBZ!edCZ"dudDdEZ#edfdvdFdGZ$edHZ%dw fdIdJZ&dxdMdNZ'dydPdQZ(dzdUdVZ)dudWdXZ*efd{ fdYdZZ+	did|d]d^Z,	did}d_d`Z-did~dadbZ.dedcddZ/  Z0S )
MySQLCacherA   a          CREATE TABLE `{table_name}` (
            cache_key varchar(255) CHARACTER SET utf8 COLLATE utf8_bin
                                   NOT NULL PRIMARY KEY,
            value longblob NOT NULL,
            value_type char(1) CHARACTER SET latin1 COLLATE latin1_bin
                               NOT NULL DEFAULT 'p',
            expires BIGINT UNSIGNED NOT NULL
        );
    r   rF   c                 C  s   t t d S Ni  )rF   r   )clsr+   r+   r,   _now~   s   zMySQLCache._nowrJ   rH   r   r   r3   r4   r   c                   s   t  || |di }|dd| _|dd| _|dd| _| jtu r5t| _	d| j
v r3td	d S |d
d }t|| _	d S )NOPTIONSCOMPRESS_MIN_LENGTHi  COMPRESS_LEVEL   CULL_PROBABILITYg{Gz?:zdCannot use the default KEY_FUNCTION and REVERSE_KEY_FUNCTION if you have a colon in your KEY_PREFIX.REVERSE_KEY_FUNCTION)r7   r-   get_compress_min_length_compress_level_cull_probabilitykey_funcr   rG   rH   
key_prefix
ValueErrorrL   )r*   r   r3   optionsrH   r:   r+   r,   r-      s   

zMySQLCache.__init__Nkeydefault
Any | Noneversion
int | Noner   c           
      C  s   | j ||d}| | t| j}t| j| j}t| 	 }|
| jj|d||  f | }W d    n1 s?w   Y  |d u rJ|S |\}}	| ||	S Nrc   r6   )make_keyvalidate_keyr   db_for_readr9   r   ops
quote_namer8   cursorexecute
_get_queryformatrP   fetchonedecode)
r*   r`   ra   rc   dbr   rl   rowvalue
value_typer+   r+   r,   rX      s   

zMySQLCache.getzx
        SELECT value, value_type
        FROM {table}
        WHERE cache_key = %s AND
              expires >= %s
    keysIterable[str]c                   s    fdd|D }t | }|D ]} | qt j}t| j j	}t| 
 }| jj|t|d|  g  | }	W d    n1 sQw   Y  i }
|	D ]\}}}|| } |||
|< qZ|
S )Nc                   s   i | ]
} j |d |qS rf   rg   .0r`   r*   rc   r+   r,   
<dictcomp>   s    z'MySQLCache.get_many.<locals>.<dictcomp>r   list_sql)listrv   rh   r   ri   r9   r   rj   rk   r8   rl   rm   _get_many_queryro   r   rP   fetchallrq   )r*   rv   rc   made_key_to_key	made_keysr`   rr   r   rl   rowsdatamade_keyrt   ru   r+   r|   r,   get_many   s(   
	zMySQLCache.get_manyz
        SELECT cache_key, value, value_type
        FROM {table}
        WHERE cache_key IN {list_sql} AND
              expires >= %s
    rt   timeoutc                 C  s,   | j ||d}| | | d||| d S )Nrf   setrg   rh   	_base_setr*   r`   rt   r   rc   r+   r+   r,   r      s   
zMySQLCache.setboolc                 C  s(   | j ||d}| | | d|||S )Nrf   addr   r   r+   r+   r,   r      s   
zMySQLCache.addmodec                 C  s   |dvrt d| |}t| j}t| j| j}| 	  t| 
 G}| |\}}	|dkr<| j}
|||	|f}n| j}
|||	||  f}||
j|d| |dkr_	 W d    dS |j}|dkW  d    S 1 spw   Y  d S )N)r   r   z'mode' should be 'set' or 'add'r   r6   Ti  )r^   get_backend_timeoutr   db_for_writer9   r   rj   rk   r8   _maybe_cullrl   encode
_set_query
_add_queryrP   rm   ro   	lastrowid)r*   r   r`   rt   r   exprr   r   rl   ru   queryr3   	insert_idr+   r+   r,   r      s(   
$zMySQLCache._base_setz
        INSERT INTO {table} (cache_key, value, value_type, expires)
        VALUES {{VALUES_CLAUSE}}
        ON DUPLICATE KEY UPDATE
            value=VALUES(value),
            value_type=VALUES(value_type),
            expires=VALUES(expires)
    {{VALUES_CLAUSE}}(%s, %s, %s, %s)a  
        INSERT INTO {table} (cache_key, value, value_type, expires)
        VALUES (%s, %s, %s, %s)
        ON DUPLICATE KEY UPDATE
            value=IF(expires > @tmp_now:=%s, value, VALUES(value)),
            value_type=IF(expires > @tmp_now, value_type, VALUES(value_type)),
            expires=IF(
                expires > @tmp_now,
                IFNULL(
                    LEAST(LAST_INSERT_ID(444), NULL),
                    expires
                ),
                VALUES(expires)
            )
    r   	list[str]c                 C  s   |  |}t| j}t| j| j}|   g }|	 D ] \}}	| j
||d}
| |
 | |	\}	}||
|	||f q| jdddd |D j|d}t|  }||| W d    g S 1 sjw   Y  g S )Nrf   r   ,c                 s  s    | ]}d V  qdS )r   Nr+   rz   r+   r+   r,   	<genexpr>F  s    z&MySQLCache.set_many.<locals>.<genexpr>r6   )r   r   r   r9   r   rj   rk   r8   r   itemsrg   rh   r   extend_set_many_queryreplacejoinro   rl   rm   )r*   r   r   rc   r   rr   r   r3   r`   rt   r   ru   r   rl   r+   r+   r,   set_many2  s*   


zMySQLCache.set_manyc                 C  s   | j ||d}| | t| j}t| j| j}t| 	 }|
| jj|d|f W d    d S 1 s9w   Y  d S re   )rg   rh   r   r   r9   r   rj   rk   r8   rl   rm   _delete_queryro   r*   r`   rc   rr   r   rl   r+   r+   r,   deleteM  s   
"zMySQLCache.deletez>
        DELETE FROM {table}
        WHERE cache_key = %s
    c                   s    fdd|D }|D ]}  | qt j}t| j j}t|  }|	 j
j|t|d| W d    d S 1 sCw   Y  d S )Nc                   s   g | ]	} j |d qS rx   ry   rz   r|   r+   r,   
<listcomp>_  s    z*MySQLCache.delete_many.<locals>.<listcomp>r~   )rh   r   r   r9   r   rj   rk   r8   rl   rm   _delete_many_queryro   r   )r*   rv   rc   r   r`   rr   r   rl   r+   r|   r,   delete_many^  s   "zMySQLCache.delete_manyzG
        DELETE FROM {table}
        WHERE cache_key IN {list_sql}
    c                 C  s   | j ||d}| | t| j}t| j| j}t| 	 }|
| jj|d||  f | d uW  d    S 1 sAw   Y  d S re   )rg   rh   r   ri   r9   r   rj   rk   r8   rl   rm   _has_key_queryro   rP   rp   r   r+   r+   r,   has_keyu  s   

$zMySQLCache.has_keyzQ
        SELECT 1 FROM {table}
        WHERE cache_key = %s and expires > %s
    deltac                 C     |  |||dS )N+_base_deltar*   r`   r   rc   r+   r+   r,   incr     zMySQLCache.incrc                 C  r   )N-r   r   r+   r+   r,   decr  r   zMySQLCache.decr	operationLiteral['+', '-']c           	      C  s   | j ||d}| | t| j}t| j| j}t| 	 !}|
| jj||d||f}|s8td| |jW  d    S 1 sEw   Y  d S )Nrf   )r   r   z%Key '%s' not found, or not an integer)rg   rh   r   r   r9   r   rj   rk   r8   rl   rm   _delta_queryro   r^   r   )	r*   r`   r   rc   r   rr   r   rl   updatedr+   r+   r,   r     s   
$zMySQLCache._base_deltaz
        UPDATE {table}
        SET value = LAST_INSERT_ID(
            CAST(value AS SIGNED INTEGER)
            {operation}
            %s
        )
        WHERE cache_key = %s AND
              value_type = 'i'
    c                 C  s`   t | j}t| j| j}t|  }|d|  W d    d S 1 s)w   Y  d S )NDELETE FROM )	r   r   r9   r   rj   rk   r8   rl   rm   )r*   rr   r   rl   r+   r+   r,   clear  s
   "zMySQLCache.clearc           	      C  s   | j ||d}| | | |}t| j}t| j| j	}t| 
 }|| jj|d|||  g}W d    |dkS 1 sDw   Y  |dkS )Nrf   r6   r   )rg   rh   r   r   r   r9   r   rj   rk   r8   rl   rm   _touch_queryro   rP   )	r*   r`   r   rc   r   rr   r   rl   affected_rowsr+   r+   r,   touch  s   


zMySQLCache.touchzr
        UPDATE {table}
        SET expires = %s
        WHERE cache_key = %s AND
              expires >= %s
    c                   s&   t |dkrtd| t |S )zU
        Django normally warns about maximum key length, but we error on it.
           z6Cache key is longer than the maxmimum 250 characters: )lenr^   r7   rh   )r*   r`   r:   r+   r,   rh     s
   zMySQLCache.validate_keyobj#tuple[int | bytes, _EncodedKeyType]c                 C  sR   |  |r	|dfS t|tj}d}| jr%t|| jkr%t|| j}d}||fS )z
        Take a Python object and return it as a tuple (value, value_type), a
        blob and a one-char code for what type it is
        r   r   r   )	_is_valid_mysql_bigintpickledumpsHIGHEST_PROTOCOLrY   r   zlibcompressrZ   )r*   r   rt   ru   r+   r+   r,   r     s   
zMySQLCache.encodeint | bytesc                 C  s$   t |tu ot|  kotkS   S N)typerF   BIGINT_SIGNED_MINBIGINT_SIGNED_MAX)r*   rt   r+   r+   r,   r     s
   z!MySQLCache._is_valid_mysql_bigintbytesru   _EncodedKeyTypec                 C  sR   |dkrt |S |dkrt|}d}nt|}|dkr!t|S td|d)zs
        Take a value blob and its value_type one-char code and convert it back
        to a python object
        r   r   r   zUnknown value_type z read from the cache table.)rF   r   
decompressr   r   loadsr^   )r*   rt   ru   	raw_valuer+   r+   r,   rq     s   


zMySQLCache.decodec                 C  s&   | j rt | j kr|   d S d S d S r   )r[   r   cull)r*   r+   r+   r,   r   	  s   zMySQLCache._maybe_cullc                   s&   |d u r| j S t |}t|d S rN   )FOREVER_TIMEOUTr7   r   rF   )r*   r   r:   r+   r,   r     s   zMySQLCache.get_backend_timeoutprefixbuiltins.set[str]c                 C  s   | j d u r	td|d u r| j}t| j}t| j| j	}| j
|d |d}t|  8}|dj|d||  f | }dd |D }i }|D ]}	|  |	\}
}}|||
< qLt|W  d    S 1 siw   Y  d S )NsTo use the _with_prefix commands with a custom KEY_FUNCTION, you need to specify a custom REVERSE_KEY_FUNCTION too.%rf   zsSELECT cache_key FROM {table}
                   WHERE cache_key LIKE %s AND
                         expires >= %sr6   c                 S  s   h | ]}|d  qS )r   r+   )r{   rs   r+   r+   r,   	<setcomp>1  s    z.MySQLCache.keys_with_prefix.<locals>.<setcomp>)rH   r^   rc   r   ri   r9   r   rj   rk   r8   rg   rl   rm   ro   rP   r   r   )r*   r   rc   rr   r   rl   r   	full_keysrv   r>   r`   r]   key_versionr+   r+   r,   keys_with_prefix  s2   


$zMySQLCache.keys_with_prefixc                 C  s   | j d u r	td|d u r| j}t| j}t| j| j	}| j
|d |d}t|  6}|dj|d||  f | }i }|D ]\}}	}
|  |\}}}| |	|
||< qE|W  d    S 1 sgw   Y  d S )Nr   r   rf   zSELECT cache_key, value, value_type
                   FROM {table}
                   WHERE cache_key LIKE %s AND
                         expires >= %sr6   )rH   r^   rc   r   ri   r9   r   rj   rk   r8   rg   rl   rm   ro   rP   r   rq   )r*   r   rc   rr   r   rl   r   r   r   rt   ru   r`   r]   r   r+   r+   r,   get_with_prefix9  s0   

	$zMySQLCache.get_with_prefixc                 C  s   |d u r| j }t| j}t| j| j}| j|d |d}t| 	 }|
dj|d|fW  d    S 1 s;w   Y  d S )Nr   rf   z>DELETE FROM {table}
                   WHERE cache_key LIKE %sr6   )rc   r   r   r9   r   rj   rk   r8   rg   rl   rm   ro   )r*   r   rc   rr   r   rl   r+   r+   r,   delete_with_prefix]  s   $zMySQLCache.delete_with_prefixc                 C  s&  t | j}t| j| j}t|  t}|d| d| 	 f}| j
dkr1	 W d    dS |d|  | d }|| j
k rM|W  d    S | jdkr]||d| 7 }n#|| j }|dj|d|f | d }||dj|d|f7 }|W  d    S 1 sw   Y  d S )	Nr   z WHERE expires < %sr   zSELECT COUNT(*) FROM zpSELECT cache_key FROM {table}
                       ORDER BY cache_key
                       LIMIT 1 OFFSET %sr6   z?DELETE FROM {table}
                       WHERE cache_key < %s)r   r   r9   r   rj   rk   r8   rl   rm   rP   _max_entriesrp   _cull_frequencyro   )r*   rr   r   rl   num_deletednumcull_nummax_keyr+   r+   r,   r   o  sF   




$zMySQLCache.cull)r   rF   r<   )NN)r`   r   ra   rb   rc   rd   r   r   r   )rv   rw   rc   rd   r   r4   )
r`   r   rt   r   r   r   rc   rd   r   r   )
r`   r   rt   r   r   r   rc   rd   r   r   )
r   r   r`   r   rt   r   r   r   r   r   )r   r4   r   r   rc   rd   r   r   )r`   r   rc   rd   r   r   )rv   rw   rc   rd   r   r   )r`   r   rc   rd   r   r   )rA   N)r`   r   r   rF   rc   rd   r   rF   )
r`   r   r   rF   rc   rd   r   r   r   rF   )r   r   )r`   r   r   r   rc   rd   r   r   )r`   r   r   r   )r   r   r   r   )rt   r   r   r   )rt   r   ru   r   r   r   )r   r   r   rF   )r   r   rc   rd   r   r   )r   r   rc   rd   r   r4   )r   r   rc   rd   r   rF   )1r.   r/   r0   BIGINT_UNSIGNED_MAXr   r   create_table_sqlclassmethodrP   __annotations__r-   rX   r   rn   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rh   r   r   rq   r   r   r   r   r   r   r=   r+   r+   r:   r,   rM   k   s   
 



	



	
	$$rM   )r>   r   r   r?   )rH   rI   r   rJ   )*
__future__r   builtinsr   rer   r   textwrapr   r   typingr   r   r   r	   r
   r   django.core.cache.backends.baser   r   r   	django.dbr   r   django.utils.encodingr   django.utils.module_loadingr   django_mysql.utilsr   r   r   r   r   r   r   r2   compilerC   rG   rL   rM   r+   r+   r+   r,   <module>   sB    	


