]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
render PRIMARY KEY in add_column
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 22 Jan 2026 16:15:35 +0000 (11:15 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 22 Jan 2026 17:13:50 +0000 (12:13 -0500)
The ``primary_key`` parameter on :class:`.Column` is now honored when
:meth:`.Operations.add_column` is used, and will emit the "PRIMARY KEY"
keyword inline within the ADD COLUMN directive.  This is strictly a syntax
enhancement; no attempt is made to reconcile the column's primary key
status with any existing primary key constraint or particular backend
limitations on adding columns to the primary key.

Fixes: #1232
Change-Id: I4a5bf163101ea045cd619daa6b780d6b89af79b3

alembic/ddl/base.py
alembic/op.pyi
alembic/operations/base.py
alembic/operations/ops.py
docs/build/unreleased/1232.rst [new file with mode: 0644]
tests/test_batch.py
tests/test_op.py
tests/test_postgresql.py

index ad2847eb2f76066264f2218ede2e173032082f92..9f93f87e9acdd0f460a615af7ba62af99aed5f03 100644 (file)
@@ -355,6 +355,9 @@ def add_column(
         compiler.get_column_specification(column, **kw),
     )
 
+    if column.primary_key:
+        text += " PRIMARY KEY"
+
     const = " ".join(
         compiler.process(constraint) for constraint in column.constraints
     )
index 96f68b82ffadb4aa23897edcc0ca5b116cb70270..5b7aad2707e9c0e640a801d0192450ef1a304c47 100644 (file)
@@ -83,21 +83,16 @@ def add_column(
 
     .. note::
 
-        With the exception of NOT NULL constraints or single-column FOREIGN
-        KEY constraints, other kinds of constraints such as PRIMARY KEY,
-        UNIQUE or CHECK constraints **cannot** be generated using this
-        method; for these constraints, refer to operations such as
-        :meth:`.Operations.create_primary_key` and
-        :meth:`.Operations.create_check_constraint`. In particular, the
-        following :class:`~sqlalchemy.schema.Column` parameters are
-        **ignored**:
-
-        * :paramref:`~sqlalchemy.schema.Column.primary_key` - SQL databases
-          typically do not support an ALTER operation that can add
-          individual columns one at a time to an existing primary key
-          constraint, therefore it's less ambiguous to use the
-          :meth:`.Operations.create_primary_key` method, which assumes no
-          existing primary key constraint is present.
+        Not all contraint types may be indicated with this directive.
+        PRIMARY KEY, NOT NULL, FOREIGN KEY, and CHECK are honored, UNIQUE
+        is currently not.
+
+        .. versionadded:: 1.18.2 Added support for PRIMARY KEY to be
+           emitted within :meth:`.Operations.add_column`.
+
+        As of 1.18.2, the following :class:`~sqlalchemy.schema.Column`
+        parameters are **ignored**:
+
         * :paramref:`~sqlalchemy.schema.Column.unique` - use the
           :meth:`.Operations.create_unique_constraint` method
         * :paramref:`~sqlalchemy.schema.Column.index` - use the
index be3a77b2ada212b7d9a238c331f8f1ce48062e3e..f94cf280ba6e2848c3647bacb771f17111633e1f 100644 (file)
@@ -650,21 +650,16 @@ class Operations(AbstractOperations):
 
             .. note::
 
-                With the exception of NOT NULL constraints or single-column FOREIGN
-                KEY constraints, other kinds of constraints such as PRIMARY KEY,
-                UNIQUE or CHECK constraints **cannot** be generated using this
-                method; for these constraints, refer to operations such as
-                :meth:`.Operations.create_primary_key` and
-                :meth:`.Operations.create_check_constraint`. In particular, the
-                following :class:`~sqlalchemy.schema.Column` parameters are
-                **ignored**:
-
-                * :paramref:`~sqlalchemy.schema.Column.primary_key` - SQL databases
-                  typically do not support an ALTER operation that can add
-                  individual columns one at a time to an existing primary key
-                  constraint, therefore it's less ambiguous to use the
-                  :meth:`.Operations.create_primary_key` method, which assumes no
-                  existing primary key constraint is present.
+                Not all contraint types may be indicated with this directive.
+                PRIMARY KEY, NOT NULL, FOREIGN KEY, and CHECK are honored, UNIQUE
+                is currently not.
+
+                .. versionadded:: 1.18.2 Added support for PRIMARY KEY to be
+                   emitted within :meth:`.Operations.add_column`.
+
+                As of 1.18.2, the following :class:`~sqlalchemy.schema.Column`
+                parameters are **ignored**:
+
                 * :paramref:`~sqlalchemy.schema.Column.unique` - use the
                   :meth:`.Operations.create_unique_constraint` method
                 * :paramref:`~sqlalchemy.schema.Column.index` - use the
index c9b1526b61ffcb99770eeadd61d5e1e09c4e4066..8e709283a1052136ee31fece9112db59374a1f99 100644 (file)
@@ -2112,21 +2112,16 @@ class AddColumnOp(AlterTableOp):
 
         .. note::
 
-            With the exception of NOT NULL constraints or single-column FOREIGN
-            KEY constraints, other kinds of constraints such as PRIMARY KEY,
-            UNIQUE or CHECK constraints **cannot** be generated using this
-            method; for these constraints, refer to operations such as
-            :meth:`.Operations.create_primary_key` and
-            :meth:`.Operations.create_check_constraint`. In particular, the
-            following :class:`~sqlalchemy.schema.Column` parameters are
-            **ignored**:
-
-            * :paramref:`~sqlalchemy.schema.Column.primary_key` - SQL databases
-              typically do not support an ALTER operation that can add
-              individual columns one at a time to an existing primary key
-              constraint, therefore it's less ambiguous to use the
-              :meth:`.Operations.create_primary_key` method, which assumes no
-              existing primary key constraint is present.
+            Not all contraint types may be indicated with this directive.
+            PRIMARY KEY, NOT NULL, FOREIGN KEY, and CHECK are honored, UNIQUE
+            is currently not.
+
+            .. versionadded:: 1.18.2 Added support for PRIMARY KEY to be
+               emitted within :meth:`.Operations.add_column`.
+
+            As of 1.18.2, the following :class:`~sqlalchemy.schema.Column`
+            parameters are **ignored**:
+
             * :paramref:`~sqlalchemy.schema.Column.unique` - use the
               :meth:`.Operations.create_unique_constraint` method
             * :paramref:`~sqlalchemy.schema.Column.index` - use the
diff --git a/docs/build/unreleased/1232.rst b/docs/build/unreleased/1232.rst
new file mode 100644 (file)
index 0000000..3fff755
--- /dev/null
@@ -0,0 +1,10 @@
+.. change::
+    :tags: usecase, operations
+    :tickets: 1232
+
+    The ``primary_key`` parameter on :class:`.Column` is now honored when
+    :meth:`.Operations.add_column` is used, and will emit the "PRIMARY KEY"
+    keyword inline within the ADD COLUMN directive.  This is strictly a syntax
+    enhancement; no attempt is made to reconcile the column's primary key
+    status with any existing primary key constraint or particular backend
+    limitations on adding columns to the primary key.
index b1a2a623f8563083714ab60766be9b207e9a7a7a..bef3dc10caf3d8ca741ae8642879b454fe29b376 100644 (file)
@@ -2291,7 +2291,6 @@ class BatchRoundTripMySQLTest(BatchRoundTripTest):
     def _datetime_server_default_fixture(self):
         return func.current_timestamp()
 
-    @exclusions.fails()
     def test_drop_pk_col_readd_pk_col(self):
         super().test_drop_pk_col_readd_pk_col()
 
@@ -2348,7 +2347,6 @@ class BatchRoundTripPostgresqlTest(BatchRoundTripTest):
     def _datetime_server_default_fixture(self):
         return func.current_timestamp()
 
-    @exclusions.fails()
     def test_drop_pk_col_readd_pk_col(self):
         super().test_drop_pk_col_readd_pk_col()
 
index f03024de7f6b0d3964a2420dfcf5295c20c6dc25..0b727f8ba44be92a3762c255754a4e48345043ba 100644 (file)
@@ -71,6 +71,18 @@ class OpTest(TestBase):
             'ALTER TABLE "some.schema".somename ADD COLUMN colname VARCHAR'
         )
 
+    def test_add_column_primary_key(self):
+        context = op_fixture("postgresql")
+        op.add_column(
+            "somename",
+            Column("colname", String, primary_key=True),
+        )
+
+        context.assert_(
+            "ALTER TABLE somename ADD COLUMN colname "
+            "VARCHAR NOT NULL PRIMARY KEY"
+        )
+
     def test_rename_table_schema_hard_quoting(self):
         context = op_fixture("postgresql")
         op.rename_table(
index db9aa382235e0f8d60f019cc6c48cc5ce98443e0..fb20d170c73f7636d8e9546bb2c65f4a96c7749a 100644 (file)
@@ -188,7 +188,9 @@ class PostgresqlOpTest(TestBase):
     def test_col_w_pk_is_serial(self):
         context = op_fixture("postgresql")
         op.add_column("some_table", Column("q", Integer, primary_key=True))
-        context.assert_("ALTER TABLE some_table ADD COLUMN q SERIAL NOT NULL")
+        context.assert_(
+            "ALTER TABLE some_table ADD COLUMN q SERIAL NOT NULL PRIMARY KEY"
+        )
 
     def test_create_exclude_constraint(self):
         context = op_fixture("postgresql")