def _render_potential_expr(
value: Any,
autogen_context: AutogenContext,
+ *,
wrap_in_text: bool = True,
is_server_default: bool = False,
+ is_index: bool = False,
) -> str:
if isinstance(value, sql.ClauseElement):
if wrap_in_text:
return template % {
"prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
"sql": autogen_context.migration_context.impl.render_ddl_sql_expr(
- value, is_server_default=is_server_default
+ value, is_server_default=is_server_default, is_index=is_index
),
}
return [
repr(_ident(getattr(exp, "name", None)))
if isinstance(exp, sa_schema.Column)
- else _render_potential_expr(exp, autogen_context)
+ else _render_potential_expr(exp, autogen_context, is_index=True)
for exp in idx.expressions
]
compile_kwargs={"literal_binds": True, "include_table": False},
).string
+ def render_ddl_sql_expr(
+ self,
+ expr: ClauseElement,
+ is_server_default: bool = False,
+ is_index: bool = False,
+ **kw: Any,
+ ) -> str:
+ """Render a SQL expression that is typically a server default,
+ index expression, etc.
+
+ """
+
+ # apply self_group to index expressions;
+ # see https://github.com/sqlalchemy/sqlalchemy/blob/
+ # 82fa95cfce070fab401d020c6e6e4a6a96cc2578/
+ # lib/sqlalchemy/dialects/postgresql/base.py#L2261
+ if is_index and not isinstance(expr, ColumnClause):
+ expr = expr.self_group()
+
+ return super().render_ddl_sql_expr(
+ expr, is_server_default=is_server_default, is_index=is_index, **kw
+ )
+
def render_type(
self, type_: TypeEngine, autogen_context: AutogenContext
) -> Union[str, Literal[False]]:
--- /dev/null
+.. change::
+ :tags: bug, postgresql
+ :tickets: 1322
+
+ Fixed autogen render issue where expressions inside of indexes for PG need
+ to be double-parenthesized, meaning a single parens must be present within
+ the generated ``text()`` construct.
"postgresql.JSONB(astext_type=sa.Text())",
)
+ def test_jsonb_expression_in_index(self):
+ """test #1322"""
+
+ m = MetaData()
+ t = Table("tbl", m, Column("c", JSONB()))
+ idx = Index("my_idx", t.c.c["foo"].astext)
+
+ eq_ignore_whitespace(
+ autogenerate.render.render_op_text(
+ self.autogen_context,
+ ops.CreateIndexOp.from_index(idx),
+ ),
+ "op.create_index('my_idx', 'tbl', "
+ "[sa.text(\"(c ->> 'foo')\")], unique=False)",
+ )
+
@config.requirements.nulls_not_distinct_sa
def test_render_unique_nulls_not_distinct_constraint(self):
m = MetaData()