You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

base.py 18 KiB

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