66import zlib
77from collections .abc import Iterable
88from random import random
9- from textwrap import dedent
109from time import time
1110from typing import Any , Callable , Literal , cast
1211
1514from django .utils .encoding import force_bytes
1615from django .utils .module_loading import import_string
1716
18- from django_mysql .utils import collapse_spaces , get_list_sql
17+ from django_mysql .utils import get_list_sql
1918
2019_EncodedKeyType = Literal ["i" , "p" , "z" ]
2120
@@ -102,18 +101,18 @@ class MySQLCache(BaseDatabaseCache):
102101 # 1970)
103102 FOREVER_TIMEOUT = BIGINT_UNSIGNED_MAX >> 1
104103
105- create_table_sql = dedent (
106- """\
107- CREATE TABLE `{table_name}` (
108- cache_key varchar(255) CHARACTER SET utf8 COLLATE utf8_bin
109- NOT NULL PRIMARY KEY,
110- value longblob NOT NULL,
111- value_type char(1) CHARACTER SET latin1 COLLATE latin1_bin
112- NOT NULL DEFAULT 'p',
113- expires BIGINT UNSIGNED NOT NULL
114- );
115- """
104+ # fmt: off
105+ create_table_sql = (
106+ "CREATE TABLE `{table_name}` (\n "
107+ " cache_key varchar(255) CHARACTER SET utf8 COLLATE utf8_bin\n "
108+ " NOT NULL PRIMARY KEY,\n "
109+ " value longblob NOT NULL,\n "
110+ " value_type char(1) CHARACTER SET latin1 COLLATE latin1_bin\n "
111+ " NOT NULL DEFAULT 'p',\n "
112+ " expires BIGINT UNSIGNED NOT NULL\n "
113+ ");\n "
116114 )
115+ # fmt: on
117116
118117 @classmethod
119118 def _now (cls ) -> int :
@@ -162,14 +161,14 @@ def get(
162161 value , value_type = row
163162 return self .decode (value , value_type )
164163
165- _get_query = collapse_spaces (
166- """
167- SELECT value, value_type
168- FROM {table}
169- WHERE cache_key = %s AND
170- expires >= %s
171- """
164+ # fmt: off
165+ _get_query = (
166+ "SELECT value, value_type "
167+ "FROM {table} "
168+ "WHERE cache_key = %s AND "
169+ "expires >= %s"
172170 )
171+ # fmt: on
173172
174173 def get_many (
175174 self , keys : Iterable [str ], version : int | None = None
@@ -199,14 +198,14 @@ def get_many(
199198
200199 return data
201200
202- _get_many_query = collapse_spaces (
203- """
204- SELECT cache_key, value, value_type
205- FROM {table}
206- WHERE cache_key IN {list_sql} AND
207- expires >= %s
208- """
201+ # fmt: off
202+ _get_many_query = (
203+ "SELECT cache_key, value, value_type "
204+ "FROM {table} "
205+ "WHERE cache_key IN {list_sql} AND "
206+ "expires >= %s"
209207 )
208+ # fmt: on
210209
211210 def set (
212211 self ,
@@ -261,39 +260,39 @@ def _base_set(
261260 insert_id = cursor .lastrowid
262261 return insert_id != 444
263262
264- _set_many_query = collapse_spaces (
265- """
266- INSERT INTO {table} (cache_key, value, value_type, expires)
267- VALUES {{VALUES_CLAUSE}}
268- ON DUPLICATE KEY UPDATE
269- value=VALUES(value),
270- value_type=VALUES(value_type),
271- expires=VALUES(expires)
272- """
263+ # fmt: off
264+ _set_many_query = (
265+ "INSERT INTO {table} (cache_key, value, value_type, expires) "
266+ "VALUES {{VALUES_CLAUSE}} "
267+ "ON DUPLICATE KEY UPDATE "
268+ "value=VALUES(value), "
269+ "value_type=VALUES(value_type), "
270+ "expires=VALUES(expires)"
273271 )
272+ # fmt: on
274273
275274 _set_query = _set_many_query .replace ("{{VALUES_CLAUSE}}" , "(%s, %s, %s, %s)" )
276275
277276 # Uses the IFNULL / LEAST / LAST_INSERT_ID trick to communicate the special
278277 # value of 444 back to the client (LAST_INSERT_ID is otherwise 0, since
279278 # there is no AUTO_INCREMENT column)
280- _add_query = collapse_spaces (
281- """
282- INSERT INTO {table} (cache_key, value, value_type, expires)
283- VALUES (%s, %s, %s, %s)
284- ON DUPLICATE KEY UPDATE
285- value=IF(expires > @tmp_now:=%s, value, VALUES(value)),
286- value_type=IF(expires > @tmp_now, value_type, VALUES(value_type)),
287- expires=IF(
288- expires > @tmp_now,
289- IFNULL(
290- LEAST(LAST_INSERT_ID(444), NULL),
291- expires
292- ),
293- VALUES(expires)
294- )
295- """
279+ # fmt: off
280+ _add_query = (
281+ "INSERT INTO {table} (cache_key, value, value_type, expires) "
282+ "VALUES (%s, %s, %s, %s) "
283+ "ON DUPLICATE KEY UPDATE "
284+ "value=IF(expires > @tmp_now:=%s, value, VALUES(value)), "
285+ "value_type=IF(expires > @tmp_now, value_type, VALUES(value_type)), "
286+ "expires=IF("
287+ "expires > @tmp_now, "
288+ "IFNULL("
289+ "LEAST(LAST_INSERT_ID(444), NULL), "
290+ "expires"
291+ "), "
292+ "VALUES(expires)"
293+ ")"
296294 )
295+ # fmt: on
297296
298297 def set_many (
299298 self ,
@@ -332,12 +331,12 @@ def delete(self, key: str, version: int | None = None) -> None:
332331 with connections [db ].cursor () as cursor :
333332 cursor .execute (self ._delete_query .format (table = table ), (key ,))
334333
335- _delete_query = collapse_spaces (
336- """
337- DELETE FROM {table}
338- WHERE cache_key = %s
339- """
334+ # fmt: off
335+ _delete_query = (
336+ "DELETE FROM {table} "
337+ "WHERE cache_key = %s"
340338 )
339+ # fmt: on
341340
342341 def delete_many (self , keys : Iterable [str ], version : int | None = None ) -> None :
343342 made_keys = [self .make_key (key , version = version ) for key in keys ]
@@ -355,12 +354,12 @@ def delete_many(self, keys: Iterable[str], version: int | None = None) -> None:
355354 made_keys ,
356355 )
357356
358- _delete_many_query = collapse_spaces (
359- """
360- DELETE FROM {table}
361- WHERE cache_key IN {list_sql}
362- """
357+ # fmt: off
358+ _delete_many_query = (
359+ "DELETE FROM {table} "
360+ "WHERE cache_key IN {list_sql}"
363361 )
362+ # fmt: on
364363
365364 def has_key (self , key : str , version : int | None = None ) -> bool :
366365 key = self .make_key (key , version = version )
@@ -373,12 +372,12 @@ def has_key(self, key: str, version: int | None = None) -> bool:
373372 cursor .execute (self ._has_key_query .format (table = table ), (key , self ._now ()))
374373 return cursor .fetchone () is not None
375374
376- _has_key_query = collapse_spaces (
377- """
378- SELECT 1 FROM {table}
379- WHERE cache_key = %s and expires > %s
380- """
375+ # fmt: off
376+ _has_key_query = (
377+ "SELECT 1 FROM {table} "
378+ "WHERE cache_key = %s and expires > %s"
381379 )
380+ # fmt: on
382381
383382 def incr (self , key : str , delta : int = 1 , version : int | None = None ) -> int :
384383 return self ._base_delta (key , delta , version , "+" )
@@ -412,18 +411,18 @@ def _base_delta(
412411
413412 # Looks a bit tangled to turn the blob back into an int for updating, but
414413 # it works. Stores the new value for insert_id() with LAST_INSERT_ID
415- _delta_query = collapse_spaces (
416- """
417- UPDATE {table}
418- SET value = LAST_INSERT_ID(
419- CAST(value AS SIGNED INTEGER)
420- {operation}
421- %s
422- )
423- WHERE cache_key = %s AND
424- value_type = 'i'
425- """
414+ # fmt: off
415+ _delta_query = (
416+ "UPDATE {table} "
417+ "SET value = LAST_INSERT_ID("
418+ "CAST(value AS SIGNED INTEGER) "
419+ "{operation} "
420+ "%s"
421+ ") "
422+ "WHERE cache_key = %s AND "
423+ "value_type = 'i'"
426424 )
425+ # fmt: on
427426
428427 def clear (self ) -> None :
429428 db = router .db_for_write (self .cache_model_class )
@@ -445,14 +444,14 @@ def touch(
445444 )
446445 return affected_rows > 0
447446
448- _touch_query = collapse_spaces (
449- """
450- UPDATE {table}
451- SET expires = %s
452- WHERE cache_key = %s AND
453- expires >= %s
454- """
447+ # fmt: off
448+ _touch_query = (
449+ "UPDATE {table} "
450+ "SET expires = %s "
451+ "WHERE cache_key = %s AND "
452+ "expires >= %s"
455453 )
454+ # fmt: on
456455
457456 def validate_key (self , key : str ) -> None :
458457 """
0 commit comments