summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/dialects/postgresql/base.py
diff options
context:
space:
mode:
authorGilbert Gilb's <gilbsgilbert@gmail.com>2022-01-23 13:00:35 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2022-01-26 22:22:14 -0500
commit77dd6808f250e0431f9bce824f46f6e1ef63eef3 (patch)
tree2e2eb137c18994d707ff27cd9d3dfb4163bdea8a /lib/sqlalchemy/dialects/postgresql/base.py
parent321f64f71e7ecc7404da9b95e2e0aa1d692ac181 (diff)
downloadsqlalchemy-77dd6808f250e0431f9bce824f46f6e1ef63eef3.tar.gz
Add compiler support for PostgreSQL "NOT VALID" constraints.
Added compiler support for the PostgreSQL ``NOT VALID`` phrase when rendering DDL for the :class:`.CheckConstraint`, :class:`.ForeignKeyConstraint` and :class:`.ForeignKey` schema constructs. Pull request courtesy Gilbert Gilb's. Fixes: #7600 Closes: #7601 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/7601 Pull-request-sha: 78eecd55fd9fad07030d963f5fd6713c4af60e80 Change-Id: I84bfe84596856eeea2bcca45c04ad23d980a75ec
Diffstat (limited to 'lib/sqlalchemy/dialects/postgresql/base.py')
-rw-r--r--lib/sqlalchemy/dialects/postgresql/base.py76
1 files changed, 74 insertions, 2 deletions
diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py
index e4ebbcb80..af81f39b0 100644
--- a/lib/sqlalchemy/dialects/postgresql/base.py
+++ b/lib/sqlalchemy/dialects/postgresql/base.py
@@ -1058,7 +1058,54 @@ dialect in conjunction with the :class:`_schema.Table` construct:
.. seealso::
`PostgreSQL CREATE TABLE options
- <https://www.postgresql.org/docs/current/static/sql-createtable.html>`_
+ <https://www.postgresql.org/docs/current/static/sql-createtable.html>`_ -
+ in the PostgreSQL documentation.
+
+.. _postgresql_constraint_options:
+
+PostgreSQL Constraint Options
+-----------------------------
+
+The following option(s) are supported by the PostgreSQL dialect in conjunction
+with selected constraint constructs:
+
+* ``NOT VALID``: This option applies towards CHECK and FOREIGN KEY constraints
+ when the constraint is being added to an existing table via ALTER TABLE,
+ and has the effect that existing rows are not scanned during the ALTER
+ operation against the constraint being added.
+
+ When using a SQL migration tool such as `Alembic <https://alembic.sqlalchemy.org>`_
+ that renders ALTER TABLE constructs, the ``postgresql_not_valid`` argument
+ may be specified as an additional keyword argument within the operation
+ that creates the constraint, as in the following Alembic example::
+
+ def update():
+ op.create_foreign_key(
+ "fk_user_address",
+ "address",
+ "user",
+ ["user_id"],
+ ["id"],
+ postgresql_not_valid=True
+ )
+
+ The keyword is ultimately accepted directly by the
+ :class:`_schema.CheckConstraint`, :class:`_schema.ForeignKeyConstraint`
+ and :class:`_schema.ForeignKey` constructs; when using a tool like
+ Alembic, dialect-specific keyword arguments are passed through to
+ these constructs from the migration operation directives::
+
+ CheckConstraint("some_field IS NOT NULL", postgresql_not_valid=True)
+
+ ForeignKeyConstraint(["some_id"], ["some_table.some_id"], postgresql_not_valid=True)
+
+ .. versionadded:: 1.4.32
+
+ .. seealso::
+
+ `PostgreSQL ALTER TABLE options
+ <https://www.postgresql.org/docs/current/static/sql-altertable.html>`_ -
+ in the PostgreSQL documentation.
.. _postgresql_table_valued_overview:
@@ -2580,6 +2627,10 @@ class PGDDLCompiler(compiler.DDLCompiler):
colspec += " NULL"
return colspec
+ def _define_constraint_validity(self, constraint):
+ not_valid = constraint.dialect_options["postgresql"]["not_valid"]
+ return " NOT VALID" if not_valid else ""
+
def visit_check_constraint(self, constraint):
if constraint._type_bound:
typ = list(constraint.columns)[0].type
@@ -2594,7 +2645,16 @@ class PGDDLCompiler(compiler.DDLCompiler):
"create_constraint=False on this Enum datatype."
)
- return super(PGDDLCompiler, self).visit_check_constraint(constraint)
+ text = super(PGDDLCompiler, self).visit_check_constraint(constraint)
+ text += self._define_constraint_validity(constraint)
+ return text
+
+ def visit_foreign_key_constraint(self, constraint):
+ text = super(PGDDLCompiler, self).visit_foreign_key_constraint(
+ constraint
+ )
+ text += self._define_constraint_validity(constraint)
+ return text
def visit_drop_table_comment(self, drop):
return "COMMENT ON TABLE %s IS NULL" % self.preparer.format_table(
@@ -3210,6 +3270,18 @@ class PGDialect(default.DefaultDialect):
"inherits": None,
},
),
+ (
+ schema.CheckConstraint,
+ {
+ "not_valid": False,
+ },
+ ),
+ (
+ schema.ForeignKeyConstraint,
+ {
+ "not_valid": False,
+ },
+ ),
]
reflection_options = ("postgresql_ignore_search_path",)