Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
Adrian Holovaty authored May 26, 2006
0  backends/oracle/__init__.py b/django/db/backends/oracle/__init__.py
No changes.
122  django/db/backends/oracle/base.py
... ...
@@ -0,0 +1,122 @@
  1
+"""
  2
+Oracle database backend for Django.
  3
+
  4
+Requires cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/
  5
+"""
  6
+
  7
+from django.db.backends import util
  8
+import cx_Oracle as Database
  9
+import types
  10
+
  11
+DatabaseError = Database.Error
  12
+
  13
+try:
  14
+    # Only exists in Python 2.4+
  15
+    from threading import local
  16
+except ImportError:
  17
+    # Import copy of _thread_local.py from Python 2.4
  18
+    from django.utils._threading_local import local
  19
+
  20
+class DatabaseWrapper(local):
  21
+    def __init__(self):
  22
+        self.connection = None
  23
+        self.queries = []
  24
+
  25
+    def _valid_connection(self):
  26
+        return self.connection is not None
  27
+
  28
+    def cursor(self):
  29
+        from django.conf import settings
  30
+        if not self._valid_connection():
  31
+            if len(settings.DATABASE_HOST.strip()) == 0:
  32
+                settings.DATABASE_HOST = 'localhost'
  33
+            if len(settings.DATABASE_PORT.strip()) != 0:
  34
+                dsn = Database.makedsn(settings.DATABASE_HOST, int(settings.DATABASE_PORT), settings.DATABASE_NAME)
  35
+                self.connection = Database.connect(settings.DATABASE_USER, settings.DATABASE_PASSWORD, dsn)
  36
+            else:
  37
+                conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)
  38
+                self.connection = Database.connect(conn_string)
  39
+        return FormatStylePlaceholderCursor(self.connection)
  40
+
  41
+    def _commit(self):
  42
+        self.connection.commit()
  43
+
  44
+    def _rollback(self):
  45
+        if self.connection:
  46
+            try:
  47
+                self.connection.rollback()
  48
+            except Database.NotSupportedError:
  49
+                pass
  50
+
  51
+    def close(self):
  52
+        if self.connection is not None:
  53
+            self.connection.close()
  54
+            self.connection = None
  55
+
  56
+supports_constraints = True
  57
+
  58
+class FormatStylePlaceholderCursor(Database.Cursor):
  59
+    """
  60
+    Django uses "format" (e.g. '%s') style placeholders, but Oracle uses ":var" style.
  61
+    This fixes it -- but note that if you want to use a literal "%s" in a query,
  62
+    you'll need to use "%%s".
  63
+    """
  64
+    def execute(self, query, params=[]):
  65
+        query = self.convert_arguments(query, len(params))
  66
+        return Database.Cursor.execute(self, query, params)
  67
+
  68
+    def executemany(self, query, params=[]):
  69
+        query = self.convert_arguments(query, len(params[0]))
  70
+        return Database.Cursor.executemany(self, query, params)
  71
+
  72
+    def convert_arguments(self, query, num_params):
  73
+        # replace occurances of "%s" with ":arg" - Oracle requires colons for parameter placeholders.
  74
+        args = [':arg' for i in range(num_params)]
  75
+        return query % tuple(args)
  76
+
  77
+def quote_name(name):
  78
+    return name
  79
+
  80
+dictfetchone = util.dictfetchone
  81
+dictfetchmany = util.dictfetchmany
  82
+dictfetchall  = util.dictfetchall
  83
+
  84
+def get_last_insert_id(cursor, table_name, pk_name):
  85
+    query = "SELECT %s_sq.currval from dual" % table_name
  86
+    cursor.execute(query)
  87
+    return cursor.fetchone()[0]
  88
+
  89
+def get_date_extract_sql(lookup_type, table_name):
  90
+    # lookup_type is 'year', 'month', 'day'
  91
+    # http://www.psoug.org/reference/date_func.html
  92
+    return "EXTRACT(%s FROM %s)" % (lookup_type, table_name)
  93
+
  94
+def get_date_trunc_sql(lookup_type, field_name):
  95
+    return "EXTRACT(%s FROM TRUNC(%s))" % (lookup_type, field_name)
  96
+
  97
+def get_limit_offset_sql(limit, offset=None):
  98
+    # Limits and offset are too complicated to be handled here.
  99
+    # Instead, they are handled in django/db/query.py.
  100
+    pass
  101
+
  102
+def get_random_function_sql():
  103
+    return "DBMS_RANDOM.RANDOM"
  104
+
  105
+def get_drop_foreignkey_sql():
  106
+    return "DROP FOREIGN KEY"
  107
+
  108
+OPERATOR_MAPPING = {
  109
+    'exact': '= %s',
  110
+    'iexact': 'LIKE %s',
  111
+    'contains': 'LIKE %s',
  112
+    'icontains': 'LIKE %s',
  113
+    'ne': '!= %s',
  114
+    'gt': '> %s',
  115
+    'gte': '>= %s',
  116
+    'lt': '< %s',
  117
+    'lte': '<= %s',
  118
+    'startswith': 'LIKE %s',
  119
+    'endswith': 'LIKE %s',
  120
+    'istartswith': 'LIKE %s',
  121
+    'iendswith': 'LIKE %s',
  122
+}
10  django/db/backends/oracle/client.py
... ...
@@ -0,0 +1,10 @@
  1
+from django.conf import settings
  2
+import os
  3
+
  4
+def runshell():
  5
+    args = ''
  6
+    args += settings.DATABASE_USER
  7
+    if settings.DATABASE_PASSWORD:
  8
+        args += "/%s" % settings.DATABASE_PASSWORD
  9
+    args += "@%s" % settings.DATABASE_NAME
  10
+    os.execvp('sqlplus', args)
26  django/db/backends/oracle/creation.py
... ...
@@ -0,0 +1,26 @@
  1
+DATA_TYPES = {
  2
+    'AutoField':         'number(38)',
  3
+    'BooleanField':      'number(1)',
  4
+    'CharField':         'varchar2(%(maxlength)s)',
  5
+    'CommaSeparatedIntegerField': 'varchar2(%(maxlength)s)',
  6
+    'DateField':         'date',
  7
+    'DateTimeField':     'date',
  8
+    'FileField':         'varchar2(100)',
  9
+    'FilePathField':     'varchar2(100)',
  10
+    'FloatField':        'number(%(max_digits)s, %(decimal_places)s)',
  11
+    'ImageField':        'varchar2(100)',
  12
+    'IntegerField':      'integer',
  13
+    'IPAddressField':    'char(15)',
  14
+    'ManyToManyField':   None,
  15
+    'NullBooleanField':  'integer',
  16
+    'OneToOneField':     'integer',
  17
+    'PhoneNumberField':  'varchar(20)',
  18
+    'PositiveIntegerField': 'integer',
  19
+    'PositiveSmallIntegerField': 'smallint',
  20
+    'SlugField':         'varchar(50)',
  21
+    'SmallIntegerField': 'smallint',
  22
+    'TextField':         'long',
  23
+    'TimeField':         'timestamp',
  24
+    'URLField':          'varchar(200)',
  25
+    'USStateField':      'varchar(2)',
  26
+}
52  django/db/backends/oracle/introspection.py
... ...
@@ -0,0 +1,52 @@
  1
+from django.db import transaction
  2
+from django.db.backends.oracle.base import quote_name
  3
+import re
  4
+
  5
+foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)")
  6
+
  7
+def get_table_list(cursor):
  8
+    "Returns a list of table names in the current database."
  9
+    cursor.execute("SELECT TABLE_NAME FROM USER_TABLES")
  10
+    return [row[0] for row in cursor.fetchall()]
  11
+
  12
+def get_table_description(cursor, table_name):
  13
+    return table_name
  14
+
  15
+def _name_to_index(cursor, table_name):
  16
+    """
  17
+    Returns a dictionary of {field_name: field_index} for the given table.
  18
+    Indexes are 0-based.
  19
+    """
  20
+    return dict([(d[0], i) for i, d in enumerate(get_table_description(cursor, table_name))])
  21
+
  22
+def get_relations(cursor, table_name):
  23
+    """
  24
+    Returns a dictionary of {field_index: (field_index_other_table, other_table)}
  25
+    representing all relationships to the given table. Indexes are 0-based.
  26
+    """
  27
+    raise NotImplementedError
  28
+
  29
+def get_indexes(cursor, table_name):
  30
+    """
  31
+    Returns a dictionary of fieldname -> infodict for the given table,
  32
+    where each infodict is in the format:
  33
+        {'primary_key': boolean representing whether it's the primary key,
  34
+         'unique': boolean representing whether it's a unique index}
  35
+    """
  36
+    raise NotImplementedError
  37
+
  38
+# Maps type codes to Django Field types.
  39
+DATA_TYPES_REVERSE = {
  40
+    16: 'BooleanField',
  41
+    21: 'SmallIntegerField',
  42
+    23: 'IntegerField',
  43
+    25: 'TextField',
  44
+    869: 'IPAddressField',
  45
+    1043: 'CharField',
  46
+    1082: 'DateField',
  47
+    1083: 'TimeField',
  48
+    1114: 'DateTimeField',
  49
+    1184: 'DateTimeField',
  50
+    1266: 'TimeField',
  51
+    1700: 'FloatField',
  52
+}

0 notes on commit cac7675

Please sign in to comment.
Something went wrong with that request. Please try again.