Ticket #17785: pscopg2-introspection.patch

File pscopg2-introspection.patch, 4.4 KB (added by guettli, 3 years ago)
  • django/db/backends/postgresql_psycopg2/introspection.py

     
    5050        """
    5151        Returns a dictionary of {field_index: (field_index_other_table, other_table)}
    5252        representing all relationships to the given table. Indexes are 0-based.
     53        If a column gets deleted, attnum of the other columns does not change. You can't use attnum as
     54        offset in the table description.
    5355        """
     56        cursor.execute("SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(table_name))
     57        this_table_col_names=[col_desc[0] for col_desc in cursor.description]
    5458        cursor.execute("""
    55             SELECT con.conkey, con.confkey, c2.relname
     59            SELECT
     60               (SELECT attname FROM pg_attribute WHERE attnum=con.conkey[1] AND attrelid=con.conrelid),
     61               (SELECT attname FROM pg_attribute WHERE attnum=con.confkey[1] AND attrelid=con.confrelid),
     62               c2.relname
    5663            FROM pg_constraint con, pg_class c1, pg_class c2
    5764            WHERE c1.oid = con.conrelid
    5865                AND c2.oid = con.confrelid
    5966                AND c1.relname = %s
    6067                AND con.contype = 'f'""", [table_name])
    6168        relations = {}
    62         for row in cursor.fetchall():
    63             # row[0] and row[1] are single-item lists, so grab the single item.
    64             relations[row[0][0] - 1] = (row[1][0] - 1, row[2])
     69        for this_col_name, other_col_name, other_table in list(cursor.fetchall()):
     70            cursor.execute("SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(other_table))
     71            other_table_col_names=[col_desc[0] for col_desc in cursor.description]
     72            relations[this_table_col_names.index(this_col_name)] = (other_table_col_names.index(other_col_name), other_table)
    6573        return relations
    6674
    6775    def get_indexes(self, cursor, table_name):
  • tests/regressiontests/introspection/tests.py

     
    44
    55from django.db import connection
    66from django.test import TestCase, skipUnlessDBFeature, skipIfDBFeature
     7from django.db.utils import DatabaseError
    78
    89from .models import Reporter, Article
    910
     
    136137        indexes = connection.introspection.get_indexes(cursor, Article._meta.db_table)
    137138        self.assertEqual(indexes['reporter_id'], {'unique': False, 'primary_key': False})
    138139
     140    def test_introspection_after_drop_column(self):
     141        cursor = connection.cursor()
     142        cursor.execute('''CREATE TABLE "django_drop_col_other1" ("id" INTEGER CONSTRAINT "other1_pk_id" PRIMARY KEY)''')
     143        cursor.execute('''CREATE TABLE "django_drop_col_other2" ("id" INTEGER CONSTRAINT "other2_pk_id" PRIMARY KEY)''')
     144        cursor.execute('''CREATE TABLE "django_drop_col_test" (
     145                              "id" INTEGER CONSTRAINT "pk_id" PRIMARY KEY,
     146                              "col_to_drop" INTEGER CONSTRAINT "fk_col_to_drop" REFERENCES "django_drop_col_other1" ("id"),
     147                              "col_fk" INTEGER CONSTRAINT "fk_col_fk" REFERENCES "django_drop_col_other2" ("id")
     148                          ) ''')
     149        col_names = [col[0] for col in connection.introspection.get_table_description(cursor, "django_drop_col_test")]
     150        self.assertEqual(col_names, ['id', 'col_to_drop', 'col_fk'])
     151        rels=connection.introspection.get_relations(cursor, "django_drop_col_test")
     152        self.assertEqual(rels, {1: (0, u'django_drop_col_other1'), 2: (0, u'django_drop_col_other2')})
     153        try:
     154            cursor.execute('ALTER TABLE "django_drop_col_test" DROP COLUMN "col_to_drop"')
     155        except DatabaseError:
     156            return # sqlite does not support drop column
     157        col_names = [col[0] for col in connection.introspection.get_table_description(cursor, "django_drop_col_test")]
     158        self.assertEqual(col_names, ['id', 'col_fk'])
     159        rels=connection.introspection.get_relations(cursor, "django_drop_col_test")
     160        self.assertEqual(rels, {1: (0, u'django_drop_col_other2')})
     161       
    139162
    140163def datatype(dbtype, description):
    141164    """Helper to convert a data type into a string."""
Back to Top