diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-08-07 11:48:19 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-08-10 12:23:13 -0400 |
commit | 3110acba13c22c7d8a934c30dca650b1537a50e3 (patch) | |
tree | 78811937b9524be873cfa8e1b5333cce7247eeb0 /tests/test_batch.py | |
parent | 8917b3532da6dabc07187adf597573624b32fe3c (diff) | |
download | alembic-3110acba13c22c7d8a934c30dca650b1537a50e3.tar.gz |
qualify sqlite batch add column for dynamic defaults
Batch "auto" mode will now select for "recreate" if the ``add_column()``
operation is used on SQLite, and the column itself meets the criteria for
SQLite where ADD COLUMN is not allowed, in this case a functional or
parenthesized SQL expression or a ``Computed`` (i.e. generated) column.
Change-Id: Ie948b4b8ad8dc698b458403831e47bac4ad45b8a
Fixes: #883
Diffstat (limited to 'tests/test_batch.py')
-rw-r--r-- | tests/test_batch.py | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/tests/test_batch.py b/tests/test_batch.py index 9e0491d..91baef7 100644 --- a/tests/test_batch.py +++ b/tests/test_batch.py @@ -26,6 +26,7 @@ from sqlalchemy.schema import CreateTable from sqlalchemy.sql import column from sqlalchemy.sql import text +from alembic import testing from alembic.ddl import sqlite from alembic.operations import Operations from alembic.operations.batch import ApplyBatchImpl @@ -40,8 +41,16 @@ from alembic.testing import TestBase from alembic.testing.fixtures import op_fixture from alembic.util import exc as alembic_exc from alembic.util.sqla_compat import _select +from alembic.util.sqla_compat import has_computed +from alembic.util.sqla_compat import has_identity from alembic.util.sqla_compat import sqla_14 +if has_computed: + from alembic.util.sqla_compat import Computed + +if has_identity: + from alembic.util.sqla_compat import Identity + class BatchApplyTest(TestBase): def setUp(self): @@ -1931,6 +1940,77 @@ class BatchRoundTripTest(TestBase): ["id", "data", "x", "data2"], ) + def test_add_column_auto_server_default_calculated(self): + """test #883""" + with self.op.batch_alter_table("foo") as batch_op: + batch_op.add_column( + Column( + "data2", + DateTime(), + server_default=self._datetime_server_default_fixture(), + ) + ) + + self._assert_data( + [ + {"id": 1, "data": "d1", "x": 5, "data2": mock.ANY}, + {"id": 2, "data": "22", "x": 6, "data2": mock.ANY}, + {"id": 3, "data": "8.5", "x": 7, "data2": mock.ANY}, + {"id": 4, "data": "9.46", "x": 8, "data2": mock.ANY}, + {"id": 5, "data": "d5", "x": 9, "data2": mock.ANY}, + ] + ) + eq_( + [col["name"] for col in inspect(config.db).get_columns("foo")], + ["id", "data", "x", "data2"], + ) + + @testing.combinations((True,), (False,)) + @testing.exclusions.only_on("sqlite") + def test_add_column_auto_generated(self, persisted): + """test #883""" + with self.op.batch_alter_table("foo") as batch_op: + batch_op.add_column( + Column( + "data2", Integer, Computed("1 + 1", persisted=persisted) + ) + ) + + self._assert_data( + [ + {"id": 1, "data": "d1", "x": 5, "data2": 2}, + {"id": 2, "data": "22", "x": 6, "data2": 2}, + {"id": 3, "data": "8.5", "x": 7, "data2": 2}, + {"id": 4, "data": "9.46", "x": 8, "data2": 2}, + {"id": 5, "data": "d5", "x": 9, "data2": 2}, + ] + ) + eq_( + [col["name"] for col in inspect(config.db).get_columns("foo")], + ["id", "data", "x", "data2"], + ) + + @config.requirements.identity_columns + def test_add_column_auto_identity(self): + """test #883""" + + self._no_pk_fixture() + + with self.op.batch_alter_table("nopk") as batch_op: + batch_op.add_column(Column("id", Integer, Identity())) + + self._assert_data( + [ + {"a": 1, "b": 2, "c": 3, "id": 1}, + {"a": 2, "b": 4, "c": 5, "id": 2}, + ], + tablename="nopk", + ) + eq_( + [col["name"] for col in inspect(config.db).get_columns("foo")], + ["id", "data", "x"], + ) + def test_add_column_insert_before_recreate(self): with self.op.batch_alter_table("foo", recreate="always") as batch_op: batch_op.add_column( |