Copy of ExcludeConstraint's as part of tometadata fails with column-based expressions.

33 views
Skip to first unread message

horema...@gmail.com

unread,
Jan 18, 2021, 10:14:48 AM1/18/21
to sqlalchemy

Hi,

we noticed that the copying of ExcludeConstraints as part of a tometadata invocation fails for constraints with column-based expressions. The copy implementation of ExcludeConstraint passes the strname's of its columns to the construction of the new constraint, which is fine for regular columns, but not for more complex expressions.
We've added a small test case (in test_metadata) that reproduces the failure below.
We also implemented a temporary solution that seems to fix the issue by passing copies of the constraint's column expressions instead.
We are on version 1.3.18.

Temporary solution:
```python
#elements = [(_copy_expression(col_expr, self.table, kw['target_table']), self.operators[col]) for col, col_expr in zip(self.columns.keys(), self.columns.values())]
        elements = [(col, self.operators[col]) for col in self.columns.keys()]
```

Test case
```python
from sqlalchemy.dialects.postgresql import ExcludeConstraint
from sqlalchemy import column, Date, literal_column

class ToMetaDataExcludeConstraint(fixtures.TestBase, ComparesTables):
    @testing.requires.check_constraints
    def test_copy(self):
        from sqlalchemy.testing.schema import Table

        meta = MetaData()

        table = Table(
            "mytable",
            meta,
            Column("myid", Integer, Sequence("foo_id_seq"), primary_key=True),
            Column("valid_from_date", Date(), nullable=True),
            Column("valid_thru_date", Date(), nullable=True),
            ExcludeConstraint(
                (literal_column("daterange(valid_from_date, valid_thru_date, '[]')"), '&&'),
                where=column("valid_from_date") <= column("valid_thru_date"),
                name='ex_mytable_valid_date_range',
                deferrable=True, initially='deferred'
            )
        )

        meta.create_all(testing.db)
       
        try:
            meta2 = MetaData()
            table_c = table.tometadata(meta2)
        finally:
            meta.drop_all(testing.db)
```


horema...@gmail.com

unread,
Jan 18, 2021, 10:16:41 AM1/18/21
to sqlalchemy
Here's the stacktrace of the test case's failure:

=============================================== FAILURES ================================================
_________________________________ ToMetaDataExcludeConstraint.test_copy _________________________________
Traceback (most recent call last):
  File "/home/jeffh/workspace/vortex-workspace/vfinance/subrepos/SQLAlchemy-1.3.18/test/sql/test_metadata.py", line 5238, in test_copy
    table_c = table.tometadata(meta2)
  File "/home/jeffh/workspace/vortex-workspace/vfinance/subrepos/SQLAlchemy-1.3.18/test/../lib/sqlalchemy/sql/schema.py", line 1063, in tometadata
    table.append_constraint(
  File "/home/jeffh/workspace/vortex-workspace/vfinance/subrepos/SQLAlchemy-1.3.18/test/../lib/sqlalchemy/sql/schema.py", line 867, in append_constraint
    constraint._set_parent_with_dispatch(self)
  File "/home/jeffh/workspace/vortex-workspace/vfinance/subrepos/SQLAlchemy-1.3.18/test/../lib/sqlalchemy/sql/base.py", line 463, in _set_parent_with_dispatch
    self._set_parent(parent)
  File "/home/jeffh/workspace/vortex-workspace/vfinance/subrepos/SQLAlchemy-1.3.18/test/../lib/sqlalchemy/sql/schema.py", line 3065, in _set_parent
    ColumnCollectionMixin._set_parent(self, table)
  File "/home/jeffh/workspace/vortex-workspace/vfinance/subrepos/SQLAlchemy-1.3.18/test/../lib/sqlalchemy/sql/schema.py", line 3022, in _set_parent
    for col in self._col_expressions(table):
  File "/home/jeffh/workspace/vortex-workspace/vfinance/subrepos/SQLAlchemy-1.3.18/test/../lib/sqlalchemy/sql/schema.py", line 3016, in _col_expressions
    return [
  File "/home/jeffh/workspace/vortex-workspace/vfinance/subrepos/SQLAlchemy-1.3.18/test/../lib/sqlalchemy/sql/schema.py", line 3017, in <listcomp>
    table.c[col] if isinstance(col, util.string_types) else col
  File "/home/jeffh/workspace/vortex-workspace/vfinance/subrepos/SQLAlchemy-1.3.18/test/../lib/sqlalchemy/util/_collections.py", line 194, in __getitem__
    return self._data[key]
KeyError: "daterange(valid_from_date, valid_thru_date, '[]')"
======================================== short test summary info ========================================
FAILED test/sql/test_metadata.py::ToMetaDataExcludeConstraint::test_copy - KeyError: "daterange(valid_...
Op maandag 18 januari 2021 om 16:14:48 UTC+1 schreef horema...@gmail.com:

Gord Thompson

unread,
Jan 18, 2021, 4:00:29 PM1/18/21
to sqlalchemy
Issue created: 

Thanks for reporting this.
Reply all
Reply to author
Forward
0 new messages