Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions alembic/ddl/postgresql.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
from sqlalchemy.dialects.postgresql.hstore import HSTORE
from sqlalchemy.dialects.postgresql.json import JSON
from sqlalchemy.dialects.postgresql.json import JSONB
from sqlalchemy.dialects.postgresql.named_types import DOMAIN
from sqlalchemy.sql.elements import ClauseElement
from sqlalchemy.sql.elements import ColumnElement
from sqlalchemy.sql.elements import quoted_name
Expand Down Expand Up @@ -515,6 +516,38 @@ def _render_JSONB_type(
),
)

def _render_DOMAIN_type(
self, type_: DOMAIN, autogen_context: AutogenContext
) -> str:
prefix = _postgresql_autogenerate_prefix(autogen_context)
args = [
repr(render._ident(type_.name)),
render._repr_type(type_.data_type, autogen_context),
]
if type_.collation is not None:
args.append("collation=%r" % type_.collation)
if type_.default is not None:
args.append(
"default=%s"
% render._render_potential_expr(
type_.default, autogen_context, wrap_in_element=True
)
)
if type_.constraint_name is not None:
args.append("constraint_name=%r" % type_.constraint_name)
if type_.not_null:
args.append("not_null=True")
if type_.check is not None:
args.append(
"check=%s"
% render._render_potential_expr(
type_.check, autogen_context, wrap_in_element=False
)
)
if type_.create_type is not True:
args.append("create_type=False")
return "%sDOMAIN(%s)" % (prefix, ", ".join(args))


class PostgresqlColumnType(AlterColumn):
def __init__(
Expand Down
12 changes: 12 additions & 0 deletions docs/build/unreleased/1360.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.. change::
:tags: bug, autogenerate, postgresql
:tickets: 1360

Fixed rendering of the PostgreSQL
:class:`~sqlalchemy.dialects.postgresql.DOMAIN` type in autogenerated
migration scripts. Previously the type was rendered using ``repr()``,
which omitted the ``check``, ``not_null``, ``default``, ``collation``,
``constraint_name`` and ``create_type`` arguments and did not apply a
dialect prefix to the underlying data type. The full set of arguments
is now rendered and the underlying data type is rendered using the
standard type-rendering logic.
39 changes: 39 additions & 0 deletions tests/test_postgresql.py
Original file line number Diff line number Diff line change
Expand Up @@ -1361,6 +1361,45 @@ def test_jsonb_type(self):
"postgresql.JSONB(astext_type=sa.Text())",
)

@config.requirements.sqlalchemy_2
def test_domain_type(self):
"""test #1360"""
from sqlalchemy.dialects.postgresql import CITEXT
from sqlalchemy.dialects.postgresql import DOMAIN

eq_ignore_whitespace(
autogenerate.render._repr_type(
DOMAIN("email", CITEXT(), check=r"value ~ '^my_.*$'"),
self.autogen_context,
),
"postgresql.DOMAIN('email', postgresql.CITEXT(), "
"check=\"value ~ '^my_.*$'\")",
)

@config.requirements.sqlalchemy_2
def test_domain_type_full(self):
"""test #1360"""
from sqlalchemy.dialects.postgresql import DOMAIN

eq_ignore_whitespace(
autogenerate.render._repr_type(
DOMAIN(
"mydom",
String(),
collation="C",
default="x",
constraint_name="ck",
not_null=True,
check="value > 0",
create_type=False,
),
self.autogen_context,
),
"postgresql.DOMAIN('mydom', sa.String(), collation='C', "
"default='x', constraint_name='ck', not_null=True, "
"check='value > 0', create_type=False)",
)

def test_jsonb_expression_in_index(self):
"""test #1322"""

Expand Down