base.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. """
  2. SQLite3 backend for the sqlite3 module in the standard library.
  3. """
  4. import decimal
  5. import re
  6. import warnings
  7. from sqlite3 import dbapi2 as Database
  8. import pytz
  9. from django.core.exceptions import ImproperlyConfigured
  10. from django.db import utils
  11. from django.db.backends import utils as backend_utils
  12. from django.db.backends.base.base import BaseDatabaseWrapper
  13. from django.utils import timezone
  14. from django.utils.dateparse import (
  15. parse_date, parse_datetime, parse_duration, parse_time,
  16. )
  17. from .client import DatabaseClient # isort:skip
  18. from .creation import DatabaseCreation # isort:skip
  19. from .features import DatabaseFeatures # isort:skip
  20. from .introspection import DatabaseIntrospection # isort:skip
  21. from .operations import DatabaseOperations # isort:skip
  22. from .schema import DatabaseSchemaEditor # isort:skip
  23. def decoder(conv_func):
  24. """
  25. Convert bytestrings from Python's sqlite3 interface to a regular string.
  26. """
  27. return lambda s: conv_func(s.decode())
  28. Database.register_converter("bool", decoder(lambda s: s == '1'))
  29. Database.register_converter("time", decoder(parse_time))
  30. Database.register_converter("date", decoder(parse_date))
  31. Database.register_converter("datetime", decoder(parse_datetime))
  32. Database.register_converter("timestamp", decoder(parse_datetime))
  33. Database.register_converter("TIMESTAMP", decoder(parse_datetime))
  34. Database.register_converter("decimal", decoder(backend_utils.typecast_decimal))
  35. Database.register_adapter(decimal.Decimal, backend_utils.rev_typecast_decimal)
  36. class DatabaseWrapper(BaseDatabaseWrapper):
  37. vendor = 'sqlite'
  38. # SQLite doesn't actually support most of these types, but it "does the right
  39. # thing" given more verbose field definitions, so leave them as is so that
  40. # schema inspection is more useful.
  41. data_types = {
  42. 'AutoField': 'integer',
  43. 'BigAutoField': 'integer',
  44. 'BinaryField': 'BLOB',
  45. 'BooleanField': 'bool',
  46. 'CharField': 'varchar(%(max_length)s)',
  47. 'DateField': 'date',
  48. 'DateTimeField': 'datetime',
  49. 'DecimalField': 'decimal',
  50. 'DurationField': 'bigint',
  51. 'FileField': 'varchar(%(max_length)s)',
  52. 'FilePathField': 'varchar(%(max_length)s)',
  53. 'FloatField': 'real',
  54. 'IntegerField': 'integer',
  55. 'BigIntegerField': 'bigint',
  56. 'IPAddressField': 'char(15)',
  57. 'GenericIPAddressField': 'char(39)',
  58. 'NullBooleanField': 'bool',
  59. 'OneToOneField': 'integer',
  60. 'PositiveIntegerField': 'integer unsigned',
  61. 'PositiveSmallIntegerField': 'smallint unsigned',
  62. 'SlugField': 'varchar(%(max_length)s)',
  63. 'SmallIntegerField': 'smallint',
  64. 'TextField': 'text',
  65. 'TimeField': 'time',
  66. 'UUIDField': 'char(32)',
  67. }
  68. data_types_suffix = {
  69. 'AutoField': 'AUTOINCREMENT',
  70. 'BigAutoField': 'AUTOINCREMENT',
  71. }
  72. # SQLite requires LIKE statements to include an ESCAPE clause if the value
  73. # being escaped has a percent or underscore in it.
  74. # See http://www.sqlite.org/lang_expr.html for an explanation.
  75. operators = {
  76. 'exact': '= %s',
  77. 'iexact': "LIKE %s ESCAPE '\\'",
  78. 'contains': "LIKE %s ESCAPE '\\'",
  79. 'icontains': "LIKE %s ESCAPE '\\'",
  80. 'regex': 'REGEXP %s',
  81. 'iregex': "REGEXP '(?i)' || %s",
  82. 'gt': '> %s',
  83. 'gte': '>= %s',
  84. 'lt': '< %s',
  85. 'lte': '<= %s',
  86. 'startswith': "LIKE %s ESCAPE '\\'",
  87. 'endswith': "LIKE %s ESCAPE '\\'",
  88. 'istartswith': "LIKE %s ESCAPE '\\'",
  89. 'iendswith': "LIKE %s ESCAPE '\\'",
  90. }
  91. # The patterns below are used to generate SQL pattern lookup clauses when
  92. # the right-hand side of the lookup isn't a raw string (it might be an expression
  93. # or the result of a bilateral transformation).
  94. # In those cases, special characters for LIKE operators (e.g. \, *, _) should be
  95. # escaped on database side.
  96. #
  97. # Note: we use str.format() here for readability as '%' is used as a wildcard for
  98. # the LIKE operator.
  99. pattern_esc = r"REPLACE(REPLACE(REPLACE({}, '\', '\\'), '%%', '\%%'), '_', '\_')"
  100. pattern_ops = {
  101. 'contains': r"LIKE '%%' || {} || '%%' ESCAPE '\'",
  102. 'icontains': r"LIKE '%%' || UPPER({}) || '%%' ESCAPE '\'",
  103. 'startswith': r"LIKE {} || '%%' ESCAPE '\'",
  104. 'istartswith': r"LIKE UPPER({}) || '%%' ESCAPE '\'",
  105. 'endswith': r"LIKE '%%' || {} ESCAPE '\'",
  106. 'iendswith': r"LIKE '%%' || UPPER({}) ESCAPE '\'",
  107. }
  108. Database = Database
  109. SchemaEditorClass = DatabaseSchemaEditor
  110. # Classes instantiated in __init__().
  111. client_class = DatabaseClient
  112. creation_class = DatabaseCreation
  113. features_class = DatabaseFeatures
  114. introspection_class = DatabaseIntrospection
  115. ops_class = DatabaseOperations
  116. def get_connection_params(self):
  117. settings_dict = self.settings_dict
  118. if not settings_dict['NAME']:
  119. raise ImproperlyConfigured(
  120. "settings.DATABASES is improperly configured. "
  121. "Please supply the NAME value.")
  122. kwargs = {
  123. 'database': settings_dict['NAME'],
  124. 'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES,
  125. }
  126. kwargs.update(settings_dict['OPTIONS'])
  127. # Always allow the underlying SQLite connection to be shareable
  128. # between multiple threads. The safe-guarding will be handled at a
  129. # higher level by the `BaseDatabaseWrapper.allow_thread_sharing`
  130. # property. This is necessary as the shareability is disabled by
  131. # default in pysqlite and it cannot be changed once a connection is
  132. # opened.
  133. if 'check_same_thread' in kwargs and kwargs['check_same_thread']:
  134. warnings.warn(
  135. 'The `check_same_thread` option was provided and set to '
  136. 'True. It will be overridden with False. Use the '
  137. '`DatabaseWrapper.allow_thread_sharing` property instead '
  138. 'for controlling thread shareability.',
  139. RuntimeWarning
  140. )
  141. kwargs.update({'check_same_thread': False})
  142. if self.features.can_share_in_memory_db:
  143. kwargs.update({'uri': True})
  144. return kwargs
  145. def get_new_connection(self, conn_params):
  146. conn = Database.connect(**conn_params)
  147. conn.create_function("django_date_extract", 2, _sqlite_date_extract)
  148. conn.create_function("django_date_trunc", 2, _sqlite_date_trunc)
  149. conn.create_function("django_datetime_cast_date", 2, _sqlite_datetime_cast_date)
  150. conn.create_function("django_datetime_cast_time", 2, _sqlite_datetime_cast_time)
  151. conn.create_function("django_datetime_extract", 3, _sqlite_datetime_extract)
  152. conn.create_function("django_datetime_trunc", 3, _sqlite_datetime_trunc)
  153. conn.create_function("django_time_extract", 2, _sqlite_time_extract)
  154. conn.create_function("django_time_trunc", 2, _sqlite_time_trunc)
  155. conn.create_function("django_time_diff", 2, _sqlite_time_diff)
  156. conn.create_function("django_timestamp_diff", 2, _sqlite_timestamp_diff)
  157. conn.create_function("regexp", 2, _sqlite_regexp)
  158. conn.create_function("django_format_dtdelta", 3, _sqlite_format_dtdelta)
  159. conn.create_function("django_power", 2, _sqlite_power)
  160. return conn
  161. def init_connection_state(self):
  162. pass
  163. def create_cursor(self, name=None):
  164. return self.connection.cursor(factory=SQLiteCursorWrapper)
  165. def close(self):
  166. self.validate_thread_sharing()
  167. # If database is in memory, closing the connection destroys the
  168. # database. To prevent accidental data loss, ignore close requests on
  169. # an in-memory db.
  170. if not self.is_in_memory_db():
  171. BaseDatabaseWrapper.close(self)
  172. def _savepoint_allowed(self):
  173. # Two conditions are required here:
  174. # - A sufficiently recent version of SQLite to support savepoints,
  175. # - Being in a transaction, which can only happen inside 'atomic'.
  176. # When 'isolation_level' is not None, sqlite3 commits before each
  177. # savepoint; it's a bug. When it is None, savepoints don't make sense
  178. # because autocommit is enabled. The only exception is inside 'atomic'
  179. # blocks. To work around that bug, on SQLite, 'atomic' starts a
  180. # transaction explicitly rather than simply disable autocommit.
  181. return self.features.uses_savepoints and self.in_atomic_block
  182. def _set_autocommit(self, autocommit):
  183. if autocommit:
  184. level = None
  185. else:
  186. # sqlite3's internal default is ''. It's different from None.
  187. # See Modules/_sqlite/connection.c.
  188. level = ''
  189. # 'isolation_level' is a misleading API.
  190. # SQLite always runs at the SERIALIZABLE isolation level.
  191. with self.wrap_database_errors:
  192. self.connection.isolation_level = level
  193. def check_constraints(self, table_names=None):
  194. """
  195. Check each table name in `table_names` for rows with invalid foreign
  196. key references. This method is intended to be used in conjunction with
  197. `disable_constraint_checking()` and `enable_constraint_checking()`, to
  198. determine if rows with invalid references were entered while constraint
  199. checks were off.
  200. Raise an IntegrityError on the first invalid foreign key reference
  201. encountered (if any) and provide detailed information about the
  202. invalid reference in the error message.
  203. Backends can override this method if they can more directly apply
  204. constraint checking (e.g. via "SET CONSTRAINTS ALL IMMEDIATE")
  205. """
  206. cursor = self.cursor()
  207. if table_names is None:
  208. table_names = self.introspection.table_names(cursor)
  209. for table_name in table_names:
  210. primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name)
  211. if not primary_key_column_name:
  212. continue
  213. key_columns = self.introspection.get_key_columns(cursor, table_name)
  214. for column_name, referenced_table_name, referenced_column_name in key_columns:
  215. cursor.execute(
  216. """
  217. SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING
  218. LEFT JOIN `%s` as REFERRED
  219. ON (REFERRING.`%s` = REFERRED.`%s`)
  220. WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL
  221. """
  222. % (
  223. primary_key_column_name, column_name, table_name,
  224. referenced_table_name, column_name, referenced_column_name,
  225. column_name, referenced_column_name,
  226. )
  227. )
  228. for bad_row in cursor.fetchall():
  229. raise utils.IntegrityError(
  230. "The row in table '%s' with primary key '%s' has an "
  231. "invalid foreign key: %s.%s contains a value '%s' that "
  232. "does not have a corresponding value in %s.%s." % (
  233. table_name, bad_row[0], table_name, column_name,
  234. bad_row[1], referenced_table_name, referenced_column_name,
  235. )
  236. )
  237. def is_usable(self):
  238. return True
  239. def _start_transaction_under_autocommit(self):
  240. """
  241. Start a transaction explicitly in autocommit mode.
  242. Staying in autocommit mode works around a bug of sqlite3 that breaks
  243. savepoints when autocommit is disabled.
  244. """
  245. self.cursor().execute("BEGIN")
  246. def is_in_memory_db(self):
  247. return self.creation.is_in_memory_db(self.settings_dict['NAME'])
  248. FORMAT_QMARK_REGEX = re.compile(r'(?<!%)%s')
  249. class SQLiteCursorWrapper(Database.Cursor):
  250. """
  251. Django uses "format" style placeholders, but pysqlite2 uses "qmark" style.
  252. This fixes it -- but note that if you want to use a literal "%s" in a query,
  253. you'll need to use "%%s".
  254. """
  255. def execute(self, query, params=None):
  256. if params is None:
  257. return Database.Cursor.execute(self, query)
  258. query = self.convert_query(query)
  259. return Database.Cursor.execute(self, query, params)
  260. def executemany(self, query, param_list):
  261. query = self.convert_query(query)
  262. return Database.Cursor.executemany(self, query, param_list)
  263. def convert_query(self, query):
  264. return FORMAT_QMARK_REGEX.sub('?', query).replace('%%', '%')
  265. def _sqlite_date_extract(lookup_type, dt):
  266. if dt is None:
  267. return None
  268. try:
  269. dt = backend_utils.typecast_timestamp(dt)
  270. except (ValueError, TypeError):
  271. return None
  272. if lookup_type == 'week_day':
  273. return (dt.isoweekday() % 7) + 1
  274. elif lookup_type == 'week':
  275. return dt.isocalendar()[1]
  276. else:
  277. return getattr(dt, lookup_type)
  278. def _sqlite_date_trunc(lookup_type, dt):
  279. try:
  280. dt = backend_utils.typecast_timestamp(dt)
  281. except (ValueError, TypeError):
  282. return None
  283. if lookup_type == 'year':
  284. return "%i-01-01" % dt.year
  285. elif lookup_type == 'month':
  286. return "%i-%02i-01" % (dt.year, dt.month)
  287. elif lookup_type == 'day':
  288. return "%i-%02i-%02i" % (dt.year, dt.month, dt.day)
  289. def _sqlite_time_trunc(lookup_type, dt):
  290. try:
  291. dt = backend_utils.typecast_time(dt)
  292. except (ValueError, TypeError):
  293. return None
  294. if lookup_type == 'hour':
  295. return "%02i:00:00" % dt.hour
  296. elif lookup_type == 'minute':
  297. return "%02i:%02i:00" % (dt.hour, dt.minute)
  298. elif lookup_type == 'second':
  299. return "%02i:%02i:%02i" % (dt.hour, dt.minute, dt.second)
  300. def _sqlite_datetime_parse(dt, tzname):
  301. if dt is None:
  302. return None
  303. try:
  304. dt = backend_utils.typecast_timestamp(dt)
  305. except (ValueError, TypeError):
  306. return None
  307. if tzname is not None:
  308. dt = timezone.localtime(dt, pytz.timezone(tzname))
  309. return dt
  310. def _sqlite_datetime_cast_date(dt, tzname):
  311. dt = _sqlite_datetime_parse(dt, tzname)
  312. if dt is None:
  313. return None
  314. return dt.date().isoformat()
  315. def _sqlite_datetime_cast_time(dt, tzname):
  316. dt = _sqlite_datetime_parse(dt, tzname)
  317. if dt is None:
  318. return None
  319. return dt.time().isoformat()
  320. def _sqlite_datetime_extract(lookup_type, dt, tzname):
  321. dt = _sqlite_datetime_parse(dt, tzname)
  322. if dt is None:
  323. return None
  324. if lookup_type == 'week_day':
  325. return (dt.isoweekday() % 7) + 1
  326. elif lookup_type == 'week':
  327. return dt.isocalendar()[1]
  328. else:
  329. return getattr(dt, lookup_type)
  330. def _sqlite_datetime_trunc(lookup_type, dt, tzname):
  331. dt = _sqlite_datetime_parse(dt, tzname)
  332. if dt is None:
  333. return None
  334. if lookup_type == 'year':
  335. return "%i-01-01 00:00:00" % dt.year
  336. elif lookup_type == 'month':
  337. return "%i-%02i-01 00:00:00" % (dt.year, dt.month)
  338. elif lookup_type == 'day':
  339. return "%i-%02i-%02i 00:00:00" % (dt.year, dt.month, dt.day)
  340. elif lookup_type == 'hour':
  341. return "%i-%02i-%02i %02i:00:00" % (dt.year, dt.month, dt.day, dt.hour)
  342. elif lookup_type == 'minute':
  343. return "%i-%02i-%02i %02i:%02i:00" % (dt.year, dt.month, dt.day, dt.hour, dt.minute)
  344. elif lookup_type == 'second':
  345. return "%i-%02i-%02i %02i:%02i:%02i" % (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
  346. def _sqlite_time_extract(lookup_type, dt):
  347. if dt is None:
  348. return None
  349. try:
  350. dt = backend_utils.typecast_time(dt)
  351. except (ValueError, TypeError):
  352. return None
  353. return getattr(dt, lookup_type)
  354. def _sqlite_format_dtdelta(conn, lhs, rhs):
  355. """
  356. LHS and RHS can be either:
  357. - An integer number of microseconds
  358. - A string representing a timedelta object
  359. - A string representing a datetime
  360. """
  361. try:
  362. if isinstance(lhs, int):
  363. lhs = str(decimal.Decimal(lhs) / decimal.Decimal(1000000))
  364. real_lhs = parse_duration(lhs)
  365. if real_lhs is None:
  366. real_lhs = backend_utils.typecast_timestamp(lhs)
  367. if isinstance(rhs, int):
  368. rhs = str(decimal.Decimal(rhs) / decimal.Decimal(1000000))
  369. real_rhs = parse_duration(rhs)
  370. if real_rhs is None:
  371. real_rhs = backend_utils.typecast_timestamp(rhs)
  372. if conn.strip() == '+':
  373. out = real_lhs + real_rhs
  374. else:
  375. out = real_lhs - real_rhs
  376. except (ValueError, TypeError):
  377. return None
  378. # typecast_timestamp returns a date or a datetime without timezone.
  379. # It will be formatted as "%Y-%m-%d" or "%Y-%m-%d %H:%M:%S[.%f]"
  380. return str(out)
  381. def _sqlite_time_diff(lhs, rhs):
  382. left = backend_utils.typecast_time(lhs)
  383. right = backend_utils.typecast_time(rhs)
  384. return (
  385. (left.hour * 60 * 60 * 1000000) +
  386. (left.minute * 60 * 1000000) +
  387. (left.second * 1000000) +
  388. (left.microsecond) -
  389. (right.hour * 60 * 60 * 1000000) -
  390. (right.minute * 60 * 1000000) -
  391. (right.second * 1000000) -
  392. (right.microsecond)
  393. )
  394. def _sqlite_timestamp_diff(lhs, rhs):
  395. left = backend_utils.typecast_timestamp(lhs)
  396. right = backend_utils.typecast_timestamp(rhs)
  397. return (left - right).total_seconds() * 1000000
  398. def _sqlite_regexp(re_pattern, re_string):
  399. return bool(re.search(re_pattern, str(re_string))) if re_string is not None else False
  400. def _sqlite_power(x, y):
  401. return x ** y