test_ddl_references.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. from django.db import connection
  2. from django.db.backends.ddl_references import (
  3. Columns, Expressions, ForeignKeyName, IndexName, Statement, Table,
  4. )
  5. from django.db.models import ExpressionList, F
  6. from django.db.models.functions import Upper
  7. from django.db.models.indexes import IndexExpression
  8. from django.test import SimpleTestCase, TransactionTestCase
  9. from .models import Person
  10. class TableTests(SimpleTestCase):
  11. def setUp(self):
  12. self.reference = Table('table', lambda table: table.upper())
  13. def test_references_table(self):
  14. self.assertIs(self.reference.references_table('table'), True)
  15. self.assertIs(self.reference.references_table('other'), False)
  16. def test_rename_table_references(self):
  17. self.reference.rename_table_references('other', 'table')
  18. self.assertIs(self.reference.references_table('table'), True)
  19. self.assertIs(self.reference.references_table('other'), False)
  20. self.reference.rename_table_references('table', 'other')
  21. self.assertIs(self.reference.references_table('table'), False)
  22. self.assertIs(self.reference.references_table('other'), True)
  23. def test_repr(self):
  24. self.assertEqual(repr(self.reference), "<Table 'TABLE'>")
  25. def test_str(self):
  26. self.assertEqual(str(self.reference), 'TABLE')
  27. class ColumnsTests(TableTests):
  28. def setUp(self):
  29. self.reference = Columns(
  30. 'table', ['first_column', 'second_column'], lambda column: column.upper()
  31. )
  32. def test_references_column(self):
  33. self.assertIs(self.reference.references_column('other', 'first_column'), False)
  34. self.assertIs(self.reference.references_column('table', 'third_column'), False)
  35. self.assertIs(self.reference.references_column('table', 'first_column'), True)
  36. def test_rename_column_references(self):
  37. self.reference.rename_column_references('other', 'first_column', 'third_column')
  38. self.assertIs(self.reference.references_column('table', 'first_column'), True)
  39. self.assertIs(self.reference.references_column('table', 'third_column'), False)
  40. self.assertIs(self.reference.references_column('other', 'third_column'), False)
  41. self.reference.rename_column_references('table', 'third_column', 'first_column')
  42. self.assertIs(self.reference.references_column('table', 'first_column'), True)
  43. self.assertIs(self.reference.references_column('table', 'third_column'), False)
  44. self.reference.rename_column_references('table', 'first_column', 'third_column')
  45. self.assertIs(self.reference.references_column('table', 'first_column'), False)
  46. self.assertIs(self.reference.references_column('table', 'third_column'), True)
  47. def test_repr(self):
  48. self.assertEqual(repr(self.reference), "<Columns 'FIRST_COLUMN, SECOND_COLUMN'>")
  49. def test_str(self):
  50. self.assertEqual(str(self.reference), 'FIRST_COLUMN, SECOND_COLUMN')
  51. class IndexNameTests(ColumnsTests):
  52. def setUp(self):
  53. def create_index_name(table_name, column_names, suffix):
  54. return ', '.join("%s_%s_%s" % (table_name, column_name, suffix) for column_name in column_names)
  55. self.reference = IndexName(
  56. 'table', ['first_column', 'second_column'], 'suffix', create_index_name
  57. )
  58. def test_repr(self):
  59. self.assertEqual(repr(self.reference), "<IndexName 'table_first_column_suffix, table_second_column_suffix'>")
  60. def test_str(self):
  61. self.assertEqual(str(self.reference), 'table_first_column_suffix, table_second_column_suffix')
  62. class ForeignKeyNameTests(IndexNameTests):
  63. def setUp(self):
  64. def create_foreign_key_name(table_name, column_names, suffix):
  65. return ', '.join("%s_%s_%s" % (table_name, column_name, suffix) for column_name in column_names)
  66. self.reference = ForeignKeyName(
  67. 'table', ['first_column', 'second_column'],
  68. 'to_table', ['to_first_column', 'to_second_column'],
  69. '%(to_table)s_%(to_column)s_fk',
  70. create_foreign_key_name,
  71. )
  72. def test_references_table(self):
  73. super().test_references_table()
  74. self.assertIs(self.reference.references_table('to_table'), True)
  75. def test_references_column(self):
  76. super().test_references_column()
  77. self.assertIs(self.reference.references_column('to_table', 'second_column'), False)
  78. self.assertIs(self.reference.references_column('to_table', 'to_second_column'), True)
  79. def test_rename_table_references(self):
  80. super().test_rename_table_references()
  81. self.reference.rename_table_references('to_table', 'other_to_table')
  82. self.assertIs(self.reference.references_table('other_to_table'), True)
  83. self.assertIs(self.reference.references_table('to_table'), False)
  84. def test_rename_column_references(self):
  85. super().test_rename_column_references()
  86. self.reference.rename_column_references('to_table', 'second_column', 'third_column')
  87. self.assertIs(self.reference.references_column('table', 'second_column'), True)
  88. self.assertIs(self.reference.references_column('to_table', 'to_second_column'), True)
  89. self.reference.rename_column_references('to_table', 'to_first_column', 'to_third_column')
  90. self.assertIs(self.reference.references_column('to_table', 'to_first_column'), False)
  91. self.assertIs(self.reference.references_column('to_table', 'to_third_column'), True)
  92. def test_repr(self):
  93. self.assertEqual(
  94. repr(self.reference),
  95. "<ForeignKeyName 'table_first_column_to_table_to_first_column_fk, "
  96. "table_second_column_to_table_to_first_column_fk'>"
  97. )
  98. def test_str(self):
  99. self.assertEqual(
  100. str(self.reference),
  101. 'table_first_column_to_table_to_first_column_fk, '
  102. 'table_second_column_to_table_to_first_column_fk'
  103. )
  104. class MockReference:
  105. def __init__(self, representation, referenced_tables, referenced_columns):
  106. self.representation = representation
  107. self.referenced_tables = referenced_tables
  108. self.referenced_columns = referenced_columns
  109. def references_table(self, table):
  110. return table in self.referenced_tables
  111. def references_column(self, table, column):
  112. return (table, column) in self.referenced_columns
  113. def rename_table_references(self, old_table, new_table):
  114. if old_table in self.referenced_tables:
  115. self.referenced_tables.remove(old_table)
  116. self.referenced_tables.add(new_table)
  117. def rename_column_references(self, table, old_column, new_column):
  118. column = (table, old_column)
  119. if column in self.referenced_columns:
  120. self.referenced_columns.remove(column)
  121. self.referenced_columns.add((table, new_column))
  122. def __str__(self):
  123. return self.representation
  124. class StatementTests(SimpleTestCase):
  125. def test_references_table(self):
  126. statement = Statement('', reference=MockReference('', {'table'}, {}), non_reference='')
  127. self.assertIs(statement.references_table('table'), True)
  128. self.assertIs(statement.references_table('other'), False)
  129. def test_references_column(self):
  130. statement = Statement('', reference=MockReference('', {}, {('table', 'column')}), non_reference='')
  131. self.assertIs(statement.references_column('table', 'column'), True)
  132. self.assertIs(statement.references_column('other', 'column'), False)
  133. def test_rename_table_references(self):
  134. reference = MockReference('', {'table'}, {})
  135. statement = Statement('', reference=reference, non_reference='')
  136. statement.rename_table_references('table', 'other')
  137. self.assertEqual(reference.referenced_tables, {'other'})
  138. def test_rename_column_references(self):
  139. reference = MockReference('', {}, {('table', 'column')})
  140. statement = Statement('', reference=reference, non_reference='')
  141. statement.rename_column_references('table', 'column', 'other')
  142. self.assertEqual(reference.referenced_columns, {('table', 'other')})
  143. def test_repr(self):
  144. reference = MockReference('reference', {}, {})
  145. statement = Statement("%(reference)s - %(non_reference)s", reference=reference, non_reference='non_reference')
  146. self.assertEqual(repr(statement), "<Statement 'reference - non_reference'>")
  147. def test_str(self):
  148. reference = MockReference('reference', {}, {})
  149. statement = Statement("%(reference)s - %(non_reference)s", reference=reference, non_reference='non_reference')
  150. self.assertEqual(str(statement), 'reference - non_reference')
  151. class ExpressionsTests(TransactionTestCase):
  152. available_apps = []
  153. def setUp(self):
  154. compiler = Person.objects.all().query.get_compiler(connection.alias)
  155. self.editor = connection.schema_editor()
  156. self.expressions = Expressions(
  157. table=Person._meta.db_table,
  158. expressions=ExpressionList(
  159. IndexExpression(F('first_name')),
  160. IndexExpression(F('last_name').desc()),
  161. IndexExpression(Upper('last_name')),
  162. ).resolve_expression(compiler.query),
  163. compiler=compiler,
  164. quote_value=self.editor.quote_value,
  165. )
  166. def test_references_table(self):
  167. self.assertIs(self.expressions.references_table(Person._meta.db_table), True)
  168. self.assertIs(self.expressions.references_table('other'), False)
  169. def test_references_column(self):
  170. table = Person._meta.db_table
  171. self.assertIs(self.expressions.references_column(table, 'first_name'), True)
  172. self.assertIs(self.expressions.references_column(table, 'last_name'), True)
  173. self.assertIs(self.expressions.references_column(table, 'other'), False)
  174. def test_rename_table_references(self):
  175. table = Person._meta.db_table
  176. self.expressions.rename_table_references(table, 'other')
  177. self.assertIs(self.expressions.references_table(table), False)
  178. self.assertIs(self.expressions.references_table('other'), True)
  179. self.assertIn(
  180. '%s.%s' % (
  181. self.editor.quote_name('other'),
  182. self.editor.quote_name('first_name'),
  183. ),
  184. str(self.expressions),
  185. )
  186. def test_rename_column_references(self):
  187. table = Person._meta.db_table
  188. self.expressions.rename_column_references(table, 'first_name', 'other')
  189. self.assertIs(self.expressions.references_column(table, 'other'), True)
  190. self.assertIs(self.expressions.references_column(table, 'first_name'), False)
  191. self.assertIn(
  192. '%s.%s' % (self.editor.quote_name(table), self.editor.quote_name('other')),
  193. str(self.expressions),
  194. )
  195. def test_str(self):
  196. table_name = self.editor.quote_name(Person._meta.db_table)
  197. expected_str = '%s.%s, %s.%s DESC, (UPPER(%s.%s))' % (
  198. table_name,
  199. self.editor.quote_name('first_name'),
  200. table_name,
  201. self.editor.quote_name('last_name'),
  202. table_name,
  203. self.editor.quote_name('last_name'),
  204. )
  205. self.assertEqual(str(self.expressions), expected_str)