base.py 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. """
  2. Oracle database backend for Django.
  3. Requires cx_Oracle: http://cx-oracle.sourceforge.net/
  4. """
  5. from __future__ import unicode_literals
  6. import datetime
  7. import decimal
  8. import re
  9. import platform
  10. import sys
  11. import warnings
  12. def _setup_environment(environ):
  13. # Cygwin requires some special voodoo to set the environment variables
  14. # properly so that Oracle will see them.
  15. if platform.system().upper().startswith('CYGWIN'):
  16. try:
  17. import ctypes
  18. except ImportError as e:
  19. from django.core.exceptions import ImproperlyConfigured
  20. raise ImproperlyConfigured("Error loading ctypes: %s; "
  21. "the Oracle backend requires ctypes to "
  22. "operate correctly under Cygwin." % e)
  23. kernel32 = ctypes.CDLL('kernel32')
  24. for name, value in environ:
  25. kernel32.SetEnvironmentVariableA(name, value)
  26. else:
  27. import os
  28. os.environ.update(environ)
  29. _setup_environment([
  30. # Oracle takes client-side character set encoding from the environment.
  31. ('NLS_LANG', '.UTF8'),
  32. # This prevents unicode from getting mangled by getting encoded into the
  33. # potentially non-unicode database character set.
  34. ('ORA_NCHAR_LITERAL_REPLACE', 'TRUE'),
  35. ])
  36. try:
  37. import cx_Oracle as Database
  38. except ImportError as e:
  39. from django.core.exceptions import ImproperlyConfigured
  40. raise ImproperlyConfigured("Error loading cx_Oracle module: %s" % e)
  41. try:
  42. import pytz
  43. except ImportError:
  44. pytz = None
  45. from django.conf import settings
  46. from django.db import utils
  47. from django.db.backends import (BaseDatabaseFeatures, BaseDatabaseOperations,
  48. BaseDatabaseWrapper, BaseDatabaseValidation, utils as backend_utils)
  49. from django.db.backends.oracle.client import DatabaseClient
  50. from django.db.backends.oracle.creation import DatabaseCreation
  51. from django.db.backends.oracle.introspection import DatabaseIntrospection
  52. from django.db.backends.oracle.schema import DatabaseSchemaEditor
  53. from django.db.utils import InterfaceError
  54. from django.utils import six, timezone
  55. from django.utils.encoding import force_bytes, force_text
  56. from django.utils.functional import cached_property
  57. DatabaseError = Database.DatabaseError
  58. IntegrityError = Database.IntegrityError
  59. # Check whether cx_Oracle was compiled with the WITH_UNICODE option if cx_Oracle is pre-5.1. This will
  60. # also be True for cx_Oracle 5.1 and in Python 3.0. See #19606
  61. if int(Database.version.split('.', 1)[0]) >= 5 and \
  62. (int(Database.version.split('.', 2)[1]) >= 1 or
  63. not hasattr(Database, 'UNICODE')):
  64. convert_unicode = force_text
  65. else:
  66. convert_unicode = force_bytes
  67. class Oracle_datetime(datetime.datetime):
  68. """
  69. A datetime object, with an additional class attribute
  70. to tell cx_Oracle to save the microseconds too.
  71. """
  72. input_size = Database.TIMESTAMP
  73. @classmethod
  74. def from_datetime(cls, dt):
  75. return Oracle_datetime(dt.year, dt.month, dt.day,
  76. dt.hour, dt.minute, dt.second, dt.microsecond)
  77. class DatabaseFeatures(BaseDatabaseFeatures):
  78. empty_fetchmany_value = ()
  79. needs_datetime_string_cast = False
  80. interprets_empty_strings_as_nulls = True
  81. uses_savepoints = True
  82. has_select_for_update = True
  83. has_select_for_update_nowait = True
  84. can_return_id_from_insert = True
  85. allow_sliced_subqueries = False
  86. supports_subqueries_in_group_by = False
  87. supports_transactions = True
  88. supports_timezones = False
  89. has_zoneinfo_database = pytz is not None
  90. supports_bitwise_or = False
  91. can_defer_constraint_checks = True
  92. supports_partially_nullable_unique_constraints = False
  93. has_bulk_insert = True
  94. supports_tablespaces = True
  95. supports_sequence_reset = False
  96. can_introspect_max_length = False
  97. can_introspect_time_field = False
  98. atomic_transactions = False
  99. supports_combined_alters = False
  100. nulls_order_largest = True
  101. requires_literal_defaults = True
  102. connection_persists_old_columns = True
  103. closed_cursor_error_class = InterfaceError
  104. bare_select_suffix = " FROM DUAL"
  105. uppercases_column_names = True
  106. # select for update with limit can be achieved on Oracle, but not with the current backend.
  107. supports_select_for_update_with_limit = False
  108. class DatabaseOperations(BaseDatabaseOperations):
  109. compiler_module = "django.db.backends.oracle.compiler"
  110. # Oracle uses NUMBER(11) and NUMBER(19) for integer fields.
  111. integer_field_ranges = {
  112. 'SmallIntegerField': (-99999999999, 99999999999),
  113. 'IntegerField': (-99999999999, 99999999999),
  114. 'BigIntegerField': (-9999999999999999999, 9999999999999999999),
  115. 'PositiveSmallIntegerField': (0, 99999999999),
  116. 'PositiveIntegerField': (0, 99999999999),
  117. }
  118. def autoinc_sql(self, table, column):
  119. # To simulate auto-incrementing primary keys in Oracle, we have to
  120. # create a sequence and a trigger.
  121. sq_name = self._get_sequence_name(table)
  122. tr_name = self._get_trigger_name(table)
  123. tbl_name = self.quote_name(table)
  124. col_name = self.quote_name(column)
  125. sequence_sql = """
  126. DECLARE
  127. i INTEGER;
  128. BEGIN
  129. SELECT COUNT(*) INTO i FROM USER_CATALOG
  130. WHERE TABLE_NAME = '%(sq_name)s' AND TABLE_TYPE = 'SEQUENCE';
  131. IF i = 0 THEN
  132. EXECUTE IMMEDIATE 'CREATE SEQUENCE "%(sq_name)s"';
  133. END IF;
  134. END;
  135. /""" % locals()
  136. trigger_sql = """
  137. CREATE OR REPLACE TRIGGER "%(tr_name)s"
  138. BEFORE INSERT ON %(tbl_name)s
  139. FOR EACH ROW
  140. WHEN (new.%(col_name)s IS NULL)
  141. BEGIN
  142. SELECT "%(sq_name)s".nextval
  143. INTO :new.%(col_name)s FROM dual;
  144. END;
  145. /""" % locals()
  146. return sequence_sql, trigger_sql
  147. def cache_key_culling_sql(self):
  148. return """
  149. SELECT cache_key
  150. FROM (SELECT cache_key, rank() OVER (ORDER BY cache_key) AS rank FROM %s)
  151. WHERE rank = %%s + 1
  152. """
  153. def date_extract_sql(self, lookup_type, field_name):
  154. if lookup_type == 'week_day':
  155. # TO_CHAR(field, 'D') returns an integer from 1-7, where 1=Sunday.
  156. return "TO_CHAR(%s, 'D')" % field_name
  157. else:
  158. # http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions050.htm
  159. return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), field_name)
  160. def date_interval_sql(self, sql, connector, timedelta):
  161. """
  162. Implements the interval functionality for expressions
  163. format for Oracle:
  164. (datefield + INTERVAL '3 00:03:20.000000' DAY(1) TO SECOND(6))
  165. """
  166. minutes, seconds = divmod(timedelta.seconds, 60)
  167. hours, minutes = divmod(minutes, 60)
  168. days = str(timedelta.days)
  169. day_precision = len(days)
  170. fmt = "(%s %s INTERVAL '%s %02d:%02d:%02d.%06d' DAY(%d) TO SECOND(6))"
  171. return fmt % (sql, connector, days, hours, minutes, seconds,
  172. timedelta.microseconds, day_precision)
  173. def date_trunc_sql(self, lookup_type, field_name):
  174. # http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions230.htm#i1002084
  175. if lookup_type in ('year', 'month'):
  176. return "TRUNC(%s, '%s')" % (field_name, lookup_type.upper())
  177. else:
  178. return "TRUNC(%s)" % field_name
  179. # Oracle crashes with "ORA-03113: end-of-file on communication channel"
  180. # if the time zone name is passed in parameter. Use interpolation instead.
  181. # https://groups.google.com/forum/#!msg/django-developers/zwQju7hbG78/9l934yelwfsJ
  182. # This regexp matches all time zone names from the zoneinfo database.
  183. _tzname_re = re.compile(r'^[\w/:+-]+$')
  184. def _convert_field_to_tz(self, field_name, tzname):
  185. if not self._tzname_re.match(tzname):
  186. raise ValueError("Invalid time zone name: %s" % tzname)
  187. # Convert from UTC to local time, returning TIMESTAMP WITH TIME ZONE.
  188. result = "(FROM_TZ(%s, '0:00') AT TIME ZONE '%s')" % (field_name, tzname)
  189. # Extracting from a TIMESTAMP WITH TIME ZONE ignore the time zone.
  190. # Convert to a DATETIME, which is called DATE by Oracle. There's no
  191. # built-in function to do that; the easiest is to go through a string.
  192. result = "TO_CHAR(%s, 'YYYY-MM-DD HH24:MI:SS')" % result
  193. result = "TO_DATE(%s, 'YYYY-MM-DD HH24:MI:SS')" % result
  194. # Re-convert to a TIMESTAMP because EXTRACT only handles the date part
  195. # on DATE values, even though they actually store the time part.
  196. return "CAST(%s AS TIMESTAMP)" % result
  197. def datetime_extract_sql(self, lookup_type, field_name, tzname):
  198. if settings.USE_TZ:
  199. field_name = self._convert_field_to_tz(field_name, tzname)
  200. if lookup_type == 'week_day':
  201. # TO_CHAR(field, 'D') returns an integer from 1-7, where 1=Sunday.
  202. sql = "TO_CHAR(%s, 'D')" % field_name
  203. else:
  204. # http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions050.htm
  205. sql = "EXTRACT(%s FROM %s)" % (lookup_type.upper(), field_name)
  206. return sql, []
  207. def datetime_trunc_sql(self, lookup_type, field_name, tzname):
  208. if settings.USE_TZ:
  209. field_name = self._convert_field_to_tz(field_name, tzname)
  210. # http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions230.htm#i1002084
  211. if lookup_type in ('year', 'month'):
  212. sql = "TRUNC(%s, '%s')" % (field_name, lookup_type.upper())
  213. elif lookup_type == 'day':
  214. sql = "TRUNC(%s)" % field_name
  215. elif lookup_type == 'hour':
  216. sql = "TRUNC(%s, 'HH24')" % field_name
  217. elif lookup_type == 'minute':
  218. sql = "TRUNC(%s, 'MI')" % field_name
  219. else:
  220. sql = field_name # Cast to DATE removes sub-second precision.
  221. return sql, []
  222. def convert_values(self, value, field):
  223. if isinstance(value, Database.LOB):
  224. value = value.read()
  225. if field and field.get_internal_type() == 'TextField':
  226. value = force_text(value)
  227. # Oracle stores empty strings as null. We need to undo this in
  228. # order to adhere to the Django convention of using the empty
  229. # string instead of null, but only if the field accepts the
  230. # empty string.
  231. if value is None and field and field.empty_strings_allowed:
  232. if field.get_internal_type() == 'BinaryField':
  233. value = b''
  234. else:
  235. value = ''
  236. # Convert 1 or 0 to True or False
  237. elif value in (1, 0) and field and field.get_internal_type() in ('BooleanField', 'NullBooleanField'):
  238. value = bool(value)
  239. # Force floats to the correct type
  240. elif value is not None and field and field.get_internal_type() == 'FloatField':
  241. value = float(value)
  242. # Convert floats to decimals
  243. elif value is not None and field and field.get_internal_type() == 'DecimalField':
  244. value = backend_utils.typecast_decimal(field.format_number(value))
  245. # cx_Oracle always returns datetime.datetime objects for
  246. # DATE and TIMESTAMP columns, but Django wants to see a
  247. # python datetime.date, .time, or .datetime. We use the type
  248. # of the Field to determine which to cast to, but it's not
  249. # always available.
  250. # As a workaround, we cast to date if all the time-related
  251. # values are 0, or to time if the date is 1/1/1900.
  252. # This could be cleaned a bit by adding a method to the Field
  253. # classes to normalize values from the database (the to_python
  254. # method is used for validation and isn't what we want here).
  255. elif isinstance(value, Database.Timestamp):
  256. if field and field.get_internal_type() == 'DateTimeField':
  257. pass
  258. elif field and field.get_internal_type() == 'DateField':
  259. value = value.date()
  260. elif field and field.get_internal_type() == 'TimeField' or (value.year == 1900 and value.month == value.day == 1):
  261. value = value.time()
  262. elif value.hour == value.minute == value.second == value.microsecond == 0:
  263. value = value.date()
  264. return value
  265. def deferrable_sql(self):
  266. return " DEFERRABLE INITIALLY DEFERRED"
  267. def drop_sequence_sql(self, table):
  268. return "DROP SEQUENCE %s;" % self.quote_name(self._get_sequence_name(table))
  269. def fetch_returned_insert_id(self, cursor):
  270. return int(cursor._insert_id_var.getvalue())
  271. def field_cast_sql(self, db_type, internal_type):
  272. if db_type and db_type.endswith('LOB'):
  273. return "DBMS_LOB.SUBSTR(%s)"
  274. else:
  275. return "%s"
  276. def last_executed_query(self, cursor, sql, params):
  277. # http://cx-oracle.sourceforge.net/html/cursor.html#Cursor.statement
  278. # The DB API definition does not define this attribute.
  279. statement = cursor.statement
  280. if statement and six.PY2 and not isinstance(statement, unicode):
  281. statement = statement.decode('utf-8')
  282. # Unlike Psycopg's `query` and MySQLdb`'s `_last_executed`, CxOracle's
  283. # `statement` doesn't contain the query parameters. refs #20010.
  284. return super(DatabaseOperations, self).last_executed_query(cursor, statement, params)
  285. def last_insert_id(self, cursor, table_name, pk_name):
  286. sq_name = self._get_sequence_name(table_name)
  287. cursor.execute('SELECT "%s".currval FROM dual' % sq_name)
  288. return cursor.fetchone()[0]
  289. def lookup_cast(self, lookup_type):
  290. if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith'):
  291. return "UPPER(%s)"
  292. return "%s"
  293. def max_in_list_size(self):
  294. return 1000
  295. def max_name_length(self):
  296. return 30
  297. def prep_for_iexact_query(self, x):
  298. return x
  299. def process_clob(self, value):
  300. if value is None:
  301. return ''
  302. return force_text(value.read())
  303. def quote_name(self, name):
  304. # SQL92 requires delimited (quoted) names to be case-sensitive. When
  305. # not quoted, Oracle has case-insensitive behavior for identifiers, but
  306. # always defaults to uppercase.
  307. # We simplify things by making Oracle identifiers always uppercase.
  308. if not name.startswith('"') and not name.endswith('"'):
  309. name = '"%s"' % backend_utils.truncate_name(name.upper(),
  310. self.max_name_length())
  311. # Oracle puts the query text into a (query % args) construct, so % signs
  312. # in names need to be escaped. The '%%' will be collapsed back to '%' at
  313. # that stage so we aren't really making the name longer here.
  314. name = name.replace('%', '%%')
  315. return name.upper()
  316. def random_function_sql(self):
  317. return "DBMS_RANDOM.RANDOM"
  318. def regex_lookup_9(self, lookup_type):
  319. raise NotImplementedError("Regexes are not supported in Oracle before version 10g.")
  320. def regex_lookup_10(self, lookup_type):
  321. if lookup_type == 'regex':
  322. match_option = "'c'"
  323. else:
  324. match_option = "'i'"
  325. return 'REGEXP_LIKE(%%s, %%s, %s)' % match_option
  326. def regex_lookup(self, lookup_type):
  327. # If regex_lookup is called before it's been initialized, then create
  328. # a cursor to initialize it and recur.
  329. with self.connection.cursor():
  330. return self.connection.ops.regex_lookup(lookup_type)
  331. def return_insert_id(self):
  332. return "RETURNING %s INTO %%s", (InsertIdVar(),)
  333. def savepoint_create_sql(self, sid):
  334. return convert_unicode("SAVEPOINT " + self.quote_name(sid))
  335. def savepoint_rollback_sql(self, sid):
  336. return convert_unicode("ROLLBACK TO SAVEPOINT " + self.quote_name(sid))
  337. def sql_flush(self, style, tables, sequences, allow_cascade=False):
  338. # Return a list of 'TRUNCATE x;', 'TRUNCATE y;',
  339. # 'TRUNCATE z;'... style SQL statements
  340. if tables:
  341. # Oracle does support TRUNCATE, but it seems to get us into
  342. # FK referential trouble, whereas DELETE FROM table works.
  343. sql = ['%s %s %s;' % (
  344. style.SQL_KEYWORD('DELETE'),
  345. style.SQL_KEYWORD('FROM'),
  346. style.SQL_FIELD(self.quote_name(table))
  347. ) for table in tables]
  348. # Since we've just deleted all the rows, running our sequence
  349. # ALTER code will reset the sequence to 0.
  350. sql.extend(self.sequence_reset_by_name_sql(style, sequences))
  351. return sql
  352. else:
  353. return []
  354. def sequence_reset_by_name_sql(self, style, sequences):
  355. sql = []
  356. for sequence_info in sequences:
  357. sequence_name = self._get_sequence_name(sequence_info['table'])
  358. table_name = self.quote_name(sequence_info['table'])
  359. column_name = self.quote_name(sequence_info['column'] or 'id')
  360. query = _get_sequence_reset_sql() % {
  361. 'sequence': sequence_name,
  362. 'table': table_name,
  363. 'column': column_name,
  364. }
  365. sql.append(query)
  366. return sql
  367. def sequence_reset_sql(self, style, model_list):
  368. from django.db import models
  369. output = []
  370. query = _get_sequence_reset_sql()
  371. for model in model_list:
  372. for f in model._meta.local_fields:
  373. if isinstance(f, models.AutoField):
  374. table_name = self.quote_name(model._meta.db_table)
  375. sequence_name = self._get_sequence_name(model._meta.db_table)
  376. column_name = self.quote_name(f.column)
  377. output.append(query % {'sequence': sequence_name,
  378. 'table': table_name,
  379. 'column': column_name})
  380. # Only one AutoField is allowed per model, so don't
  381. # continue to loop
  382. break
  383. for f in model._meta.many_to_many:
  384. if not f.rel.through:
  385. table_name = self.quote_name(f.m2m_db_table())
  386. sequence_name = self._get_sequence_name(f.m2m_db_table())
  387. column_name = self.quote_name('id')
  388. output.append(query % {'sequence': sequence_name,
  389. 'table': table_name,
  390. 'column': column_name})
  391. return output
  392. def start_transaction_sql(self):
  393. return ''
  394. def tablespace_sql(self, tablespace, inline=False):
  395. if inline:
  396. return "USING INDEX TABLESPACE %s" % self.quote_name(tablespace)
  397. else:
  398. return "TABLESPACE %s" % self.quote_name(tablespace)
  399. def value_to_db_date(self, value):
  400. """
  401. Transform a date value to an object compatible with what is expected
  402. by the backend driver for date columns.
  403. The default implementation transforms the date to text, but that is not
  404. necessary for Oracle.
  405. """
  406. return value
  407. def value_to_db_datetime(self, value):
  408. """
  409. Transform a datetime value to an object compatible with what is expected
  410. by the backend driver for datetime columns.
  411. If naive datetime is passed assumes that is in UTC. Normally Django
  412. models.DateTimeField makes sure that if USE_TZ is True passed datetime
  413. is timezone aware.
  414. """
  415. if value is None:
  416. return None
  417. # cx_Oracle doesn't support tz-aware datetimes
  418. if timezone.is_aware(value):
  419. if settings.USE_TZ:
  420. value = value.astimezone(timezone.utc).replace(tzinfo=None)
  421. else:
  422. raise ValueError("Oracle backend does not support timezone-aware datetimes when USE_TZ is False.")
  423. return Oracle_datetime.from_datetime(value)
  424. def value_to_db_time(self, value):
  425. if value is None:
  426. return None
  427. if isinstance(value, six.string_types):
  428. return datetime.datetime.strptime(value, '%H:%M:%S')
  429. # Oracle doesn't support tz-aware times
  430. if timezone.is_aware(value):
  431. raise ValueError("Oracle backend does not support timezone-aware times.")
  432. return Oracle_datetime(1900, 1, 1, value.hour, value.minute,
  433. value.second, value.microsecond)
  434. def year_lookup_bounds_for_date_field(self, value):
  435. # Create bounds as real date values
  436. first = datetime.date(value, 1, 1)
  437. last = datetime.date(value, 12, 31)
  438. return [first, last]
  439. def year_lookup_bounds_for_datetime_field(self, value):
  440. # cx_Oracle doesn't support tz-aware datetimes
  441. bounds = super(DatabaseOperations, self).year_lookup_bounds_for_datetime_field(value)
  442. if settings.USE_TZ:
  443. bounds = [b.astimezone(timezone.utc) for b in bounds]
  444. return [Oracle_datetime.from_datetime(b) for b in bounds]
  445. def combine_expression(self, connector, sub_expressions):
  446. "Oracle requires special cases for %% and & operators in query expressions"
  447. if connector == '%%':
  448. return 'MOD(%s)' % ','.join(sub_expressions)
  449. elif connector == '&':
  450. return 'BITAND(%s)' % ','.join(sub_expressions)
  451. elif connector == '|':
  452. raise NotImplementedError("Bit-wise or is not supported in Oracle.")
  453. elif connector == '^':
  454. return 'POWER(%s)' % ','.join(sub_expressions)
  455. return super(DatabaseOperations, self).combine_expression(connector, sub_expressions)
  456. def _get_sequence_name(self, table):
  457. name_length = self.max_name_length() - 3
  458. return '%s_SQ' % backend_utils.truncate_name(table, name_length).upper()
  459. def _get_trigger_name(self, table):
  460. name_length = self.max_name_length() - 3
  461. return '%s_TR' % backend_utils.truncate_name(table, name_length).upper()
  462. def bulk_insert_sql(self, fields, num_values):
  463. items_sql = "SELECT %s FROM DUAL" % ", ".join(["%s"] * len(fields))
  464. return " UNION ALL ".join([items_sql] * num_values)
  465. class _UninitializedOperatorsDescriptor(object):
  466. def __get__(self, instance, owner):
  467. # If connection.operators is looked up before a connection has been
  468. # created, transparently initialize connection.operators to avert an
  469. # AttributeError.
  470. if instance is None:
  471. raise AttributeError("operators not available as class attribute")
  472. # Creating a cursor will initialize the operators.
  473. instance.cursor().close()
  474. return instance.__dict__['operators']
  475. class DatabaseWrapper(BaseDatabaseWrapper):
  476. vendor = 'oracle'
  477. operators = _UninitializedOperatorsDescriptor()
  478. _standard_operators = {
  479. 'exact': '= %s',
  480. 'iexact': '= UPPER(%s)',
  481. 'contains': "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
  482. 'icontains': "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
  483. 'gt': '> %s',
  484. 'gte': '>= %s',
  485. 'lt': '< %s',
  486. 'lte': '<= %s',
  487. 'startswith': "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
  488. 'endswith': "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
  489. 'istartswith': "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
  490. 'iendswith': "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) ESCAPE TRANSLATE('\\' USING NCHAR_CS)",
  491. }
  492. _likec_operators = _standard_operators.copy()
  493. _likec_operators.update({
  494. 'contains': "LIKEC %s ESCAPE '\\'",
  495. 'icontains': "LIKEC UPPER(%s) ESCAPE '\\'",
  496. 'startswith': "LIKEC %s ESCAPE '\\'",
  497. 'endswith': "LIKEC %s ESCAPE '\\'",
  498. 'istartswith': "LIKEC UPPER(%s) ESCAPE '\\'",
  499. 'iendswith': "LIKEC UPPER(%s) ESCAPE '\\'",
  500. })
  501. Database = Database
  502. def __init__(self, *args, **kwargs):
  503. super(DatabaseWrapper, self).__init__(*args, **kwargs)
  504. self.features = DatabaseFeatures(self)
  505. use_returning_into = self.settings_dict["OPTIONS"].get('use_returning_into', True)
  506. self.features.can_return_id_from_insert = use_returning_into
  507. self.ops = DatabaseOperations(self)
  508. self.client = DatabaseClient(self)
  509. self.creation = DatabaseCreation(self)
  510. self.introspection = DatabaseIntrospection(self)
  511. self.validation = BaseDatabaseValidation(self)
  512. def _connect_string(self):
  513. settings_dict = self.settings_dict
  514. if not settings_dict['HOST'].strip():
  515. settings_dict['HOST'] = 'localhost'
  516. if settings_dict['PORT'].strip():
  517. dsn = Database.makedsn(settings_dict['HOST'],
  518. int(settings_dict['PORT']),
  519. settings_dict['NAME'])
  520. else:
  521. dsn = settings_dict['NAME']
  522. return "%s/%s@%s" % (settings_dict['USER'],
  523. settings_dict['PASSWORD'], dsn)
  524. def get_connection_params(self):
  525. conn_params = self.settings_dict['OPTIONS'].copy()
  526. if 'use_returning_into' in conn_params:
  527. del conn_params['use_returning_into']
  528. return conn_params
  529. def get_new_connection(self, conn_params):
  530. conn_string = convert_unicode(self._connect_string())
  531. return Database.connect(conn_string, **conn_params)
  532. def init_connection_state(self):
  533. cursor = self.create_cursor()
  534. # Set the territory first. The territory overrides NLS_DATE_FORMAT
  535. # and NLS_TIMESTAMP_FORMAT to the territory default. When all of
  536. # these are set in single statement it isn't clear what is supposed
  537. # to happen.
  538. cursor.execute("ALTER SESSION SET NLS_TERRITORY = 'AMERICA'")
  539. # Set Oracle date to ANSI date format. This only needs to execute
  540. # once when we create a new connection. We also set the Territory
  541. # to 'AMERICA' which forces Sunday to evaluate to a '1' in
  542. # TO_CHAR().
  543. cursor.execute(
  544. "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'"
  545. " NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'"
  546. + (" TIME_ZONE = 'UTC'" if settings.USE_TZ else ''))
  547. cursor.close()
  548. if 'operators' not in self.__dict__:
  549. # Ticket #14149: Check whether our LIKE implementation will
  550. # work for this connection or we need to fall back on LIKEC.
  551. # This check is performed only once per DatabaseWrapper
  552. # instance per thread, since subsequent connections will use
  553. # the same settings.
  554. cursor = self.create_cursor()
  555. try:
  556. cursor.execute("SELECT 1 FROM DUAL WHERE DUMMY %s"
  557. % self._standard_operators['contains'],
  558. ['X'])
  559. except DatabaseError:
  560. self.operators = self._likec_operators
  561. else:
  562. self.operators = self._standard_operators
  563. cursor.close()
  564. # There's no way for the DatabaseOperations class to know the
  565. # currently active Oracle version, so we do some setups here.
  566. # TODO: Multi-db support will need a better solution (a way to
  567. # communicate the current version).
  568. if self.oracle_version is not None and self.oracle_version <= 9:
  569. self.ops.regex_lookup = self.ops.regex_lookup_9
  570. else:
  571. self.ops.regex_lookup = self.ops.regex_lookup_10
  572. try:
  573. self.connection.stmtcachesize = 20
  574. except AttributeError:
  575. # Django docs specify cx_Oracle version 4.3.1 or higher, but
  576. # stmtcachesize is available only in 4.3.2 and up.
  577. pass
  578. # Ensure all changes are preserved even when AUTOCOMMIT is False.
  579. if not self.get_autocommit():
  580. self.commit()
  581. def create_cursor(self):
  582. return FormatStylePlaceholderCursor(self.connection)
  583. def _commit(self):
  584. if self.connection is not None:
  585. try:
  586. return self.connection.commit()
  587. except Database.DatabaseError as e:
  588. # cx_Oracle 5.0.4 raises a cx_Oracle.DatabaseError exception
  589. # with the following attributes and values:
  590. # code = 2091
  591. # message = 'ORA-02091: transaction rolled back
  592. # 'ORA-02291: integrity constraint (TEST_DJANGOTEST.SYS
  593. # _C00102056) violated - parent key not found'
  594. # We convert that particular case to our IntegrityError exception
  595. x = e.args[0]
  596. if hasattr(x, 'code') and hasattr(x, 'message') \
  597. and x.code == 2091 and 'ORA-02291' in x.message:
  598. six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
  599. raise
  600. def schema_editor(self, *args, **kwargs):
  601. "Returns a new instance of this backend's SchemaEditor"
  602. return DatabaseSchemaEditor(self, *args, **kwargs)
  603. # Oracle doesn't support releasing savepoints. But we fake them when query
  604. # logging is enabled to keep query counts consistent with other backends.
  605. def _savepoint_commit(self, sid):
  606. if self.queries_logged:
  607. self.queries.append({
  608. 'sql': '-- RELEASE SAVEPOINT %s (faked)' % self.ops.quote_name(sid),
  609. 'time': '0.000',
  610. })
  611. def _set_autocommit(self, autocommit):
  612. with self.wrap_database_errors:
  613. self.connection.autocommit = autocommit
  614. def check_constraints(self, table_names=None):
  615. """
  616. To check constraints, we set constraints to immediate. Then, when, we're done we must ensure they
  617. are returned to deferred.
  618. """
  619. self.cursor().execute('SET CONSTRAINTS ALL IMMEDIATE')
  620. self.cursor().execute('SET CONSTRAINTS ALL DEFERRED')
  621. def is_usable(self):
  622. try:
  623. if hasattr(self.connection, 'ping'): # Oracle 10g R2 and higher
  624. self.connection.ping()
  625. else:
  626. # Use a cx_Oracle cursor directly, bypassing Django's utilities.
  627. self.connection.cursor().execute("SELECT 1 FROM DUAL")
  628. except Database.Error:
  629. return False
  630. else:
  631. return True
  632. @cached_property
  633. def oracle_full_version(self):
  634. with self.temporary_connection():
  635. return self.connection.version
  636. @cached_property
  637. def oracle_version(self):
  638. try:
  639. return int(self.oracle_full_version.split('.')[0])
  640. except ValueError:
  641. return None
  642. @cached_property
  643. def version_has_default_introspection_bug(self):
  644. """
  645. Some versions of Oracle -- we've seen this on 11.2.0.1 and suspect
  646. it goes back -- have a weird bug where, when an integer column is
  647. defined with a default, its precision is later reported on introspection
  648. as 0, regardless of the real precision. For Django introspection, this
  649. means that such columns are reported as IntegerField even if they are
  650. really BigIntegerField or BooleanField.
  651. The bug is solved in Oracle 11.2.0.2 and up.
  652. """
  653. return self.oracle_full_version < '11.2.0.2'
  654. class OracleParam(object):
  655. """
  656. Wrapper object for formatting parameters for Oracle. If the string
  657. representation of the value is large enough (greater than 4000 characters)
  658. the input size needs to be set as CLOB. Alternatively, if the parameter
  659. has an `input_size` attribute, then the value of the `input_size` attribute
  660. will be used instead. Otherwise, no input size will be set for the
  661. parameter when executing the query.
  662. """
  663. def __init__(self, param, cursor, strings_only=False):
  664. # With raw SQL queries, datetimes can reach this function
  665. # without being converted by DateTimeField.get_db_prep_value.
  666. if settings.USE_TZ and (isinstance(param, datetime.datetime) and
  667. not isinstance(param, Oracle_datetime)):
  668. if timezone.is_naive(param):
  669. warnings.warn("Oracle received a naive datetime (%s)"
  670. " while time zone support is active." % param,
  671. RuntimeWarning)
  672. default_timezone = timezone.get_default_timezone()
  673. param = timezone.make_aware(param, default_timezone)
  674. param = Oracle_datetime.from_datetime(param.astimezone(timezone.utc))
  675. string_size = 0
  676. # Oracle doesn't recognize True and False correctly in Python 3.
  677. # The conversion done below works both in 2 and 3.
  678. if param is True:
  679. param = "1"
  680. elif param is False:
  681. param = "0"
  682. if hasattr(param, 'bind_parameter'):
  683. self.force_bytes = param.bind_parameter(cursor)
  684. elif isinstance(param, Database.Binary):
  685. self.force_bytes = param
  686. else:
  687. # To transmit to the database, we need Unicode if supported
  688. # To get size right, we must consider bytes.
  689. self.force_bytes = convert_unicode(param, cursor.charset,
  690. strings_only)
  691. if isinstance(self.force_bytes, six.string_types):
  692. # We could optimize by only converting up to 4000 bytes here
  693. string_size = len(force_bytes(param, cursor.charset, strings_only))
  694. if hasattr(param, 'input_size'):
  695. # If parameter has `input_size` attribute, use that.
  696. self.input_size = param.input_size
  697. elif string_size > 4000:
  698. # Mark any string param greater than 4000 characters as a CLOB.
  699. self.input_size = Database.CLOB
  700. else:
  701. self.input_size = None
  702. class VariableWrapper(object):
  703. """
  704. An adapter class for cursor variables that prevents the wrapped object
  705. from being converted into a string when used to instantiate an OracleParam.
  706. This can be used generally for any other object that should be passed into
  707. Cursor.execute as-is.
  708. """
  709. def __init__(self, var):
  710. self.var = var
  711. def bind_parameter(self, cursor):
  712. return self.var
  713. def __getattr__(self, key):
  714. return getattr(self.var, key)
  715. def __setattr__(self, key, value):
  716. if key == 'var':
  717. self.__dict__[key] = value
  718. else:
  719. setattr(self.var, key, value)
  720. class InsertIdVar(object):
  721. """
  722. A late-binding cursor variable that can be passed to Cursor.execute
  723. as a parameter, in order to receive the id of the row created by an
  724. insert statement.
  725. """
  726. def bind_parameter(self, cursor):
  727. param = cursor.cursor.var(Database.NUMBER)
  728. cursor._insert_id_var = param
  729. return param
  730. class FormatStylePlaceholderCursor(object):
  731. """
  732. Django uses "format" (e.g. '%s') style placeholders, but Oracle uses ":var"
  733. style. This fixes it -- but note that if you want to use a literal "%s" in
  734. a query, you'll need to use "%%s".
  735. We also do automatic conversion between Unicode on the Python side and
  736. UTF-8 -- for talking to Oracle -- in here.
  737. """
  738. charset = 'utf-8'
  739. def __init__(self, connection):
  740. self.cursor = connection.cursor()
  741. # Necessary to retrieve decimal values without rounding error.
  742. self.cursor.numbersAsStrings = True
  743. # Default arraysize of 1 is highly sub-optimal.
  744. self.cursor.arraysize = 100
  745. def _format_params(self, params):
  746. try:
  747. return dict((k, OracleParam(v, self, True)) for k, v in params.items())
  748. except AttributeError:
  749. return tuple(OracleParam(p, self, True) for p in params)
  750. def _guess_input_sizes(self, params_list):
  751. # Try dict handling; if that fails, treat as sequence
  752. if hasattr(params_list[0], 'keys'):
  753. sizes = {}
  754. for params in params_list:
  755. for k, value in params.items():
  756. if value.input_size:
  757. sizes[k] = value.input_size
  758. self.setinputsizes(**sizes)
  759. else:
  760. # It's not a list of dicts; it's a list of sequences
  761. sizes = [None] * len(params_list[0])
  762. for params in params_list:
  763. for i, value in enumerate(params):
  764. if value.input_size:
  765. sizes[i] = value.input_size
  766. self.setinputsizes(*sizes)
  767. def _param_generator(self, params):
  768. # Try dict handling; if that fails, treat as sequence
  769. if hasattr(params, 'items'):
  770. return dict((k, v.force_bytes) for k, v in params.items())
  771. else:
  772. return [p.force_bytes for p in params]
  773. def _fix_for_params(self, query, params):
  774. # cx_Oracle wants no trailing ';' for SQL statements. For PL/SQL, it
  775. # it does want a trailing ';' but not a trailing '/'. However, these
  776. # characters must be included in the original query in case the query
  777. # is being passed to SQL*Plus.
  778. if query.endswith(';') or query.endswith('/'):
  779. query = query[:-1]
  780. if params is None:
  781. params = []
  782. query = convert_unicode(query, self.charset)
  783. elif hasattr(params, 'keys'):
  784. # Handle params as dict
  785. args = dict((k, ":%s" % k) for k in params.keys())
  786. query = convert_unicode(query % args, self.charset)
  787. else:
  788. # Handle params as sequence
  789. args = [(':arg%d' % i) for i in range(len(params))]
  790. query = convert_unicode(query % tuple(args), self.charset)
  791. return query, self._format_params(params)
  792. def execute(self, query, params=None):
  793. query, params = self._fix_for_params(query, params)
  794. self._guess_input_sizes([params])
  795. try:
  796. return self.cursor.execute(query, self._param_generator(params))
  797. except Database.DatabaseError as e:
  798. # cx_Oracle <= 4.4.0 wrongly raises a DatabaseError for ORA-01400.
  799. if hasattr(e.args[0], 'code') and e.args[0].code == 1400 and not isinstance(e, IntegrityError):
  800. six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
  801. raise
  802. def executemany(self, query, params=None):
  803. if not params:
  804. # No params given, nothing to do
  805. return None
  806. # uniform treatment for sequences and iterables
  807. params_iter = iter(params)
  808. query, firstparams = self._fix_for_params(query, next(params_iter))
  809. # we build a list of formatted params; as we're going to traverse it
  810. # more than once, we can't make it lazy by using a generator
  811. formatted = [firstparams] + [self._format_params(p) for p in params_iter]
  812. self._guess_input_sizes(formatted)
  813. try:
  814. return self.cursor.executemany(query,
  815. [self._param_generator(p) for p in formatted])
  816. except Database.DatabaseError as e:
  817. # cx_Oracle <= 4.4.0 wrongly raises a DatabaseError for ORA-01400.
  818. if hasattr(e.args[0], 'code') and e.args[0].code == 1400 and not isinstance(e, IntegrityError):
  819. six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
  820. raise
  821. def fetchone(self):
  822. row = self.cursor.fetchone()
  823. if row is None:
  824. return row
  825. return _rowfactory(row, self.cursor)
  826. def fetchmany(self, size=None):
  827. if size is None:
  828. size = self.arraysize
  829. return tuple(_rowfactory(r, self.cursor) for r in self.cursor.fetchmany(size))
  830. def fetchall(self):
  831. return tuple(_rowfactory(r, self.cursor) for r in self.cursor.fetchall())
  832. def close(self):
  833. try:
  834. self.cursor.close()
  835. except Database.InterfaceError:
  836. # already closed
  837. pass
  838. def var(self, *args):
  839. return VariableWrapper(self.cursor.var(*args))
  840. def arrayvar(self, *args):
  841. return VariableWrapper(self.cursor.arrayvar(*args))
  842. def __getattr__(self, attr):
  843. if attr in self.__dict__:
  844. return self.__dict__[attr]
  845. else:
  846. return getattr(self.cursor, attr)
  847. def __iter__(self):
  848. return CursorIterator(self.cursor)
  849. class CursorIterator(six.Iterator):
  850. """Cursor iterator wrapper that invokes our custom row factory."""
  851. def __init__(self, cursor):
  852. self.cursor = cursor
  853. self.iter = iter(cursor)
  854. def __iter__(self):
  855. return self
  856. def __next__(self):
  857. return _rowfactory(next(self.iter), self.cursor)
  858. def _rowfactory(row, cursor):
  859. # Cast numeric values as the appropriate Python type based upon the
  860. # cursor description, and convert strings to unicode.
  861. casted = []
  862. for value, desc in zip(row, cursor.description):
  863. if value is not None and desc[1] is Database.NUMBER:
  864. precision, scale = desc[4:6]
  865. if scale == -127:
  866. if precision == 0:
  867. # NUMBER column: decimal-precision floating point
  868. # This will normally be an integer from a sequence,
  869. # but it could be a decimal value.
  870. if '.' in value:
  871. value = decimal.Decimal(value)
  872. else:
  873. value = int(value)
  874. else:
  875. # FLOAT column: binary-precision floating point.
  876. # This comes from FloatField columns.
  877. value = float(value)
  878. elif precision > 0:
  879. # NUMBER(p,s) column: decimal-precision fixed point.
  880. # This comes from IntField and DecimalField columns.
  881. if scale == 0:
  882. value = int(value)
  883. else:
  884. value = decimal.Decimal(value)
  885. elif '.' in value:
  886. # No type information. This normally comes from a
  887. # mathematical expression in the SELECT list. Guess int
  888. # or Decimal based on whether it has a decimal point.
  889. value = decimal.Decimal(value)
  890. else:
  891. value = int(value)
  892. # datetimes are returned as TIMESTAMP, except the results
  893. # of "dates" queries, which are returned as DATETIME.
  894. elif desc[1] in (Database.TIMESTAMP, Database.DATETIME):
  895. # Confirm that dt is naive before overwriting its tzinfo.
  896. if settings.USE_TZ and value is not None and timezone.is_naive(value):
  897. value = value.replace(tzinfo=timezone.utc)
  898. elif desc[1] in (Database.STRING, Database.FIXED_CHAR,
  899. Database.LONG_STRING):
  900. value = to_unicode(value)
  901. casted.append(value)
  902. return tuple(casted)
  903. def to_unicode(s):
  904. """
  905. Convert strings to Unicode objects (and return all other data types
  906. unchanged).
  907. """
  908. if isinstance(s, six.string_types):
  909. return force_text(s)
  910. return s
  911. def _get_sequence_reset_sql():
  912. # TODO: colorize this SQL code with style.SQL_KEYWORD(), etc.
  913. return """
  914. DECLARE
  915. table_value integer;
  916. seq_value integer;
  917. BEGIN
  918. SELECT NVL(MAX(%(column)s), 0) INTO table_value FROM %(table)s;
  919. SELECT NVL(last_number - cache_size, 0) INTO seq_value FROM user_sequences
  920. WHERE sequence_name = '%(sequence)s';
  921. WHILE table_value > seq_value LOOP
  922. SELECT "%(sequence)s".nextval INTO seq_value FROM dual;
  923. END LOOP;
  924. END;
  925. /"""