From 134bf3a26bc9ac39ca736c13381034d470014170 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Fri, 14 Sep 2007 06:21:25 +0000 Subject: [PATCH] Backed out [6165]. It breaks things for people using psycopg2 because it requires psycopg to also be installed due to imports. git-svn-id: http://code.djangoproject.com/svn/django/trunk@6171 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- .../postgresql_psycopg2/introspection.py | 63 ++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/django/db/backends/postgresql_psycopg2/introspection.py b/django/db/backends/postgresql_psycopg2/introspection.py index 6dfcd6a599..bf839c3e95 100644 --- a/django/db/backends/postgresql_psycopg2/introspection.py +++ b/django/db/backends/postgresql_psycopg2/introspection.py @@ -1,8 +1,23 @@ from django.db.backends.postgresql_psycopg2.base import DatabaseOperations -from django.db.backends.postgresql.introspection import get_table_list, get_table_description, get_indexes, DATA_TYPES_REVERSE quote_name = DatabaseOperations().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)} @@ -20,3 +35,49 @@ def get_relations(cursor, table_name): # row[0] and row[1] are single-item lists, so grab the single item. relations[row[0][0] - 1] = (row[1][0] - 1, row[2]) 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} + """ + # This query retrieves each index on the given table, including the + # first associated field name + cursor.execute(""" + SELECT attr.attname, idx.indkey, idx.indisunique, idx.indisprimary + FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, + pg_catalog.pg_index idx, pg_catalog.pg_attribute attr + WHERE c.oid = idx.indrelid + AND idx.indexrelid = c2.oid + AND attr.attrelid = c.oid + AND attr.attnum = idx.indkey[0] + AND c.relname = %s""", [table_name]) + indexes = {} + for row in cursor.fetchall(): + # row[1] (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[1]: + continue + indexes[row[0]] = {'primary_key': row[3], 'unique': row[2]} + return indexes + +# Maps type codes to Django Field types. +DATA_TYPES_REVERSE = { + 16: 'BooleanField', + 21: 'SmallIntegerField', + 23: 'IntegerField', + 25: 'TextField', + 701: 'FloatField', + 869: 'IPAddressField', + 1043: 'CharField', + 1082: 'DateField', + 1083: 'TimeField', + 1114: 'DateTimeField', + 1184: 'DateTimeField', + 1266: 'TimeField', + 1700: 'DecimalField', +}