summaryrefslogtreecommitdiff
path: root/django/db
diff options
context:
space:
mode:
authorJoseph Kocherhans <joseph@jkocherhans.com>2006-05-22 15:19:32 +0000
committerJoseph Kocherhans <joseph@jkocherhans.com>2006-05-22 15:19:32 +0000
commit681763a29c9d82858a214a6898e807be0c835c47 (patch)
treedf7f7644137f2c5ac961dc21245543e499c4cb67 /django/db
parentd659956cf5e9dbe1b22e7eae7f7e75d186caa226 (diff)
multi-auth: Merged to [2964]
git-svn-id: http://code.djangoproject.com/svn/django/branches/multi-auth@2965 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/db')
-rw-r--r--django/db/backends/postgresql_psycopg2/__init__.py0
-rw-r--r--django/db/backends/postgresql_psycopg2/base.py123
-rw-r--r--django/db/backends/postgresql_psycopg2/client.py1
-rw-r--r--django/db/backends/postgresql_psycopg2/creation.py1
-rw-r--r--django/db/backends/postgresql_psycopg2/introspection.py85
-rw-r--r--django/db/models/base.py6
6 files changed, 213 insertions, 3 deletions
diff --git a/django/db/backends/postgresql_psycopg2/__init__.py b/django/db/backends/postgresql_psycopg2/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/django/db/backends/postgresql_psycopg2/__init__.py
diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py
new file mode 100644
index 0000000000..9376c36772
--- /dev/null
+++ b/django/db/backends/postgresql_psycopg2/base.py
@@ -0,0 +1,123 @@
+"""
+PostgreSQL database backend for Django.
+
+Requires psycopg 2: http://initd.org/projects/psycopg2
+"""
+
+from django.db.backends import util
+import psycopg2 as Database
+
+DatabaseError = Database.DatabaseError
+
+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 cursor(self):
+ from django.conf import settings
+ if self.connection is None:
+ if settings.DATABASE_NAME == '':
+ from django.core.exceptions import ImproperlyConfigured
+ raise ImproperlyConfigured, "You need to specify DATABASE_NAME in your Django settings file."
+ conn_string = "dbname=%s" % settings.DATABASE_NAME
+ if settings.DATABASE_USER:
+ conn_string = "user=%s %s" % (settings.DATABASE_USER, conn_string)
+ if settings.DATABASE_PASSWORD:
+ conn_string += " password='%s'" % settings.DATABASE_PASSWORD
+ if settings.DATABASE_HOST:
+ conn_string += " host=%s" % settings.DATABASE_HOST
+ if settings.DATABASE_PORT:
+ conn_string += " port=%s" % settings.DATABASE_PORT
+ self.connection = Database.connect(conn_string)
+ self.connection.set_isolation_level(1) # make transactions transparent to all cursors
+ cursor = self.connection.cursor()
+ cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
+ if settings.DEBUG:
+ return util.CursorDebugWrapper(cursor, self)
+ return cursor
+
+ def _commit(self):
+ return self.connection.commit()
+
+ def _rollback(self):
+ if self.connection:
+ return self.connection.rollback()
+
+ def close(self):
+ if self.connection is not None:
+ self.connection.close()
+ self.connection = None
+
+supports_constraints = True
+
+def quote_name(name):
+ if name.startswith('"') and name.endswith('"'):
+ return name # Quoting once is enough.
+ return '"%s"' % name
+
+def dictfetchone(cursor):
+ "Returns a row from the cursor as a dict"
+ # TODO: cursor.dictfetchone() doesn't exist in psycopg2,
+ # but no Django code uses this. Safe to remove?
+ return cursor.dictfetchone()
+
+def dictfetchmany(cursor, number):
+ "Returns a certain number of rows from a cursor as a dict"
+ # TODO: cursor.dictfetchmany() doesn't exist in psycopg2,
+ # but no Django code uses this. Safe to remove?
+ return cursor.dictfetchmany(number)
+
+def dictfetchall(cursor):
+ "Returns all rows from a cursor as a dict"
+ # TODO: cursor.dictfetchall() doesn't exist in psycopg2,
+ # but no Django code uses this. Safe to remove?
+ return cursor.dictfetchall()
+
+def get_last_insert_id(cursor, table_name, pk_name):
+ cursor.execute("SELECT CURRVAL('\"%s_%s_seq\"')" % (table_name, pk_name))
+ return cursor.fetchone()[0]
+
+def get_date_extract_sql(lookup_type, table_name):
+ # lookup_type is 'year', 'month', 'day'
+ # http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
+ return "EXTRACT('%s' FROM %s)" % (lookup_type, table_name)
+
+def get_date_trunc_sql(lookup_type, field_name):
+ # lookup_type is 'year', 'month', 'day'
+ # http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
+ return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
+
+def get_limit_offset_sql(limit, offset=None):
+ sql = "LIMIT %s" % limit
+ if offset and offset != 0:
+ sql += " OFFSET %s" % offset
+ return sql
+
+def get_random_function_sql():
+ return "RANDOM()"
+
+def get_drop_foreignkey_sql():
+ return "DROP CONSTRAINT"
+
+OPERATOR_MAPPING = {
+ 'exact': '= %s',
+ 'iexact': 'ILIKE %s',
+ 'contains': 'LIKE %s',
+ 'icontains': 'ILIKE %s',
+ 'gt': '> %s',
+ 'gte': '>= %s',
+ 'lt': '< %s',
+ 'lte': '<= %s',
+ 'startswith': 'LIKE %s',
+ 'endswith': 'LIKE %s',
+ 'istartswith': 'ILIKE %s',
+ 'iendswith': 'ILIKE %s',
+}
diff --git a/django/db/backends/postgresql_psycopg2/client.py b/django/db/backends/postgresql_psycopg2/client.py
new file mode 100644
index 0000000000..c9d879a1b7
--- /dev/null
+++ b/django/db/backends/postgresql_psycopg2/client.py
@@ -0,0 +1 @@
+from django.db.backends.postgresql.client import *
diff --git a/django/db/backends/postgresql_psycopg2/creation.py b/django/db/backends/postgresql_psycopg2/creation.py
new file mode 100644
index 0000000000..8c87e5c493
--- /dev/null
+++ b/django/db/backends/postgresql_psycopg2/creation.py
@@ -0,0 +1 @@
+from django.db.backends.postgresql.creation import *
diff --git a/django/db/backends/postgresql_psycopg2/introspection.py b/django/db/backends/postgresql_psycopg2/introspection.py
new file mode 100644
index 0000000000..88c44f98d7
--- /dev/null
+++ b/django/db/backends/postgresql_psycopg2/introspection.py
@@ -0,0 +1,85 @@
+from django.db import transaction
+from django.db.backends.postgresql_psycopg2.base import quote_name
+
+def get_table_list(cursor):
+ "Returns a list of table names in the current database."
+ cursor.execute("""
+ SELECT c.relname
+ FROM pg_catalog.pg_class c
+ LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
+ WHERE c.relkind IN ('r', 'v', '')
+ AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
+ AND pg_catalog.pg_table_is_visible(c.oid)""")
+ return [row[0] for row in cursor.fetchall()]
+
+def get_table_description(cursor, table_name):
+ "Returns a description of the table, with the DB-API cursor.description interface."
+ cursor.execute("SELECT * FROM %s LIMIT 1" % quote_name(table_name))
+ return cursor.description
+
+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.
+ """
+ cursor.execute("""
+ SELECT con.conkey, con.confkey, c2.relname
+ FROM pg_constraint con, pg_class c1, pg_class c2
+ WHERE c1.oid = con.conrelid
+ AND c2.oid = con.confrelid
+ AND c1.relname = %s
+ AND con.contype = 'f'""", [table_name])
+ relations = {}
+ for row in cursor.fetchall():
+ try:
+ # row[0] and row[1] are like "{2}", so strip the curly braces.
+ relations[int(row[0][1:-1]) - 1] = (int(row[1][1:-1]) - 1, row[2])
+ except ValueError:
+ continue
+ return relations
+
+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}
+ """
+ # Get the table description because we only have the column indexes, and we
+ # need the column names.
+ desc = get_table_description(cursor, table_name)
+ # This query retrieves each index on the given table.
+ cursor.execute("""
+ SELECT idx.indkey, idx.indisunique, idx.indisprimary
+ FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
+ pg_catalog.pg_index idx
+ WHERE c.oid = idx.indrelid
+ AND idx.indexrelid = c2.oid
+ AND c.relname = %s""", [table_name])
+ indexes = {}
+ for row in cursor.fetchall():
+ # row[0] (idx.indkey) is stored in the DB as an array. It comes out as
+ # a string of space-separated integers. This designates the field
+ # indexes (1-based) of the fields that have indexes on the table.
+ # Here, we skip any indexes across multiple fields.
+ if ' ' in row[0]:
+ continue
+ col_name = desc[int(row[0])-1][0]
+ indexes[col_name] = {'primary_key': row[2], 'unique': row[1]}
+ return indexes
+
+# 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',
+}
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 88bed45c8a..08a81c9ab9 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -341,16 +341,16 @@ class Model(object):
_save_FIELD_file.alters_data = True
def _get_FIELD_width(self, field):
- return self.__get_image_dimensions(field)[0]
+ return self._get_image_dimensions(field)[0]
def _get_FIELD_height(self, field):
- return self.__get_image_dimensions(field)[1]
+ return self._get_image_dimensions(field)[1]
def _get_image_dimensions(self, field):
cachename = "__%s_dimensions_cache" % field.name
if not hasattr(self, cachename):
from django.utils.images import get_image_dimensions
- filename = self.__get_FIELD_filename(field)()
+ filename = self._get_FIELD_filename(field)()
setattr(self, cachename, get_image_dimensions(filename))
return getattr(self, cachename)