Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #1904 -- Got postgresql_psycopg2 backend working. Thanks for th…

…e patch, germish@gmail.com

git-svn-id: http://code.djangoproject.com/svn/django/trunk@2934 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 0ed64fe3298d4f72e90c7f5fa00c805c8f24f58c 1 parent bccc0fb
Adrian Holovaty authored May 18, 2006
16  django/db/backends/postgresql_psycopg2/base.py
@@ -5,7 +5,7 @@
5 5
 """
6 6
 
7 7
 from django.db.backends import util
8  
-import psycopg2.psycopg1 as Database
  8
+import psycopg2 as Database
9 9
 
10 10
 DatabaseError = Database.DatabaseError
11 11
 
@@ -65,14 +65,20 @@ def quote_name(name):
65 65
 
66 66
 def dictfetchone(cursor):
67 67
     "Returns a row from the cursor as a dict"
  68
+    # TODO: cursor.dictfetchone() doesn't exist in psycopg2,
  69
+    # but no Django code uses this. Safe to remove?
68 70
     return cursor.dictfetchone()
69 71
 
70 72
 def dictfetchmany(cursor, number):
71 73
     "Returns a certain number of rows from a cursor as a dict"
  74
+    # TODO: cursor.dictfetchmany() doesn't exist in psycopg2,
  75
+    # but no Django code uses this. Safe to remove?
72 76
     return cursor.dictfetchmany(number)
73 77
 
74 78
 def dictfetchall(cursor):
75 79
     "Returns all rows from a cursor as a dict"
  80
+    # TODO: cursor.dictfetchall() doesn't exist in psycopg2,
  81
+    # but no Django code uses this. Safe to remove?
76 82
     return cursor.dictfetchall()
77 83
 
78 84
 def get_last_insert_id(cursor, table_name, pk_name):
@@ -101,14 +107,6 @@ def get_random_function_sql():
101 107
 def get_drop_foreignkey_sql():
102 108
     return "DROP CONSTRAINT"
103 109
 
104  
-# Register these custom typecasts, because Django expects dates/times to be
105  
-# in Python's native (standard-library) datetime/time format, whereas psycopg
106  
-# use mx.DateTime by default.
107  
-Database.register_type(Database.new_type((1082,), "DATE", util.typecast_date))
108  
-Database.register_type(Database.new_type((1083,1266), "TIME", util.typecast_time))
109  
-Database.register_type(Database.new_type((1114,1184), "TIMESTAMP", util.typecast_timestamp))
110  
-Database.register_type(Database.new_type((16,), "BOOLEAN", util.typecast_boolean))
111  
-
112 110
 OPERATOR_MAPPING = {
113 111
     'exact': '= %s',
114 112
     'iexact': 'ILIKE %s',
86  django/db/backends/postgresql_psycopg2/introspection.py
... ...
@@ -1 +1,85 @@
1  
-from django.db.backends.postgresql.introspection import *
  1
+from django.db import transaction
  2
+from django.db.backends.postgresql_psycopg2.base import quote_name
  3
+
  4
+def get_table_list(cursor):
  5
+    "Returns a list of table names in the current database."
  6
+    cursor.execute("""
  7
+        SELECT c.relname
  8
+        FROM pg_catalog.pg_class c
  9
+        LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
  10
+        WHERE c.relkind IN ('r', 'v', '')
  11
+            AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
  12
+            AND pg_catalog.pg_table_is_visible(c.oid)""")
  13
+    return [row[0] for row in cursor.fetchall()]
  14
+
  15
+def get_table_description(cursor, table_name):
  16
+    "Returns a description of the table, with the DB-API cursor.description interface."
  17
+    cursor.execute("SELECT * FROM %s LIMIT 1" % quote_name(table_name))
  18
+    return cursor.description
  19
+
  20
+def get_relations(cursor, table_name):
  21
+    """
  22
+    Returns a dictionary of {field_index: (field_index_other_table, other_table)}
  23
+    representing all relationships to the given table. Indexes are 0-based.
  24
+    """
  25
+    cursor.execute("""
  26
+        SELECT con.conkey, con.confkey, c2.relname
  27
+        FROM pg_constraint con, pg_class c1, pg_class c2
  28
+        WHERE c1.oid = con.conrelid
  29
+            AND c2.oid = con.confrelid
  30
+            AND c1.relname = %s
  31
+            AND con.contype = 'f'""", [table_name])
  32
+    relations = {}
  33
+    for row in cursor.fetchall():
  34
+        try:
  35
+            # row[0] and row[1] are like "{2}", so strip the curly braces.
  36
+            relations[int(row[0][1:-1]) - 1] = (int(row[1][1:-1]) - 1, row[2])
  37
+        except ValueError:
  38
+            continue
  39
+    return relations
  40
+
  41
+def get_indexes(cursor, table_name):
  42
+    """
  43
+    Returns a dictionary of fieldname -> infodict for the given table,
  44
+    where each infodict is in the format:
  45
+        {'primary_key': boolean representing whether it's the primary key,
  46
+         'unique': boolean representing whether it's a unique index}
  47
+    """
  48
+    # Get the table description because we only have the column indexes, and we
  49
+    # need the column names.
  50
+    desc = get_table_description(cursor, table_name)
  51
+    # This query retrieves each index on the given table.
  52
+    cursor.execute("""
  53
+        SELECT idx.indkey, idx.indisunique, idx.indisprimary
  54
+        FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
  55
+            pg_catalog.pg_index idx
  56
+        WHERE c.oid = idx.indrelid
  57
+            AND idx.indexrelid = c2.oid
  58
+            AND c.relname = %s""", [table_name])
  59
+    indexes = {}
  60
+    for row in cursor.fetchall():
  61
+        # row[0] (idx.indkey) is stored in the DB as an array. It comes out as
  62
+        # a string of space-separated integers. This designates the field
  63
+        # indexes (1-based) of the fields that have indexes on the table.
  64
+        # Here, we skip any indexes across multiple fields.
  65
+        if ' ' in row[0]:
  66
+            continue
  67
+        col_name = desc[int(row[0])-1][0]
  68
+        indexes[col_name] = {'primary_key': row[2], 'unique': row[1]}
  69
+    return indexes
  70
+
  71
+# Maps type codes to Django Field types.
  72
+DATA_TYPES_REVERSE = {
  73
+    16: 'BooleanField',
  74
+    21: 'SmallIntegerField',
  75
+    23: 'IntegerField',
  76
+    25: 'TextField',
  77
+    869: 'IPAddressField',
  78
+    1043: 'CharField',
  79
+    1082: 'DateField',
  80
+    1083: 'TimeField',
  81
+    1114: 'DateTimeField',
  82
+    1184: 'DateTimeField',
  83
+    1266: 'TimeField',
  84
+    1700: 'FloatField',
  85
+}

0 notes on commit 0ed64fe

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