from sqlalchemy.sql.elements import ColumnClause
from sqlalchemy.sql.elements import TextClause
from sqlalchemy.sql.elements import UnaryExpression
+from sqlalchemy.sql.functions import FunctionElement
from sqlalchemy.types import NULLTYPE
from .base import alter_column
("name", render._render_gen_name(autogen_context, constraint.name))
)
- if alter:
+ def do_expr_where_opts():
args = [
- repr(render._render_gen_name(autogen_context, constraint.name))
+ "(%s, %r)"
+ % (
+ _render_potential_column(sqltext, autogen_context),
+ opstring,
+ )
+ for sqltext, name, opstring in constraint._render_exprs # type:ignore[attr-defined] # noqa
]
- if not has_batch:
- args += [repr(render._ident(constraint.table.name))]
- args.extend(
- [
- "(%s, %r)"
- % (
- _render_potential_column(sqltext, autogen_context),
- opstring,
- )
- for sqltext, name, opstring in constraint._render_exprs # type:ignore[attr-defined] # noqa
- ]
- )
if constraint.where is not None:
args.append(
"where=%s"
)
)
args.extend(["%s=%r" % (k, v) for k, v in opts])
+ return args
+
+ if alter:
+ args = [
+ repr(render._render_gen_name(autogen_context, constraint.name))
+ ]
+ if not has_batch:
+ args += [repr(render._ident(constraint.table.name))]
+ args.extend(do_expr_where_opts())
return "%(prefix)screate_exclude_constraint(%(args)s)" % {
"prefix": render._alembic_autogenerate_prefix(autogen_context),
"args": ", ".join(args),
}
else:
- args = [
- "(%s, %r)"
- % (_render_potential_column(sqltext, autogen_context), opstring)
- for sqltext, name, opstring in constraint._render_exprs
- ]
- if constraint.where is not None:
- args.append(
- "where=%s"
- % render._render_potential_expr(
- constraint.where, autogen_context
- )
- )
- args.extend(["%s=%r" % (k, v) for k, v in opts])
+ args = do_expr_where_opts()
return "%(prefix)sExcludeConstraint(%(args)s)" % {
"prefix": _postgresql_autogenerate_prefix(autogen_context),
"args": ", ".join(args),
def _render_potential_column(
- value: Union[ColumnClause, Column, TextClause],
+ value: Union[ColumnClause, Column, TextClause, FunctionElement],
autogen_context: AutogenContext,
) -> str:
if isinstance(value, ColumnClause):
}
else:
return render._render_potential_expr(
- value, autogen_context, wrap_in_text=isinstance(value, TextClause)
+ value,
+ autogen_context,
+ wrap_in_text=isinstance(value, (TextClause, FunctionElement)),
)
)
def test_add_exclude_constraint(self):
- from sqlalchemy.dialects.postgresql import ExcludeConstraint
-
autogen_context = self.autogen_context
m = MetaData()
)
def test_add_exclude_constraint_case_sensitive(self):
- from sqlalchemy.dialects.postgresql import ExcludeConstraint
-
autogen_context = self.autogen_context
m = MetaData()
)
def test_inline_exclude_constraint(self):
- from sqlalchemy.dialects.postgresql import ExcludeConstraint
-
autogen_context = self.autogen_context
m = MetaData()
)
def test_inline_exclude_constraint_case_sensitive(self):
- from sqlalchemy.dialects.postgresql import ExcludeConstraint
-
autogen_context = self.autogen_context
m = MetaData()
"name='TExclID'))",
)
+ @config.requirements.sqlalchemy_2
+ def test_inline_exclude_constraint_fn(self):
+ """test for #1230"""
+
+ autogen_context = self.autogen_context
+
+ effective_time = Column("effective_time", DateTime(timezone=True))
+ expiry_time = Column("expiry_time", DateTime(timezone=True))
+
+ m = MetaData()
+ t = Table(
+ "TTable",
+ m,
+ effective_time,
+ expiry_time,
+ ExcludeConstraint(
+ (func.tstzrange(effective_time, expiry_time), "&&"),
+ using="gist",
+ ),
+ )
+
+ op_obj = ops.CreateTableOp.from_table(t)
+
+ eq_ignore_whitespace(
+ autogenerate.render_op_text(autogen_context, op_obj),
+ "op.create_table('TTable',sa.Column('effective_time', "
+ "sa.DateTime(timezone=True), nullable=True),"
+ "sa.Column('expiry_time', sa.DateTime(timezone=True), "
+ "nullable=True),postgresql.ExcludeConstraint("
+ "(sa.text('tstzrange(effective_time, expiry_time)'), "
+ "'&&'), using='gist'))",
+ )
+
@config.requirements.sqlalchemy_2
def test_inline_exclude_constraint_text(self):
"""test for #1184.