1
from __future__ import absolute_import
1
from __future__ import absolute_import, unicode_literals
3
3
from functools import update_wrapper
5
5
from django.db import connection
6
6
from django.test import TestCase, skipUnlessDBFeature, skipIfDBFeature
7
from django.utils import six, unittest
8
9
from .models import Reporter, Article
11
if connection.vendor == 'oracle':
12
expectedFailureOnOracle = unittest.expectedFailure
14
expectedFailureOnOracle = lambda f: f
11
17
# The introspection module is optional, so methods tested here might raise
12
18
# NotImplementedError. This is perfectly acceptable behavior for the backend
13
19
# in question, but the tests need to handle this without failing. Ideally we'd
17
23
# wrapper that ignores the exception.
19
25
# The metaclass is just for fun.
22
28
def ignore_not_implemented(func):
23
29
def _inner(*args, **kwargs):
28
34
update_wrapper(_inner, func)
31
38
class IgnoreNotimplementedError(type):
32
39
def __new__(cls, name, bases, attrs):
33
for k,v in attrs.items():
40
for k, v in attrs.items():
34
41
if k.startswith('test'):
35
42
attrs[k] = ignore_not_implemented(v)
36
43
return type.__new__(cls, name, bases, attrs)
38
class IntrospectionTests(TestCase):
39
__metaclass__ = IgnoreNotimplementedError
46
class IntrospectionTests(six.with_metaclass(IgnoreNotimplementedError, TestCase)):
41
47
def test_table_names(self):
42
48
tl = connection.introspection.table_names()
49
self.assertEqual(tl, sorted(tl))
43
50
self.assertTrue(Reporter._meta.db_table in tl,
44
51
"'%s' isn't in table_list()." % Reporter._meta.db_table)
45
52
self.assertTrue(Article._meta.db_table in tl,
89
96
['IntegerField', 'CharField', 'CharField', 'CharField', 'BigIntegerField']
99
# The following test fails on Oracle due to #17202 (can't correctly
100
# inspect the length of character columns).
101
@expectedFailureOnOracle
102
def test_get_table_description_col_lengths(self):
103
cursor = connection.cursor()
104
desc = connection.introspection.get_table_description(cursor, Reporter._meta.db_table)
106
[r[3] for r in desc if datatype(r[1], r) == 'CharField'],
92
110
# Oracle forces null=True under the hood in some cases (see
93
111
# https://docs.djangoproject.com/en/dev/ref/databases/#null-and-empty-strings)
94
112
# so its idea about null_ok in cursor.description is different from ours.
124
142
def test_get_key_columns(self):
125
143
cursor = connection.cursor()
126
144
key_columns = connection.introspection.get_key_columns(cursor, Article._meta.db_table)
127
self.assertEqual(key_columns, [(u'reporter_id', Reporter._meta.db_table, u'id')])
145
self.assertEqual(key_columns, [('reporter_id', Reporter._meta.db_table, 'id')])
129
147
def test_get_primary_key_column(self):
130
148
cursor = connection.cursor()
131
149
primary_key_column = connection.introspection.get_primary_key_column(cursor, Article._meta.db_table)
132
self.assertEqual(primary_key_column, u'id')
150
self.assertEqual(primary_key_column, 'id')
134
152
def test_get_indexes(self):
135
153
cursor = connection.cursor()
136
154
indexes = connection.introspection.get_indexes(cursor, Article._meta.db_table)
137
155
self.assertEqual(indexes['reporter_id'], {'unique': False, 'primary_key': False})
157
def test_get_indexes_multicol(self):
159
Test that multicolumn indexes are not included in the introspection
162
cursor = connection.cursor()
163
indexes = connection.introspection.get_indexes(cursor, Reporter._meta.db_table)
164
self.assertNotIn('first_name', indexes)
165
self.assertIn('id', indexes)
140
168
def datatype(dbtype, description):
141
169
"""Helper to convert a data type into a string."""