Skip to content

Commit

Permalink
document constraint behavior for add_column()
Browse files Browse the repository at this point in the history
note which constraints are generated from Column (nullable,
single column FOREIGN KEY) and which
are not (PRIMARY KEY, CHECK, UNIQUE, etc.).

Change-Id: I030f2b4e17b08a63e0543567cf01ba03e8752d79
Fixes: #1232
  • Loading branch information
zzzeek committed Apr 29, 2023
1 parent abd175b commit b0fd144
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 20 deletions.
49 changes: 39 additions & 10 deletions alembic/op.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,39 @@ def add_column(
op.add_column("organization", Column("name", String()))
The provided :class:`~sqlalchemy.schema.Column` object can also
specify a :class:`~sqlalchemy.schema.ForeignKey`, referencing
a remote table name. Alembic will automatically generate a stub
"referenced" table and emit a second ALTER statement in order
to add the constraint separately::
The :meth:`.Operations.add_column` method typically corresponds
to the SQL command "ALTER TABLE... ADD COLUMN". Within the scope
of this command, the column's name, datatype, nullability,
and optional server-generated defaults may be indicated.
.. 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.
* :paramref:`~sqlalchemy.schema.Column.unique` - use the
:meth:`.Operations.create_unique_constraint` method
* :paramref:`~sqlalchemy.schema.Column.index` - use the
:meth:`.Operations.create_index` method
The provided :class:`~sqlalchemy.schema.Column` object may include a
:class:`~sqlalchemy.schema.ForeignKey` constraint directive,
referencing a remote table name. For this specific type of constraint,
Alembic will automatically emit a second ALTER statement in order to
add the single-column FOREIGN KEY constraint separately::
from alembic import op
from sqlalchemy import Column, INTEGER, ForeignKey
Expand All @@ -67,11 +95,12 @@ def add_column(
Column("account_id", INTEGER, ForeignKey("accounts.id")),
)
Note that this statement uses the :class:`~sqlalchemy.schema.Column`
construct as is from the SQLAlchemy library. In particular,
default values to be created on the database side are
specified using the ``server_default`` parameter, and not
``default`` which only specifies Python-side defaults::
The column argument passed to :meth:`.Operations.add_column` is a
:class:`~sqlalchemy.schema.Column` construct, used in the same way it's
used in SQLAlchemy. In particular, values or functions to be indicated
as producing the column's default value on the database side are
specified using the ``server_default`` parameter, and not ``default``
which only specifies Python-side defaults::
from alembic import op
from sqlalchemy import Column, TIMESTAMP, func
Expand Down
49 changes: 39 additions & 10 deletions alembic/operations/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -2012,11 +2012,39 @@ def add_column(
op.add_column("organization", Column("name", String()))
The provided :class:`~sqlalchemy.schema.Column` object can also
specify a :class:`~sqlalchemy.schema.ForeignKey`, referencing
a remote table name. Alembic will automatically generate a stub
"referenced" table and emit a second ALTER statement in order
to add the constraint separately::
The :meth:`.Operations.add_column` method typically corresponds
to the SQL command "ALTER TABLE... ADD COLUMN". Within the scope
of this command, the column's name, datatype, nullability,
and optional server-generated defaults may be indicated.
.. 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.
* :paramref:`~sqlalchemy.schema.Column.unique` - use the
:meth:`.Operations.create_unique_constraint` method
* :paramref:`~sqlalchemy.schema.Column.index` - use the
:meth:`.Operations.create_index` method
The provided :class:`~sqlalchemy.schema.Column` object may include a
:class:`~sqlalchemy.schema.ForeignKey` constraint directive,
referencing a remote table name. For this specific type of constraint,
Alembic will automatically emit a second ALTER statement in order to
add the single-column FOREIGN KEY constraint separately::
from alembic import op
from sqlalchemy import Column, INTEGER, ForeignKey
Expand All @@ -2026,11 +2054,12 @@ def add_column(
Column("account_id", INTEGER, ForeignKey("accounts.id")),
)
Note that this statement uses the :class:`~sqlalchemy.schema.Column`
construct as is from the SQLAlchemy library. In particular,
default values to be created on the database side are
specified using the ``server_default`` parameter, and not
``default`` which only specifies Python-side defaults::
The column argument passed to :meth:`.Operations.add_column` is a
:class:`~sqlalchemy.schema.Column` construct, used in the same way it's
used in SQLAlchemy. In particular, values or functions to be indicated
as producing the column's default value on the database side are
specified using the ``server_default`` parameter, and not ``default``
which only specifies Python-side defaults::
from alembic import op
from sqlalchemy import Column, TIMESTAMP, func
Expand Down

0 comments on commit b0fd144

Please sign in to comment.