diff options
| author | cheremnov <32135863+cheremnov@users.noreply.github.com> | 2022-02-24 02:22:33 -0500 |
|---|---|---|
| committer | Federico Caselli <cfederico87@gmail.com> | 2022-06-29 09:13:37 +0000 |
| commit | 5fb63bc1423e75812a24e809d16731a3282c2a12 (patch) | |
| tree | 2e3293890e1b326146ea8848ceac9a65fae9490b /lib/sqlalchemy/testing | |
| parent | 6a560cf03c302d2ebd9ae7c7dc4d587983096ba4 (diff) | |
| download | sqlalchemy-5fb63bc1423e75812a24e809d16731a3282c2a12.tar.gz | |
Comments on (named) constraints
Adds support for comments on named constraints, including `ForeignKeyConstraint`, `PrimaryKeyConstraint`, `CheckConstraint`, `UniqueConstraint`, solving the [Issue 5667](https://github.com/sqlalchemy/sqlalchemy/issues/5667).
Supports only PostgreSQL backend.
### Description
Following the example of [Issue 1546](https://github.com/sqlalchemy/sqlalchemy/issues/1546), supports comments on constraints. Specifically, enables comments on _named_ ones — as I get it, PostgreSQL prohibits comments on unnamed constraints.
Enables setting the comments for named constraints like this:
```
Table(
'example', metadata,
Column('id', Integer),
Column('data', sa.String(30)),
PrimaryKeyConstraint(
"id", name="id_pk", comment="id_pk comment"
),
CheckConstraint('id < 100', name="cc1", comment="Id value can't exceed 100"),
UniqueConstraint(['data'], name="uc1", comment="Must have unique data field"),
)
```
Provides the DDL representation for constraint comments and routines to create and drop them. Class `.Inspector` reflects constraint comments via methods like `get_check_constraints` .
### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)
-->
This pull request is:
- [ ] A documentation / typographical error fix
- [ ] A short code fix
- [x] A new feature implementation
- Solves the issue 5667.
- The commit message includes `Fixes: 5667`.
- Includes tests based on comment reflection.
**Have a nice day!**
Fixes: #5667
Closes: #7742
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/7742
Pull-request-sha: 42a5d3c3e9ccf9a9d5397fd007aeab0854f66130
Change-Id: Ia60f578595afdbd6089541c9a00e37997ef78ad3
Diffstat (limited to 'lib/sqlalchemy/testing')
| -rw-r--r-- | lib/sqlalchemy/testing/requirements.py | 7 | ||||
| -rw-r--r-- | lib/sqlalchemy/testing/suite/test_reflection.py | 122 |
2 files changed, 85 insertions, 44 deletions
diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py index 038f6e9bd..c0a2bcf65 100644 --- a/lib/sqlalchemy/testing/requirements.py +++ b/lib/sqlalchemy/testing/requirements.py @@ -625,6 +625,13 @@ class SuiteRequirements(Requirements): @property def comment_reflection(self): + """Indicates if the database support table comment reflection""" + return exclusions.closed() + + @property + def constraint_comment_reflection(self): + """indicates if the database support constraint on constraints + and their reflection""" return exclusions.closed() @property diff --git a/lib/sqlalchemy/testing/suite/test_reflection.py b/lib/sqlalchemy/testing/suite/test_reflection.py index 7b8e2aa8b..6c71696a0 100644 --- a/lib/sqlalchemy/testing/suite/test_reflection.py +++ b/lib/sqlalchemy/testing/suite/test_reflection.py @@ -415,35 +415,29 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): schema_prefix = "" if testing.requires.self_referential_foreign_keys.enabled: - users = Table( - "users", - metadata, - Column("user_id", sa.INT, primary_key=True), - Column("test1", sa.CHAR(5), nullable=False), - Column("test2", sa.Float(), nullable=False), - Column( - "parent_user_id", - sa.Integer, - sa.ForeignKey( - "%susers.user_id" % schema_prefix, name="user_id_fk" - ), + parent_id_args = ( + ForeignKey( + "%susers.user_id" % schema_prefix, name="user_id_fk" ), - sa.CheckConstraint("test2 > 0", name="test2_gt_zero"), - schema=schema, - test_needs_fk=True, ) else: - users = Table( - "users", - metadata, - Column("user_id", sa.INT, primary_key=True), - Column("test1", sa.CHAR(5), nullable=False), - Column("test2", sa.Float(), nullable=False), - Column("parent_user_id", sa.Integer), - sa.CheckConstraint("test2 > 0", name="test2_gt_zero"), - schema=schema, - test_needs_fk=True, - ) + parent_id_args = () + users = Table( + "users", + metadata, + Column("user_id", sa.INT, primary_key=True), + Column("test1", sa.CHAR(5), nullable=False), + Column("test2", sa.Float(), nullable=False), + Column("parent_user_id", sa.Integer, *parent_id_args), + sa.CheckConstraint( + "test2 > 0", + name="zz_test2_gt_zero", + comment="users check constraint", + ), + sa.CheckConstraint("test2 <= 1000"), + schema=schema, + test_needs_fk=True, + ) Table( "dingalings", @@ -452,18 +446,27 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): Column( "address_id", sa.Integer, - sa.ForeignKey( + ForeignKey( "%semail_addresses.address_id" % schema_prefix, - name="email_add_id_fg", + name="zz_email_add_id_fg", + comment="di fk comment", ), ), + Column( + "id_user", + sa.Integer, + ForeignKey("%susers.user_id" % schema_prefix), + ), Column("data", sa.String(30), unique=True), sa.CheckConstraint( "address_id > 0 AND address_id < 1000", name="address_id_gt_zero", ), sa.UniqueConstraint( - "address_id", "dingaling_id", name="zz_dingalings_multiple" + "address_id", + "dingaling_id", + name="zz_dingalings_multiple", + comment="di unique comment", ), schema=schema, test_needs_fk=True, @@ -472,11 +475,11 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): "email_addresses", metadata, Column("address_id", sa.Integer), - Column( - "remote_user_id", sa.Integer, sa.ForeignKey(users.c.user_id) - ), + Column("remote_user_id", sa.Integer, ForeignKey(users.c.user_id)), Column("email_address", sa.String(20), index=True), - sa.PrimaryKeyConstraint("address_id", name="email_ad_pk"), + sa.PrimaryKeyConstraint( + "address_id", name="email_ad_pk", comment="ea pk comment" + ), schema=schema, test_needs_fk=True, ) @@ -799,6 +802,7 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): (schema, "dingalings_v"): [ col("dingaling_id", auto="omit", nullable=mock.ANY), col("address_id"), + col("id_user"), col("data"), ] } @@ -831,6 +835,7 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): (schema, "dingalings"): [ pk("dingaling_id"), col("address_id"), + col("id_user"), col("data"), ], (schema, "email_addresses"): [ @@ -873,8 +878,12 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): kind=ObjectKind.ANY, filter_names=None, ): - def pk(*cols, name=mock.ANY): - return {"constrained_columns": list(cols), "name": name} + def pk(*cols, name=mock.ANY, comment=None): + return { + "constrained_columns": list(cols), + "name": name, + "comment": comment, + } empty = pk(name=None) if testing.requires.materialized_views_reflect_pk.enabled: @@ -890,7 +899,9 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): tables = { (schema, "users"): pk("user_id"), (schema, "dingalings"): pk("dingaling_id"), - (schema, "email_addresses"): pk("address_id", name="email_ad_pk"), + (schema, "email_addresses"): pk( + "address_id", name="email_ad_pk", comment="ea pk comment" + ), (schema, "comment_test"): pk("id"), (schema, "no_constraints"): empty, (schema, "local_table"): pk("id"), @@ -926,7 +937,14 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): or config.db.dialect.default_schema_name == other ) - def fk(cols, ref_col, ref_table, ref_schema=schema, name=mock.ANY): + def fk( + cols, + ref_col, + ref_table, + ref_schema=schema, + name=mock.ANY, + comment=None, + ): return { "constrained_columns": cols, "referred_columns": ref_col, @@ -936,6 +954,7 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): if ref_schema is not None else tt(), "referred_table": ref_table, + "comment": comment, } materialized = {(schema, "dingalings_v"): []} @@ -950,12 +969,14 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): fk(["parent_user_id"], ["user_id"], "users", name="user_id_fk") ], (schema, "dingalings"): [ + fk(["id_user"], ["user_id"], "users"), fk( ["address_id"], ["address_id"], "email_addresses", - name="email_add_id_fg", - ) + name="zz_email_add_id_fg", + comment="di fk comment", + ), ], (schema, "email_addresses"): [ fk(["remote_user_id"], ["user_id"], "users") @@ -1053,6 +1074,7 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): ], (schema, "dingalings"): [ *idx("data", name=mock.ANY, unique=True, duplicates=True), + *idx("id_user", name=mock.ANY, fk=True), *idx( "address_id", "dingaling_id", @@ -1118,13 +1140,16 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): filter_names=None, all_=False, ): - def uc(*cols, name, duplicates_index=None, is_index=False): + def uc( + *cols, name, duplicates_index=None, is_index=False, comment=None + ): req = testing.requires.unique_index_reflect_as_unique_constraints if is_index and not req.enabled: return () res = { "column_names": list(cols), "name": name, + "comment": comment, } if duplicates_index: res["duplicates_index"] = duplicates_index @@ -1154,6 +1179,7 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): "dingaling_id", name="zz_dingalings_multiple", duplicates_index="zz_dingalings_multiple", + comment="di unique comment", ), ], (schema, "email_addresses"): [], @@ -1196,8 +1222,8 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): ) return self in res - def cc(text, name): - return {"sqltext": tt(text), "name": name} + def cc(text, name, comment=None): + return {"sqltext": tt(text), "name": name, "comment": comment} # print({1: "test2 > (0)::double precision"} == {1: tt("test2 > 0")}) # assert 0 @@ -1209,7 +1235,14 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): } self._resolve_views(views, materialized) tables = { - (schema, "users"): [cc("test2 > 0", "test2_gt_zero")], + (schema, "users"): [ + cc("test2 <= 1000", mock.ANY), + cc( + "test2 > 0", + "zz_test2_gt_zero", + comment="users check constraint", + ), + ], (schema, "dingalings"): [ cc( "address_id > 0 and address_id < 1000", @@ -1764,6 +1797,7 @@ class ComponentReflectionTest(ComparesTables, fixtures.TablesTest): dupe = refl.pop("duplicates_index", None) if dupe: names_that_duplicate_index.add(dupe) + eq_(refl.pop("comment", None), None) eq_(orig, refl) reflected_metadata = MetaData() @@ -2459,7 +2493,7 @@ class ComponentReflectionTestExtra(fixtures.TestBase): "table", metadata, Column("id", Integer, primary_key=True), - Column("x_id", Integer, sa.ForeignKey("x.id", name="xid")), + Column("x_id", Integer, ForeignKey("x.id", name="xid")), Column("test", String(10)), test_needs_fk=True, ) |
