summaryrefslogtreecommitdiff
path: root/django/core/db/backends/postgresql.py
diff options
context:
space:
mode:
Diffstat (limited to 'django/core/db/backends/postgresql.py')
-rw-r--r--django/core/db/backends/postgresql.py238
1 files changed, 0 insertions, 238 deletions
diff --git a/django/core/db/backends/postgresql.py b/django/core/db/backends/postgresql.py
deleted file mode 100644
index 0bc799c247..0000000000
--- a/django/core/db/backends/postgresql.py
+++ /dev/null
@@ -1,238 +0,0 @@
-"""
-PostgreSQL database backend for Django.
-
-Requires psycopg 1: http://initd.org/projects/psycopg1
-"""
-
-from django.core.db import base, typecasts
-import psycopg 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.settings import DATABASE_USER, DATABASE_NAME, DATABASE_HOST, DATABASE_PORT, DATABASE_PASSWORD, DEBUG, TIME_ZONE
- if self.connection is None:
- if 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" % DATABASE_NAME
- if DATABASE_USER:
- conn_string = "user=%s %s" % (DATABASE_USER, conn_string)
- if DATABASE_PASSWORD:
- conn_string += " password='%s'" % DATABASE_PASSWORD
- if DATABASE_HOST:
- conn_string += " host=%s" % DATABASE_HOST
- if DATABASE_PORT:
- conn_string += " port=%s" % 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", [TIME_ZONE])
- if DEBUG:
- return base.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
-
- def quote_name(self, 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"
- return cursor.dictfetchone()
-
-def dictfetchmany(cursor, number):
- "Returns a certain number of rows from a cursor as a dict"
- return cursor.dictfetchmany(number)
-
-def dictfetchall(cursor):
- "Returns all rows from a cursor as a dict"
- 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_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" % DatabaseWrapper().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
-
-# Register these custom typecasts, because Django expects dates/times to be
-# in Python's native (standard-library) datetime/time format, whereas psycopg
-# use mx.DateTime by default.
-try:
- Database.register_type(Database.new_type((1082,), "DATE", typecasts.typecast_date))
-except AttributeError:
- raise Exception, "You appear to be using psycopg version 2, which isn't supported yet, because it's still in beta. Use psycopg version 1 instead: http://initd.org/projects/psycopg1"
-Database.register_type(Database.new_type((1083,1266), "TIME", typecasts.typecast_time))
-Database.register_type(Database.new_type((1114,1184), "TIMESTAMP", typecasts.typecast_timestamp))
-Database.register_type(Database.new_type((16,), "BOOLEAN", typecasts.typecast_boolean))
-
-OPERATOR_MAPPING = {
- 'exact': '= %s',
- 'iexact': 'ILIKE %s',
- 'contains': 'LIKE %s',
- 'icontains': 'ILIKE %s',
- 'ne': '!= %s',
- 'gt': '> %s',
- 'gte': '>= %s',
- 'lt': '< %s',
- 'lte': '<= %s',
- 'startswith': 'LIKE %s',
- 'endswith': 'LIKE %s',
- 'istartswith': 'ILIKE %s',
- 'iendswith': 'ILIKE %s',
-}
-
-# This dictionary maps Field objects to their associated PostgreSQL column
-# types, as strings. Column-type strings can contain format strings; they'll
-# be interpolated against the values of Field.__dict__ before being output.
-# If a column type is set to None, it won't be included in the output.
-DATA_TYPES = {
- 'AutoField': 'serial',
- 'BooleanField': 'boolean',
- 'CharField': 'varchar(%(maxlength)s)',
- 'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
- 'DateField': 'date',
- 'DateTimeField': 'timestamp with time zone',
- 'FileField': 'varchar(100)',
- 'FilePathField': 'varchar(100)',
- 'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
- 'ImageField': 'varchar(100)',
- 'IntegerField': 'integer',
- 'IPAddressField': 'inet',
- 'ManyToManyField': None,
- 'NullBooleanField': 'boolean',
- 'OneToOneField': 'integer',
- 'PhoneNumberField': 'varchar(20)',
- 'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)',
- 'PositiveSmallIntegerField': 'smallint CHECK ("%(column)s" >= 0)',
- 'SlugField': 'varchar(%(maxlength)s)',
- 'SmallIntegerField': 'smallint',
- 'TextField': 'text',
- 'TimeField': 'time',
- 'URLField': 'varchar(200)',
- 'USStateField': 'varchar(2)',
-}
-
-# 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',
-}