Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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.