Releases: sqlalchemy/alembic
1.4.0
1.4.0
Released: February 4, 2020
feature
-
[feature] [batch] Added new parameters
BatchOperations.add_column.insert_before
,
BatchOperations.add_column.insert_after
which provide for
establishing the specific position in which a new column should be placed.
Also addedOperations.batch_alter_table.partial_reordering
which allows the complete set of columns to be reordered when the new table
is created. Both operations apply only to when batch mode is recreating
the whole table usingrecreate="always"
. Thanks to Marcin Szymanski
for assistance with the implementation.References: #640
bug
-
[bug] [autogenerate] Adjusted the unique constraint comparison logic in a similar manner as that
of #421 did for indexes in order to take into account SQLAlchemy's
own truncation of long constraint names when a naming convention is in use.
Without this step, a name that is truncated by SQLAlchemy based on a unique
constraint naming convention or hardcoded name will not compare properly.References: #647
-
[bug] [autogenerate] A major rework of the "type comparison" logic is in place which changes the
entire approach by which column datatypes are compared. Types are now
compared based on the DDL string generated by the metadata type vs. the
datatype reflected from the database. This means we compare types based on
what would actually render and additionally if elements of the types change
like string length, those changes are detected as well. False positives
like those generated between SQLAlchemy Boolean and MySQL TINYINT should
also be resolved. Thanks very much to Paul Becotte for lots of hard work
and patience on this one.References: #605
usecase
-
[usecase] [environment] Moved the use of the
__file__
attribute at the base of the Alembic
package into the one place that it is specifically needed, which is when
the config attempts to locate the template directory. This helps to allow
Alembic to be fully importable in environments that are using Python
memory-only import schemes. Pull request courtesy layday.References: #648
misc
- [change] The internal inspection routines no longer use SQLAlchemy's
Inspector.from_engine()
method, which is expected to be deprecated in
1.4. Theinspect()
function is now used.
1.3.3
1.3.3
Released: January 22, 2020
bug
-
[bug] [postgresql] Fixed issue where COMMENT directives for PostgreSQL failed to correctly
include an explicit schema name, as well as correct quoting rules for
schema, table, and column names. Pull request courtesy Matthew Sills.References: #637
usecase
-
[usecase] [operations] Added support for rendering of "computed" elements on
Column
objects, supported in SQLAlchemy via the newComputed
element
introduced in version 1.3.11. Pull request courtesy Federico Caselli.Note that there is currently no support for ALTER COLUMN to add, remove, or
modify the "GENERATED ALWAYS AS" element from a column; at least for
PostgreSQL, it does not seem to be supported by the database. Additionally,
SQLAlchemy does not currently reliably reflect the "GENERATED ALWAYS AS"
phrase from an existing column, so there is also no autogenerate support
for addition or removal of theComputed
element to or from an
existing column, there is only support for adding new columns that include
theComputed
element. In the case that theComputed
element is removed from theColumn
object in the table metadata,
PostgreSQL and Oracle currently reflect the "GENERATED ALWAYS AS"
expression as the "server default" which will produce an op that tries to
drop the element as a default.References: #624
1.3.2
1.3.2
Released: December 16, 2019
bug
-
[bug] [api] [autogenerate] Fixed regression introduced by #579 where server default rendering
functions began to require a dialect implementation, however the
render_python_code()
convenience function did not include one, thus
causing the function to fail when used in a server default context. The
function now accepts a migration context argument and also creates one
against the default dialect if one is not provided.References: #635
1.3.1
1.3.0
1.3.0
Released: October 31, 2019
feature
-
[feature] [command] Added support for ALEMBIC_CONFIG environment variable,
refers to the location of the alembic configuration script
in lieu of using the -c command line option.References: #608
bug
-
[bug] [autogenerate] Fixed bug in new Variant autogenerate where the order of the arguments to
Variant were mistakenly reversed.References: #131
misc
- [change] [compatibility] Some internal modifications have been made to how the names of indexes and
unique constraints work to make use of new functions added in SQLAlchemy
1.4, so that SQLAlchemy has more flexibility over how naming conventions
may be applied to these objects.
1.2.1
1.2.1
Released: September 24, 2019
bug
-
[bug] [command] Reverted the name change of the "revisions" argument to
command.stamp()
to "revision" as apparently applications are
calling upon this argument as a keyword name. Pull request courtesy
Thomas Bechtold. Special translations are also added to the command
line interface so that it is still known as "revisions" in the CLI.References: #601
-
[bug] [tests] Removed the "test requirements" from "setup.py test", as this command now
only emits a removal error in any case and these requirements are unused.References: #592
1.2.0
1.2.0
Released: September 20, 2019
-
[command] [feature] Added new
--purge
flag to thealembic stamp
command, which will
unconditionally erase the version table before stamping anything. This is
useful for development where non-existent version identifiers might be left
within the table. Additionally,alembic.stamp
now supports a list of
revision identifiers, which are intended to allow setting up muliple heads
at once. Overall handling of version identifiers within the
alembic.stamp
command has been improved with many new tests and
use cases added.References: #473
-
[autogenerate] [bug] Improved the Python rendering of a series of migration operations such that
a single "pass" is rendered for aUpgradeOps
or
DowngradeOps
based on if no lines of Python code actually
rendered under the operation, rather than whether or not sub-directives
exist. Removed extra "pass" lines that would generate from the
ModifyTableOps
directive so that these aren't duplicated under
operation rewriting scenarios.References: #550
-
[feature] [runtime] Added new feature
MigrationContext.autocommit_block()
, a special
directive which will provide for a non-transactional block inside of a
migration script. The feature requres that: the database driver
(e.g. DBAPI) supports the AUTOCOMMIT isolation mode. The directive
also necessarily needs to COMMIT the existing transaction in progress
in order to enter autocommit mode.References: #123
-
[change: py3k] Python 3.4 support is dropped, as the upstream tooling (pip, mysqlclient)
etc are already dropping support for Python 3.4, which itself is no longer
maintained. -
[autogenerate] [usecase] Added autogenerate support for
Column
objects that have
dialect-specific**kwargs
, support first added in SQLAlchemy 1.3.
This includes SQLite "on conflict" as well as options used by some
third party dialects.References: #518
-
[autogenerate] [usecase] Added rendering for SQLAlchemy
Variant
datatypes, which render as the
base type plus one or more.with_variant()
method calls.References: #131
-
[commands] [feature] Added "post write hooks" to revision generation. These allow custom logic
to run after a revision Python script is generated, typically for the
purpose of running code formatters such as "Black" or "autopep8", but may
be used for any arbitrary post-render hook as well, including custom Python
functions or scripts. The hooks are enabled by providing a
[post_write_hooks]
section in the alembic.ini file. A single hook
is provided which runs an arbitrary Python executable on the newly
generated revision script, which can be configured to run code formatters
such as Black; full examples are included in the documentation.References: #307
-
[commands] [usecase] Made the command interface revision lookup behavior more strict in that an
Alembic revision number is only resolved based on a partial match rules if
it has at least four characters, to prevent simple typographical issues
from inadvertently running migrations.References: #534
-
[environment] [feature] Added new flag
--package
toalembic init
. For environments where
the Alembic migration files and such are within the package tree and
importable as modules, this flag can be specified which will add the
additional__init__.py
files in the version location and the
environment location.References: #463
-
[autogenerate] [bug] Fixed bug where rendering of comment text for table-level comments within
Operations.create_table_comment()
and
Operations.drop_table_comment()
was not properly quote-escaped
within rendered Python code for autogenerate.References: #549
-
[autogenerate] [bug] Modified the logic of the
Rewriter
object such that it keeps a
memoization of which directives it has processed, so that it can ensure it
processes a particular directive only once, and additionally fixed
Rewriter
so that it functions correctly for multiple-pass
autogenerate schemes, such as the one illustrated in the "multidb"
template. By tracking which directives have been processed, a
multiple-pass scheme which calls upon theRewriter
multiple times
for the same structure as elements are added can work without running
duplicate operations on the same elements more than once.References: #505
1.1.0
1.1.0
Released: August 26, 2019
-
[change] Alembic 1.1 bumps the minimum version of SQLAlchemy to 1.1. As was the
case before, Python requirements remain at Python 2.7, or in the 3.x series
Python 3.4. -
[change] [internals] The test suite for Alembic now makes use of SQLAlchemy's testing framework
directly. Previously, Alembic had its own version of this framework that
was mostly copied from that of SQLAlchemy to enable testing with older
SQLAlchemy versions. The majority of this code is now removed so that both
projects can leverage improvements from a common testing framework. -
[bug] [commands] Fixed bug where the double-percent logic applied to some dialects such as
psycopg2 would be rendered in--sql
mode, by allowing dialect options
to be passed through to the dialect used to generate SQL and then providing
paramstyle="named"
so that percent signs need not be doubled. For
users having this issue, existing env.py scripts need to add
dialect_opts={"paramstyle": "named"}
to their offline
context.configure(). See thealembic/templates/generic/env.py
template
for an example.References: #562
-
[bug] [py3k] Fixed use of the deprecated "imp" module, which is used to detect pep3147
availability as well as to locate .pyc files, which started emitting
deprecation warnings during the test suite. The warnings were not being
emitted earlier during the test suite, the change is possibly due to
changes in py.test itself but this is not clear. The check for pep3147 is
set to True for any Python version 3.5 or greater now and importlib is used
when available. Note that some dependencies such as distutils may still be
emitting this warning. Tests are adjusted to accommodate for dependencies
that emit the warning as well. -
[bug] [mysql] Fixed issue where emitting a change of column name for MySQL did not
preserve the column comment, even if it were specified as existing_comment.References: #594
-
[bug] [setup] Removed the "python setup.py test" feature in favor of a straight run of
"tox". Per Pypa / pytest developers, "setup.py" commands are in general
headed towards deprecation in favor of tox. The tox.ini script has been
updated such that running "tox" with no arguments will perform a single run
of the test suite against the default installed Python interpreter.References: #592
-
[commands] [usecase] The "alembic init" command will now proceed if the target directory exists
as long as it's still empty. Previously, it would not proceed if the
directory existed. The new behavior is modeled from what git does, to
accommodate for container or other deployments where an Alembic target
directory may need to be already mounted instead of being created with
alembic init. Pull request courtesy Aviskar KC.References: #571
1.0.11
1.0.11
Released: June 25, 2019
-
[autogenerate] [batch] [bug] [sqlite] SQLite server default reflection will ensure parenthesis are surrounding a
column default expression that is detected as being a non-constant
expression, such as adatetime()
default, to accommodate for the
requirement that SQL expressions have to be parenthesized when being sent
as DDL. Parenthesis are not added to constant expressions to allow for
maximum cross-compatibility with other dialects and existing test suites
(such as Alembic's), which necessarily entails scanning the expression to
eliminate for constant numeric and string values. The logic is added to the
two "reflection->DDL round trip" paths which are currently autogenerate and
batch migration. Within autogenerate, the logic is on the rendering side,
whereas in batch the logic is installed as a column reflection hook.References: #579
-
[autogenerate] [bug] [sqlite] Improved SQLite server default comparison to accommodate for a
text()
construct that added parenthesis directly vs. a construct that relied
upon the SQLAlchemy SQLite dialect to render the parenthesis, as well
as improved support for various forms of constant expressions such as
values that are quoted vs. non-quoted.References: #579
-
[autogenerate] [bug] Fixed bug where the "literal_binds" flag was not being set when
autogenerate would create a server default value, meaning server default
comparisons would fail for functions that contained literal values. -
[bug] [mysql] Added support for MySQL "DROP CHECK", which is added as of MySQL 8.0.16,
separate from MariaDB's "DROP CONSTRAINT" for CHECK constraints. The MySQL
Alembic implementation now checks for "MariaDB" in server_version_info to
decide which one to use.References: #554
-
[bug] [mysql] [operations] Fixed issue where MySQL databases need to use CHANGE COLUMN when altering a
server default of CURRENT_TIMESTAMP, NOW() and probably other functions
that are only usable with DATETIME/TIMESTAMP columns. While MariaDB
supports both CHANGE and ALTER COLUMN in this case, MySQL databases only
support CHANGE. So the new logic is that if the server default change is
against a DateTime-oriented column, the CHANGE format is used
unconditionally, as in the vast majority of cases the server default is to
be CURRENT_TIMESTAMP which may also be potentially bundled with an "ON
UPDATE CURRENT_TIMESTAMP" directive, which SQLAlchemy does not currently
support as a distinct field. The fix addiionally improves the server
default comparison logic when the "ON UPDATE" clause is present and
there are parenthesis to be adjusted for as is the case on some MariaDB
versions.References: #564
-
[bug] [environment] Warnings emitted by Alembic now include a default stack level of 2, and in
some cases it's set to 3, in order to help warnings indicate more closely
where they are originating from. Pull request courtesy Ash Berlin-Taylor. -
[bug] [py3k] Replaced the Python compatbility routines for
getargspec()
with a fully
vendored version based ongetfullargspec()
from Python 3.3.
Originally, Python was emitting deprecation warnings for this function in
Python 3.8 alphas. While this change was reverted, it was observed that
Python 3 implementations forgetfullargspec()
are an order of magnitude
slower as of the 3.4 series where it was rewritten againstSignature
.
While Python plans to improve upon this situation, SQLAlchemy projects for
now are using a simple replacement to avoid any future issues.References: #563
1.0.10
1.0.10
Released: April 28, 2019
-
[bug] [commands] Fixed bug introduced in release 0.9.0 where the helptext for commands
inadvertently got expanded to include function docstrings from the
command.py module. The logic has been adjusted to only refer to the first
line(s) preceding the first line break within each docstring, as was the
original intent.References: #552
-
[bug] [mysql] [operations] Added an assertion in
RevisionMap.get_revisions()
and other methods
which ensures revision numbers are passed as strings or collections of
strings. Driver issues particularly on MySQL may inadvertently be passing
bytes here which leads to failures later on.References: #551
-
[autogenerate] [bug] [mysql] Fixed bug when using the
EnvironmentContext.configure.compare_server_default
flag set
toTrue
where a server default that is introduced in the table metadata
on anInteger
column, where there is no existing server default in the
database, would raise aTypeError
.References: #553