Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added half of oracle backend. (The other half is all of the special-c…

…asing in django/db/models/query.py, which I will be refactoring.) Refs #1990. Thanks, Jason Huggins and tzellman

git-svn-id: http://code.djangoproject.com/svn/django/trunk@2986 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit cac7675f247da325cb862a312804fe64845d1155 1 parent 0fd9eef
@adrianholovaty adrianholovaty authored
View
0  django/db/backends/oracle/__init__.py
No changes.
View
122 django/db/backends/oracle/base.py
@@ -0,0 +1,122 @@
+"""
+Oracle database backend for Django.
+
+Requires cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/
+"""
+
+from django.db.backends import util
+import cx_Oracle as Database
+import types
+
+DatabaseError = Database.Error
+
+try:
+ # Only exists in Python 2.4+
+ from threading import local
+except ImportError:
+ # Import copy of _thread_local.py from Python 2.4
+ from django.utils._threading_local import local
+
+class DatabaseWrapper(local):
+ def __init__(self):
+ self.connection = None
+ self.queries = []
+
+ def _valid_connection(self):
+ return self.connection is not None
+
+ def cursor(self):
+ from django.conf import settings
+ if not self._valid_connection():
+ if len(settings.DATABASE_HOST.strip()) == 0:
+ settings.DATABASE_HOST = 'localhost'
+ if len(settings.DATABASE_PORT.strip()) != 0:
+ dsn = Database.makedsn(settings.DATABASE_HOST, int(settings.DATABASE_PORT), settings.DATABASE_NAME)
+ self.connection = Database.connect(settings.DATABASE_USER, settings.DATABASE_PASSWORD, dsn)
+ else:
+ conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)
+ self.connection = Database.connect(conn_string)
+ return FormatStylePlaceholderCursor(self.connection)
+
+ def _commit(self):
+ self.connection.commit()
+
+ def _rollback(self):
+ if self.connection:
+ try:
+ self.connection.rollback()
+ except Database.NotSupportedError:
+ pass
+
+ def close(self):
+ if self.connection is not None:
+ self.connection.close()
+ self.connection = None
+
+supports_constraints = True
+
+class FormatStylePlaceholderCursor(Database.Cursor):
+ """
+ Django uses "format" (e.g. '%s') style placeholders, but Oracle uses ":var" style.
+ This fixes it -- but note that if you want to use a literal "%s" in a query,
+ you'll need to use "%%s".
+ """
+ def execute(self, query, params=[]):
+ query = self.convert_arguments(query, len(params))
+ return Database.Cursor.execute(self, query, params)
+
+ def executemany(self, query, params=[]):
+ query = self.convert_arguments(query, len(params[0]))
+ return Database.Cursor.executemany(self, query, params)
+
+ def convert_arguments(self, query, num_params):
+ # replace occurances of "%s" with ":arg" - Oracle requires colons for parameter placeholders.
+ args = [':arg' for i in range(num_params)]
+ return query % tuple(args)
+
+def quote_name(name):
+ return name
+
+dictfetchone = util.dictfetchone
+dictfetchmany = util.dictfetchmany
+dictfetchall = util.dictfetchall
+
+def get_last_insert_id(cursor, table_name, pk_name):
+ query = "SELECT %s_sq.currval from dual" % table_name
+ cursor.execute(query)
+ return cursor.fetchone()[0]
+
+def get_date_extract_sql(lookup_type, table_name):
+ # lookup_type is 'year', 'month', 'day'
+ # http://www.psoug.org/reference/date_func.html
+ return "EXTRACT(%s FROM %s)" % (lookup_type, table_name)
+
+def get_date_trunc_sql(lookup_type, field_name):
+ return "EXTRACT(%s FROM TRUNC(%s))" % (lookup_type, field_name)
+
+def get_limit_offset_sql(limit, offset=None):
+ # Limits and offset are too complicated to be handled here.
+ # Instead, they are handled in django/db/query.py.
+ pass
+
+def get_random_function_sql():
+ return "DBMS_RANDOM.RANDOM"
+
+def get_drop_foreignkey_sql():
+ return "DROP FOREIGN KEY"
+
+OPERATOR_MAPPING = {
+ 'exact': '= %s',
+ 'iexact': 'LIKE %s',
+ 'contains': 'LIKE %s',
+ 'icontains': 'LIKE %s',
+ 'ne': '!= %s',
+ 'gt': '> %s',
+ 'gte': '>= %s',
+ 'lt': '< %s',
+ 'lte': '<= %s',
+ 'startswith': 'LIKE %s',
+ 'endswith': 'LIKE %s',
+ 'istartswith': 'LIKE %s',
+ 'iendswith': 'LIKE %s',
+}
View
10 django/db/backends/oracle/client.py
@@ -0,0 +1,10 @@
+from django.conf import settings
+import os
+
+def runshell():
+ args = ''
+ args += settings.DATABASE_USER
+ if settings.DATABASE_PASSWORD:
+ args += "/%s" % settings.DATABASE_PASSWORD
+ args += "@%s" % settings.DATABASE_NAME
+ os.execvp('sqlplus', args)
View
26 django/db/backends/oracle/creation.py
@@ -0,0 +1,26 @@
+DATA_TYPES = {
+ 'AutoField': 'number(38)',
+ 'BooleanField': 'number(1)',
+ 'CharField': 'varchar2(%(maxlength)s)',
+ 'CommaSeparatedIntegerField': 'varchar2(%(maxlength)s)',
+ 'DateField': 'date',
+ 'DateTimeField': 'date',
+ 'FileField': 'varchar2(100)',
+ 'FilePathField': 'varchar2(100)',
+ 'FloatField': 'number(%(max_digits)s, %(decimal_places)s)',
+ 'ImageField': 'varchar2(100)',
+ 'IntegerField': 'integer',
+ 'IPAddressField': 'char(15)',
+ 'ManyToManyField': None,
+ 'NullBooleanField': 'integer',
+ 'OneToOneField': 'integer',
+ 'PhoneNumberField': 'varchar(20)',
+ 'PositiveIntegerField': 'integer',
+ 'PositiveSmallIntegerField': 'smallint',
+ 'SlugField': 'varchar(50)',
+ 'SmallIntegerField': 'smallint',
+ 'TextField': 'long',
+ 'TimeField': 'timestamp',
+ 'URLField': 'varchar(200)',
+ 'USStateField': 'varchar(2)',
+}
View
52 django/db/backends/oracle/introspection.py
@@ -0,0 +1,52 @@
+from django.db import transaction
+from django.db.backends.oracle.base import quote_name
+import re
+
+foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)")
+
+def get_table_list(cursor):
+ "Returns a list of table names in the current database."
+ cursor.execute("SELECT TABLE_NAME FROM USER_TABLES")
+ return [row[0] for row in cursor.fetchall()]
+
+def get_table_description(cursor, table_name):
+ return table_name
+
+def _name_to_index(cursor, table_name):
+ """
+ Returns a dictionary of {field_name: field_index} for the given table.
+ Indexes are 0-based.
+ """
+ return dict([(d[0], i) for i, d in enumerate(get_table_description(cursor, table_name))])
+
+def get_relations(cursor, table_name):
+ """
+ Returns a dictionary of {field_index: (field_index_other_table, other_table)}
+ representing all relationships to the given table. Indexes are 0-based.
+ """
+ raise NotImplementedError
+
+def get_indexes(cursor, table_name):
+ """
+ Returns a dictionary of fieldname -> infodict for the given table,
+ where each infodict is in the format:
+ {'primary_key': boolean representing whether it's the primary key,
+ 'unique': boolean representing whether it's a unique index}
+ """
+ raise NotImplementedError
+
+# Maps type codes to Django Field types.
+DATA_TYPES_REVERSE = {
+ 16: 'BooleanField',
+ 21: 'SmallIntegerField',
+ 23: 'IntegerField',
+ 25: 'TextField',
+ 869: 'IPAddressField',
+ 1043: 'CharField',
+ 1082: 'DateField',
+ 1083: 'TimeField',
+ 1114: 'DateTimeField',
+ 1184: 'DateTimeField',
+ 1266: 'TimeField',
+ 1700: 'FloatField',
+}
Please sign in to comment.
Something went wrong with that request. Please try again.