connection=None,
url=None,
dialect_name=None,
+ dialect_opts=None,
transactional_ddl=None,
transaction_per_migration=False,
output_buffer=None,
"postgresql", "mssql", etc.
The type of dialect to be used will be derived from this if
``connection`` and ``url`` are not passed.
+ :param dialect_opts: dictionary of options to be passed to dialect
+ constructor.
+
+ .. versionadded:: 1.0.11
+
:param transactional_ddl: Force the usage of "transactional"
DDL on or off;
this otherwise defaults to whether or not the dialect in
url=url,
dialect_name=dialect_name,
environment_context=self,
+ dialect_opts=dialect_opts,
opts=opts,
)
dialect_name=None,
dialect=None,
environment_context=None,
+ dialect_opts=None,
opts=None,
):
"""Create a new :class:`.MigrationContext`.
"""
if opts is None:
opts = {}
+ if dialect_opts is None:
+ dialect_opts = {}
if connection:
if not isinstance(connection, Connection):
"'connection' argument to configure() is expected "
"to be a sqlalchemy.engine.Connection instance, "
"got %r" % connection,
- stacklevel=3
+ stacklevel=3,
)
dialect = connection.dialect
elif url:
url = sqla_url.make_url(url)
- dialect = url.get_dialect()()
+ dialect = url.get_dialect()(**dialect_opts)
elif dialect_name:
url = sqla_url.make_url("%s://" % dialect_name)
- dialect = url.get_dialect()()
+ dialect = url.get_dialect()(**dialect_opts)
elif not dialect:
raise Exception("Connection, url, or dialect_name is required.")
-
from logging.config import fileConfig
from sqlalchemy import engine_from_config
"""
url = config.get_main_option("sqlalchemy.url")
context.configure(
- url=url, target_metadata=target_metadata, literal_binds=True
+ url=url,
+ target_metadata=target_metadata,
+ literal_binds=True,
+ dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
-
import logging
from logging.config import fileConfig
import re
output_buffer=buffer,
target_metadata=target_metadata.get(name),
literal_binds=True,
+ dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations(engine_name=name)
url=meta.engine.url,
target_metadata=target_metadata,
literal_binds=True,
+ dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def reflects_fk_options(self):
return exclusions.closed()
+ @property
+ def sqlalchemy_issue_3740(self):
+ """Fixes percent sign escaping for paramstyles that don't require it"""
+ return exclusions.skip_if(
+ lambda config: not util.sqla_120,
+ "SQLAlchemy 1.2 or greater required",
+ )
+
@property
def sqlalchemy_12(self):
return exclusions.skip_if(
--- /dev/null
+.. change::
+ :tags: bug, commands
+ :tickets: 562
+
+ 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 the ``alembic/templates/generic/env.py`` template
+ for an example.
#!coding: utf-8
-
+from alembic import command
from alembic.environment import EnvironmentContext
from alembic.migration import MigrationContext
from alembic.script import ScriptDirectory
+from alembic.testing import config
from alembic.testing import eq_
from alembic.testing import is_
from alembic.testing.assertions import expect_warnings
from alembic.testing.env import clear_staging_env
from alembic.testing.env import staging_env
from alembic.testing.env import write_script
+from alembic.testing.fixtures import capture_context_buffer
from alembic.testing.fixtures import TestBase
from alembic.testing.mock import call
from alembic.testing.mock import MagicMock
ctx = MigrationContext(ctx.dialect, None, {})
is_(ctx.config, None)
+ @config.requirements.sqlalchemy_issue_3740
+ def test_sql_mode_parameters(self):
+ env = self._fixture()
+
+ a_rev = "arev"
+ env.script.generate_revision(a_rev, "revision a", refresh=True)
+ write_script(
+ env.script,
+ a_rev,
+ """\
+"Rev A"
+revision = '{}'
+down_revision = None
+
+from alembic import op
+
+def upgrade():
+ op.execute('''
+ do some SQL thing with a % percent sign %
+ ''')
+
+""".format(
+ a_rev
+ ),
+ )
+ with capture_context_buffer(transactional_ddl=True) as buf:
+ command.upgrade(self.cfg, "arev", sql=True)
+ assert "do some SQL thing with a % percent sign %" in buf.getvalue()
+
def test_warning_on_passing_engine(self):
env = self._fixture()