--- /dev/null
+.. change::
+ :tags: usecase, postgresql
+ :tickets: 5604
+ :versions: 1.4.0b2
+
+ Added new parameter :paramref:`_postgresql.ExcludeConstraint.ops` to the
+ :class:`_postgresql.ExcludeConstraint` object, to support operator class
+ specification with this constraint. Pull request courtesy Alon Menczer.
Index('my_index', my_table.c.id, postgresql_where=my_table.c.value > 10)
+.. _postgresql_operator_classes:
+
Operator Classes
^^^^^^^^^^^^^^^^
'id': 'int4_ops'
})
-Note that the keys in the ``postgresql_ops`` dictionary are the "key" name of
-the :class:`_schema.Column`, i.e. the name used to access it from the ``.c``
-collection of :class:`_schema.Table`,
-which can be configured to be different than
-the actual name of the column as expressed in the database.
+Note that the keys in the ``postgresql_ops`` dictionaries are the
+"key" name of the :class:`_schema.Column`, i.e. the name used to access it from
+the ``.c`` collection of :class:`_schema.Table`, which can be configured to be
+different than the actual name of the column as expressed in the database.
If ``postgresql_ops`` is to be used against a complex SQL expression such
as a function call, then to apply to the column it must be given a label
'id': 'int4_ops'
})
+Operator classes are also supported by the
+:class:`_postgresql.ExcludeConstraint` construct using the
+:paramref:`_postgresql.ExcludeConstraint.ops` parameter. See that parameter for
+details.
+
+.. versionadded:: 1.3.20 added support for operator classes with
+ :class:`_postgresql.ExcludeConstraint`.
+
Index Types
^^^^^^^^^^^
elements = []
for expr, name, op in constraint._render_exprs:
kw["include_table"] = False
- elements.append(
- "%s WITH %s" % (self.sql_compiler.process(expr, **kw), op)
+ exclude_element = self.sql_compiler.process(expr, **kw) + (
+ (" " + constraint.ops[expr.key])
+ if hasattr(expr, "key") and expr.key in constraint.ops
+ else ""
)
+
+ elements.append("%s WITH %s" % (exclude_element, op))
text += "EXCLUDE USING %s (%s)" % (
self.preparer.validate_sql_phrase(
constraint.using, IDX_USING
const = ExcludeConstraint(
(Column('period'), '&&'),
(Column('group'), '='),
- where=(Column('group') != 'some group')
+ where=(Column('group') != 'some group'),
+ ops={'group': 'my_operator_class'}
)
The constraint is normally embedded into the :class:`_schema.Table`
(some_table.c.period, '&&'),
(some_table.c.group, '='),
where=some_table.c.group != 'some group',
- name='some_table_excl_const'
+ name='some_table_excl_const',
+ ops={'group': 'my_operator_class'}
)
)
If set, emit WHERE <predicate> when issuing DDL
for this constraint.
+ :param ops:
+ Optional dictionary. Used to define operator classes for the
+ elements; works the same way as that of the
+ :ref:`postgresql_ops <postgresql_operator_classes>`
+ parameter specified to the :class:`_schema.Index` construct.
+
+ .. versionadded:: 1.3.21
+
+ .. seealso::
+
+ :ref:`postgresql_operator_classes` - general description of how
+ PostgreSQL operator classes are specified.
+
"""
columns = []
render_exprs = []
if where is not None:
self.where = coercions.expect(roles.StatementOptionRole, where)
+ self.ops = kw.get("ops", {})
+
def _set_parent(self, table, **kw):
super(ExcludeConstraint, self)._set_parent(table)
where="room > 100",
deferrable=True,
initially="immediate",
+ ops={"room": "my_opclass"},
)
tbl.append_constraint(cons)
self.assert_compile(
schema.AddConstraint(cons),
"ALTER TABLE testtbl ADD CONSTRAINT my_name "
"EXCLUDE USING gist "
- "(room WITH =, during WITH "
+ "(room my_opclass WITH =, during WITH "
"&&) WHERE "
"(room > 100) DEFERRABLE INITIALLY immediate",
dialect=postgresql.dialect(),
dialect=postgresql.dialect(),
)
+ def test_exclude_constraint_ops_many(self):
+ m = MetaData()
+ tbl = Table(
+ "testtbl", m, Column("room", String), Column("during", TSRANGE)
+ )
+ cons = ExcludeConstraint(
+ ("room", "="),
+ ("during", "&&"),
+ ops={"room": "first_opsclass", "during": "second_opclass"},
+ )
+ tbl.append_constraint(cons)
+ self.assert_compile(
+ schema.AddConstraint(cons),
+ "ALTER TABLE testtbl ADD EXCLUDE USING gist "
+ "(room first_opsclass WITH =, during second_opclass WITH &&)",
+ dialect=postgresql.dialect(),
+ )
+
def test_substring(self):
self.assert_compile(
func.substring("abc", 1, 2),