Ticket #17574: 17574-1.diff

File 17574-1.diff, 5.5 KB (added by claudep, 4 years ago)

Introspection code improvements

  • django/db/backends/__init__.py

    diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
    index ebe8875..85c0750 100644
    a b class BaseDatabaseIntrospection(object): 
    963963
    964964    def get_primary_key_column(self, cursor, table_name):
    965965        """
    966         Backends can override this to return the column name of the primary key for the given table.
     966        Returns the name of the primary key column for the given table
    967967        """
    968         raise NotImplementedError
     968        for column in self.get_indexes(cursor, table_name).iteritems():
     969            if column[1]['primary_key']:
     970                return column[0]
     971        return None
    969972
    970973class BaseDatabaseClient(object):
    971974    """
  • django/db/backends/mysql/introspection.py

    diff --git a/django/db/backends/mysql/introspection.py b/django/db/backends/mysql/introspection.py
    index ab4eebe..c771337 100644
    a b class DatabaseIntrospection(BaseDatabaseIntrospection): 
    8888                    key_columns.append(match.groups())
    8989        return key_columns
    9090
    91     def get_primary_key_column(self, cursor, table_name):
    92         """
    93         Returns the name of the primary key column for the given table
    94         """
    95         for column in self.get_indexes(cursor, table_name).iteritems():
    96             if column[1]['primary_key']:
    97                 return column[0]
    98         return None
    99 
    10091    def get_indexes(self, cursor, table_name):
    10192        """
    10293        Returns a dictionary of fieldname -> infodict for the given table,
  • django/db/backends/postgresql_psycopg2/introspection.py

    diff --git a/django/db/backends/postgresql_psycopg2/introspection.py b/django/db/backends/postgresql_psycopg2/introspection.py
    index 0027ec5..dc73ce3 100644
    a b class DatabaseIntrospection(BaseDatabaseIntrospection): 
    6363            relations[row[0][0] - 1] = (row[1][0] - 1, row[2])
    6464        return relations
    6565
     66    def get_key_columns(self, cursor, table_name):
     67        key_columns = []
     68        cursor.execute("""
     69            SELECT kcu.column_name, ccu.table_name AS referenced_table, ccu.column_name AS referenced_column
     70            FROM information_schema.constraint_column_usage ccu
     71            LEFT JOIN information_schema.key_column_usage kcu
     72                ON ccu.constraint_catalog = kcu.constraint_catalog
     73                    AND ccu.constraint_schema = kcu.constraint_schema
     74                    AND ccu.constraint_name = kcu.constraint_name
     75            LEFT JOIN information_schema.table_constraints tc
     76                ON ccu.constraint_catalog = tc.constraint_catalog
     77                    AND ccu.constraint_schema = tc.constraint_schema
     78                    AND ccu.constraint_name = tc.constraint_name
     79            WHERE kcu.table_name = %s AND tc.constraint_type = 'FOREIGN KEY'""" , [table_name])
     80        key_columns.extend(cursor.fetchall())
     81        return key_columns
     82
    6683    def get_indexes(self, cursor, table_name):
    6784        """
    6885        Returns a dictionary of fieldname -> infodict for the given table,
  • tests/regressiontests/introspection/models.py

    diff --git a/tests/regressiontests/introspection/models.py b/tests/regressiontests/introspection/models.py
    index 3b8383e..486133a 100644
    a b class Article(models.Model): 
    1919        return self.headline
    2020
    2121    class Meta:
    22         ordering = ('headline',)
    23  No newline at end of file
     22        ordering = ('headline',)
  • tests/regressiontests/introspection/tests.py

    diff --git a/tests/regressiontests/introspection/tests.py b/tests/regressiontests/introspection/tests.py
    index fa2b6c5..95c7241 100644
    a b  
    11from __future__ import absolute_import
    22
    3 from functools import update_wrapper
    4 
    53from django.db import connection
    64from django.test import TestCase, skipUnlessDBFeature
    75
    86from .models import Reporter, Article
    97
    10 #
    11 # The introspection module is optional, so methods tested here might raise
    12 # NotImplementedError. This is perfectly acceptable behavior for the backend
    13 # in question, but the tests need to handle this without failing. Ideally we'd
    14 # skip these tests, but until #4788 is done we'll just ignore them.
    15 #
    16 # The easiest way to accomplish this is to decorate every test case with a
    17 # wrapper that ignores the exception.
    18 #
    19 # The metaclass is just for fun.
    20 #
    21 
    22 def ignore_not_implemented(func):
    23     def _inner(*args, **kwargs):
    24         try:
    25             return func(*args, **kwargs)
    26         except NotImplementedError:
    27             return None
    28     update_wrapper(_inner, func)
    29     return _inner
    30 
    31 class IgnoreNotimplementedError(type):
    32     def __new__(cls, name, bases, attrs):
    33         for k,v in attrs.items():
    34             if k.startswith('test'):
    35                 attrs[k] = ignore_not_implemented(v)
    36         return type.__new__(cls, name, bases, attrs)
    378
    389class IntrospectionTests(TestCase):
    39     __metaclass__ = IgnoreNotimplementedError
    4010
    4111    def test_table_names(self):
    4212        tl = connection.introspection.table_names()
    class IntrospectionTests(TestCase): 
    10676            # That's {field_index: (field_index_other_table, other_table)}
    10777            self.assertEqual(relations, {3: (0, Reporter._meta.db_table)})
    10878
     79    @skipUnlessDBFeature('can_introspect_foreign_keys')
    10980    def test_get_key_columns(self):
    11081        cursor = connection.cursor()
    11182        key_columns = connection.introspection.get_key_columns(cursor, Article._meta.db_table)
Back to Top