示例#1
0
    class Meta:

        indexes = ([
            GinIndex(
                OpClass("artist", "gin_trgm_ops"),
                name="core_archivedsong_artist_trgm",
            ),
            GinIndex(
                OpClass("title", "gin_trgm_ops"),
                name="core_archivedsong_title_trgm",
            ),
        ] if connection.vendor == "postgresql" else [])
示例#2
0
 def _get_expressions(self, schema_editor, query):
     expressions = []
     for idx, (expression, operator) in enumerate(self.expressions):
         if isinstance(expression, str):
             expression = F(expression)
         try:
             expression = OpClass(expression, self.opclasses[idx])
         except IndexError:
             pass
         expression = ExclusionConstraintExpression(expression, operator=operator)
         expression.set_wrapper_classes(schema_editor.connection)
         expressions.append(expression)
     return ExpressionList(*expressions).resolve_expression(query)
示例#3
0
 def test_op_class_descending_collation(self):
     collation = connection.features.test_collations.get("non_default")
     if not collation:
         self.skipTest("This backend does not support case-insensitive collations.")
     index_name = "test_op_class_descending_collation"
     index = Index(
         Collate(
             OpClass(Lower("field"), name="text_pattern_ops").desc(nulls_last=True),
             collation=collation,
         ),
         name=index_name,
     )
     with connection.schema_editor() as editor:
         editor.add_index(TextFieldModel, index)
         self.assertIn(
             "COLLATE %s" % editor.quote_name(collation),
             str(index.create_sql(TextFieldModel, editor)),
         )
     with editor.connection.cursor() as cursor:
         cursor.execute(self.get_opclass_query, [index_name])
         self.assertCountEqual(cursor.fetchall(), [("text_pattern_ops", index_name)])
     table = TextFieldModel._meta.db_table
     constraints = self.get_constraints(table)
     self.assertIn(index_name, constraints)
     self.assertEqual(constraints[index_name]["orders"], ["DESC"])
     with connection.schema_editor() as editor:
         editor.remove_index(TextFieldModel, index)
     self.assertNotIn(index_name, self.get_constraints(table))
示例#4
0
 def test_repr(self):
     constraint = ExclusionConstraint(
         name="exclude_overlapping",
         expressions=[
             (F("datespan"), RangeOperators.OVERLAPS),
             (F("room"), RangeOperators.EQUAL),
         ],
     )
     self.assertEqual(
         repr(constraint),
         "<ExclusionConstraint: index_type='GIST' expressions=["
         "(F(datespan), '&&'), (F(room), '=')] name='exclude_overlapping'>",
     )
     constraint = ExclusionConstraint(
         name="exclude_overlapping",
         expressions=[(F("datespan"), RangeOperators.ADJACENT_TO)],
         condition=Q(cancelled=False),
         index_type="SPGiST",
     )
     self.assertEqual(
         repr(constraint),
         "<ExclusionConstraint: index_type='SPGiST' expressions=["
         "(F(datespan), '-|-')] name='exclude_overlapping' "
         "condition=(AND: ('cancelled', False))>",
     )
     constraint = ExclusionConstraint(
         name="exclude_overlapping",
         expressions=[(F("datespan"), RangeOperators.ADJACENT_TO)],
         deferrable=Deferrable.IMMEDIATE,
     )
     self.assertEqual(
         repr(constraint),
         "<ExclusionConstraint: index_type='GIST' expressions=["
         "(F(datespan), '-|-')] name='exclude_overlapping' "
         "deferrable=Deferrable.IMMEDIATE>",
     )
     constraint = ExclusionConstraint(
         name="exclude_overlapping",
         expressions=[(F("datespan"), RangeOperators.ADJACENT_TO)],
         include=["cancelled", "room"],
     )
     self.assertEqual(
         repr(constraint),
         "<ExclusionConstraint: index_type='GIST' expressions=["
         "(F(datespan), '-|-')] name='exclude_overlapping' "
         "include=('cancelled', 'room')>",
     )
     constraint = ExclusionConstraint(
         name="exclude_overlapping",
         expressions=[
             (OpClass("datespan",
                      name="range_ops"), RangeOperators.ADJACENT_TO),
         ],
     )
     self.assertEqual(
         repr(constraint),
         "<ExclusionConstraint: index_type='GIST' expressions=["
         "(OpClass(F(datespan), name=range_ops), '-|-')] "
         "name='exclude_overlapping'>",
     )
示例#5
0
 def test_range_adjacent_opclass(self):
     constraint_name = "ints_adjacent_opclass"
     self.assertNotIn(constraint_name,
                      self.get_constraints(RangesModel._meta.db_table))
     constraint = ExclusionConstraint(
         name=constraint_name,
         expressions=[
             (OpClass("ints",
                      name="range_ops"), RangeOperators.ADJACENT_TO),
         ],
     )
     with connection.schema_editor() as editor:
         editor.add_constraint(RangesModel, constraint)
     constraints = self.get_constraints(RangesModel._meta.db_table)
     self.assertIn(constraint_name, constraints)
     with editor.connection.cursor() as cursor:
         cursor.execute(SchemaTests.get_opclass_query, [constraint_name])
         self.assertEqual(
             cursor.fetchall(),
             [("range_ops", constraint_name)],
         )
     RangesModel.objects.create(ints=(20, 50))
     with self.assertRaises(IntegrityError), transaction.atomic():
         RangesModel.objects.create(ints=(10, 20))
     RangesModel.objects.create(ints=(10, 19))
     RangesModel.objects.create(ints=(51, 60))
     # Drop the constraint.
     with connection.schema_editor() as editor:
         editor.remove_constraint(RangesModel, constraint)
     self.assertNotIn(constraint_name,
                      self.get_constraints(RangesModel._meta.db_table))
示例#6
0
 def test_opclass_func(self):
     constraint = UniqueConstraint(
         OpClass(Lower('scene'), name='text_pattern_ops'),
         name='test_opclass_func',
     )
     with connection.schema_editor() as editor:
         editor.add_constraint(Scene, constraint)
     constraints = self.get_constraints(Scene._meta.db_table)
     self.assertIs(constraints[constraint.name]['unique'], True)
     self.assertIn(constraint.name, constraints)
     with editor.connection.cursor() as cursor:
         cursor.execute(self.get_opclass_query, [constraint.name])
         self.assertEqual(
             cursor.fetchall(),
             [('text_pattern_ops', constraint.name)],
         )
     Scene.objects.create(scene='Scene 10', setting='The dark forest of Ewing')
     with self.assertRaises(IntegrityError), transaction.atomic():
         Scene.objects.create(scene='ScEnE 10', setting="Sir Bedemir's Castle")
     Scene.objects.create(scene='Scene 5', setting="Sir Bedemir's Castle")
     # Drop the constraint.
     with connection.schema_editor() as editor:
         editor.remove_constraint(Scene, constraint)
     self.assertNotIn(constraint.name, self.get_constraints(Scene._meta.db_table))
     Scene.objects.create(scene='ScEnE 10', setting="Sir Bedemir's Castle")
示例#7
0
 class Meta:
     if connection.vendor == "postgresql":
         indexes = ([
             GinIndex(
                 OpClass("query", "gin_trgm_ops"),
                 name="core_archivedquery_query_trgm",
             )
         ] if connection.vendor == "postgresql" else [])
示例#8
0
    def test_range_overlaps_custom(self):
        class TsTzRange(Func):
            function = 'TSTZRANGE'
            output_field = DateTimeRangeField()

        constraint = ExclusionConstraint(
            name='exclude_overlapping_reservations_custom_opclass',
            expressions=[
                (
                    OpClass(TsTzRange('start', 'end', RangeBoundary()),
                            'range_ops'),
                    RangeOperators.OVERLAPS,
                ),
                (OpClass('room', 'gist_int4_ops'), RangeOperators.EQUAL),
            ],
            condition=Q(cancelled=False),
        )
        self._test_range_overlaps(constraint)
示例#9
0
    def test_range_overlaps_custom(self):
        class TsTzRange(Func):
            function = "TSTZRANGE"
            output_field = DateTimeRangeField()

        constraint = ExclusionConstraint(
            name="exclude_overlapping_reservations_custom_opclass",
            expressions=[
                (
                    OpClass(TsTzRange("start", "end", RangeBoundary()),
                            "range_ops"),
                    RangeOperators.OVERLAPS,
                ),
                (OpClass("room", "gist_int4_ops"), RangeOperators.EQUAL),
            ],
            condition=Q(cancelled=False),
        )
        self._test_range_overlaps(constraint)
示例#10
0
 def test_op_class(self):
     index_name = "test_op_class"
     index = Index(
         OpClass(Lower("field"), name="text_pattern_ops"),
         name=index_name,
     )
     with connection.schema_editor() as editor:
         editor.add_index(TextFieldModel, index)
     with editor.connection.cursor() as cursor:
         cursor.execute(self.get_opclass_query, [index_name])
         self.assertCountEqual(cursor.fetchall(), [("text_pattern_ops", index_name)])
示例#11
0
 def test_trigram_op_class_gin_index(self):
     index_name = "trigram_op_class_gin"
     index = GinIndex(OpClass(F("scene"), name="gin_trgm_ops"), name=index_name)
     with connection.schema_editor() as editor:
         editor.add_index(Scene, index)
     with editor.connection.cursor() as cursor:
         cursor.execute(self.get_opclass_query, [index_name])
         self.assertCountEqual(cursor.fetchall(), [("gin_trgm_ops", index_name)])
     constraints = self.get_constraints(Scene._meta.db_table)
     self.assertIn(index_name, constraints)
     self.assertIn(constraints[index_name]["type"], GinIndex.suffix)
     with connection.schema_editor() as editor:
         editor.remove_index(Scene, index)
     self.assertNotIn(index_name, self.get_constraints(Scene._meta.db_table))
示例#12
0
 def test_op_class_descending_partial(self):
     index_name = "test_op_class_descending_partial"
     index = Index(
         OpClass(Lower("field"), name="text_pattern_ops").desc(),
         name=index_name,
         condition=Q(field__contains="China"),
     )
     with connection.schema_editor() as editor:
         editor.add_index(TextFieldModel, index)
     with editor.connection.cursor() as cursor:
         cursor.execute(self.get_opclass_query, [index_name])
         self.assertCountEqual(cursor.fetchall(), [("text_pattern_ops", index_name)])
     constraints = self.get_constraints(TextFieldModel._meta.db_table)
     self.assertIn(index_name, constraints)
     self.assertEqual(constraints[index_name]["orders"], ["DESC"])
示例#13
0
 def test_range_adjacent_opclass_deferrable(self):
     constraint_name = "ints_adjacent_opclass_deferrable"
     self.assertNotIn(constraint_name,
                      self.get_constraints(RangesModel._meta.db_table))
     constraint = ExclusionConstraint(
         name=constraint_name,
         expressions=[
             (OpClass("ints",
                      name="range_ops"), RangeOperators.ADJACENT_TO),
         ],
         deferrable=Deferrable.DEFERRED,
     )
     with connection.schema_editor() as editor:
         editor.add_constraint(RangesModel, constraint)
     self.assertIn(constraint_name,
                   self.get_constraints(RangesModel._meta.db_table))
示例#14
0
 def test_range_adjacent_opclass_condition(self):
     constraint_name = 'ints_adjacent_opclass_condition'
     self.assertNotIn(constraint_name,
                      self.get_constraints(RangesModel._meta.db_table))
     constraint = ExclusionConstraint(
         name=constraint_name,
         expressions=[
             (OpClass('ints',
                      name='range_ops'), RangeOperators.ADJACENT_TO),
         ],
         condition=Q(id__gte=100),
     )
     with connection.schema_editor() as editor:
         editor.add_constraint(RangesModel, constraint)
     self.assertIn(constraint_name,
                   self.get_constraints(RangesModel._meta.db_table))
示例#15
0
 def test_range_adjacent_spgist_opclass_include(self):
     constraint_name = "ints_adjacent_spgist_opclass_include"
     self.assertNotIn(constraint_name,
                      self.get_constraints(RangesModel._meta.db_table))
     constraint = ExclusionConstraint(
         name=constraint_name,
         expressions=[
             (OpClass("ints",
                      name="range_ops"), RangeOperators.ADJACENT_TO),
         ],
         index_type="spgist",
         include=["decimals"],
     )
     with connection.schema_editor() as editor:
         editor.add_constraint(RangesModel, constraint)
     self.assertIn(constraint_name,
                   self.get_constraints(RangesModel._meta.db_table))
示例#16
0
 def test_op_class_descending_partial_tablespace(self):
     index_name = 'test_op_class_descending_partial_tablespace'
     index = Index(
         OpClass(Lower('field').desc(), name='text_pattern_ops'),
         name=index_name,
         condition=Q(field__contains='China'),
         db_tablespace='pg_default',
     )
     with connection.schema_editor() as editor:
         editor.add_index(TextFieldModel, index)
         self.assertIn('TABLESPACE "pg_default" ',
                       str(index.create_sql(TextFieldModel, editor)))
     with editor.connection.cursor() as cursor:
         cursor.execute(self.get_opclass_query, [index_name])
         self.assertCountEqual(cursor.fetchall(),
                               [('text_pattern_ops', index_name)])
     constraints = self.get_constraints(TextFieldModel._meta.db_table)
     self.assertIn(index_name, constraints)
     self.assertEqual(constraints[index_name]['orders'], ['DESC'])
示例#17
0
 def test_tsvector_op_class_gist_index(self):
     index_name = "tsvector_op_class_gist"
     index = GistIndex(
         OpClass(
             SearchVector("scene", "setting", config="english"),
             name="tsvector_ops",
         ),
         name=index_name,
     )
     with connection.schema_editor() as editor:
         editor.add_index(Scene, index)
         sql = index.create_sql(Scene, editor)
     table = Scene._meta.db_table
     constraints = self.get_constraints(table)
     self.assertIn(index_name, constraints)
     self.assertIn(constraints[index_name]["type"], GistIndex.suffix)
     self.assertIs(sql.references_column(table, "scene"), True)
     self.assertIs(sql.references_column(table, "setting"), True)
     with connection.schema_editor() as editor:
         editor.remove_index(Scene, index)
     self.assertNotIn(index_name, self.get_constraints(table))