We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Database migration fails if the URI contains '%' signs
If the `SQLALCHEMY_DATABASE_URI` contains query parameters like `ssl_ca=/path/to/cert` the path separators will be url-encoded with `%` signs.
This fails when passing the URI to the alembic configuration (https://alembic.sqlalchemy.org/en/latest/api/config.html#alembic.config.Config.set_main_option).
The `%` signs should be escaped in the URI string before passing it to alembic.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `migrations/env.py`
Content:
```
1 from __future__ import with_statement
2 from alembic import context
3 from sqlalchemy import engine_from_config, pool
4 from sqlalchemy.engine.url import make_url
5 from logging.config import fileConfig
6 
7 # this is the Alembic Config object, which provides
8 # access to the values within the .ini file in use.
9 
10 config = context.config
11 
12 # Interpret the config file for Python logging.
13 # This line sets up loggers basically.
14 fileConfig(config.config_file_name)
15 
16 # add your model's MetaData object here
17 # for 'autogenerate' support
18 # from myapp import mymodel
19 # target_metadata = mymodel.Base.metadata
20 from flask import current_app
21 
22 
23 def set_database_url(config):
24     url = current_app.config.get('SQLALCHEMY_DATABASE_URI')
25     try:
26         # In case of MySQL, add ``charset=utf8`` to the parameters (if no charset is set),
27         # because this is what Flask-SQLAlchemy does
28         if url.startswith("mysql"):
29             parsed_url = make_url(url)
30             parsed_url.query.setdefault("charset", "utf8")
31             url = str(parsed_url)
32     except Exception as exx:
33         print(u"Attempted to set charset=utf8 on connection, but failed: {}".format(exx))
34     config.set_main_option('sqlalchemy.url', url)
35 
36 
37 set_database_url(config)
38 target_metadata = current_app.extensions['migrate'].db.metadata
39 
40 # other values from the config, defined by the needs of env.py,
41 # can be acquired:
42 # my_important_option = config.get_main_option("my_important_option")
43 # ... etc.
44 
45 
46 def run_migrations_offline():
47     """Run migrations in 'offline' mode.
48 
49     This configures the context with just a URL
50     and not an Engine, though an Engine is acceptable
51     here as well.  By skipping the Engine creation
52     we don't even need a DBAPI to be available.
53 
54     Calls to context.execute() here emit the given string to the
55     script output.
56 
57     """
58     url = config.get_main_option("sqlalchemy.url")
59     context.configure(url=url)
60 
61     with context.begin_transaction():
62         context.run_migrations()
63 
64 
65 def run_migrations_online():
66     """Run migrations in 'online' mode.
67 
68     In this scenario we need to create an Engine
69     and associate a connection with the context.
70 
71     """
72     # FIX for Postgres updates
73     url = config.get_section(config.config_ini_section).get("sqlalchemy.url")
74     driver = url.split(":")[0]
75 
76     if driver == "postgresql+psycopg2":
77         engine = engine_from_config(
78                     config.get_section(config.config_ini_section),
79                     prefix='sqlalchemy.',
80                     isolation_level="AUTOCOMMIT",
81                     poolclass=pool.NullPool)
82     else:
83         engine = engine_from_config(
84                     config.get_section(config.config_ini_section),
85                     prefix='sqlalchemy.',
86                     poolclass=pool.NullPool)
87 
88     connection = engine.connect()
89     context.configure(
90                 connection=connection,
91                 target_metadata=target_metadata,
92                 compare_type=True
93                 )
94 
95     try:
96         with context.begin_transaction():
97             context.run_migrations()
98     finally:
99         connection.close()
100 
101 if context.is_offline_mode():
102     print("Running offline")
103     run_migrations_offline()
104 else:
105     print("Running online")
106     run_migrations_online()
107 
108
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/migrations/env.py b/migrations/env.py
--- a/migrations/env.py
+++ b/migrations/env.py
@@ -3,6 +3,7 @@
 from sqlalchemy import engine_from_config, pool
 from sqlalchemy.engine.url import make_url
 from logging.config import fileConfig
+from six.moves.urllib.parse import quote
 
 # this is the Alembic Config object, which provides
 # access to the values within the .ini file in use.
@@ -28,10 +29,13 @@
         if url.startswith("mysql"):
             parsed_url = make_url(url)
             parsed_url.query.setdefault("charset", "utf8")
+            # We need to quote the password in case it contains special chars
+            parsed_url.password = quote(parsed_url.password)
             url = str(parsed_url)
     except Exception as exx:
         print(u"Attempted to set charset=utf8 on connection, but failed: {}".format(exx))
-    config.set_main_option('sqlalchemy.url', url)
+    # set_main_option() requires escaped "%" signs in the string
+    config.set_main_option('sqlalchemy.url', url.replace('%', '%%'))
 
 
 set_database_url(config)
@@ -98,10 +102,10 @@
     finally:
         connection.close()
 
+
 if context.is_offline_mode():
     print("Running offline")
     run_migrations_offline()
 else:
     print("Running online")
     run_migrations_online()
-

{"golden_diff": "diff --git a/migrations/env.py b/migrations/env.py\n--- a/migrations/env.py\n+++ b/migrations/env.py\n@@ -3,6 +3,7 @@\n from sqlalchemy import engine_from_config, pool\n from sqlalchemy.engine.url import make_url\n from logging.config import fileConfig\n+from six.moves.urllib.parse import quote\n \n # this is the Alembic Config object, which provides\n # access to the values within the .ini file in use.\n@@ -28,10 +29,13 @@\n         if url.startswith(\"mysql\"):\n             parsed_url = make_url(url)\n             parsed_url.query.setdefault(\"charset\", \"utf8\")\n+            # We need to quote the password in case it contains special chars\n+            parsed_url.password = quote(parsed_url.password)\n             url = str(parsed_url)\n     except Exception as exx:\n         print(u\"Attempted to set charset=utf8 on connection, but failed: {}\".format(exx))\n-    config.set_main_option('sqlalchemy.url', url)\n+    # set_main_option() requires escaped \"%\" signs in the string\n+    config.set_main_option('sqlalchemy.url', url.replace('%', '%%'))\n \n \n set_database_url(config)\n@@ -98,10 +102,10 @@\n     finally:\n         connection.close()\n \n+\n if context.is_offline_mode():\n     print(\"Running offline\")\n     run_migrations_offline()\n else:\n     print(\"Running online\")\n     run_migrations_online()\n-\n", "issue": "Database migration fails if the URI contains '%' signs\nIf the `SQLALCHEMY_DATABASE_URI` contains query parameters like `ssl_ca=/path/to/cert` the path separators will be url-encoded with `%` signs.\r\nThis fails when passing the URI to the alembic configuration (https://alembic.sqlalchemy.org/en/latest/api/config.html#alembic.config.Config.set_main_option).\r\nThe `%` signs should be escaped in the URI string before passing it to alembic.\n", "before_files": [{"content": "from __future__ import with_statement\nfrom alembic import context\nfrom sqlalchemy import engine_from_config, pool\nfrom sqlalchemy.engine.url import make_url\nfrom logging.config import fileConfig\n\n# this is the Alembic Config object, which provides\n# access to the values within the .ini file in use.\n\nconfig = context.config\n\n# Interpret the config file for Python logging.\n# This line sets up loggers basically.\nfileConfig(config.config_file_name)\n\n# add your model's MetaData object here\n# for 'autogenerate' support\n# from myapp import mymodel\n# target_metadata = mymodel.Base.metadata\nfrom flask import current_app\n\n\ndef set_database_url(config):\n    url = current_app.config.get('SQLALCHEMY_DATABASE_URI')\n    try:\n        # In case of MySQL, add ``charset=utf8`` to the parameters (if no charset is set),\n        # because this is what Flask-SQLAlchemy does\n        if url.startswith(\"mysql\"):\n            parsed_url = make_url(url)\n            parsed_url.query.setdefault(\"charset\", \"utf8\")\n            url = str(parsed_url)\n    except Exception as exx:\n        print(u\"Attempted to set charset=utf8 on connection, but failed: {}\".format(exx))\n    config.set_main_option('sqlalchemy.url', url)\n\n\nset_database_url(config)\ntarget_metadata = current_app.extensions['migrate'].db.metadata\n\n# other values from the config, defined by the needs of env.py,\n# can be acquired:\n# my_important_option = config.get_main_option(\"my_important_option\")\n# ... etc.\n\n\ndef run_migrations_offline():\n    \"\"\"Run migrations in 'offline' mode.\n\n    This configures the context with just a URL\n    and not an Engine, though an Engine is acceptable\n    here as well.  By skipping the Engine creation\n    we don't even need a DBAPI to be available.\n\n    Calls to context.execute() here emit the given string to the\n    script output.\n\n    \"\"\"\n    url = config.get_main_option(\"sqlalchemy.url\")\n    context.configure(url=url)\n\n    with context.begin_transaction():\n        context.run_migrations()\n\n\ndef run_migrations_online():\n    \"\"\"Run migrations in 'online' mode.\n\n    In this scenario we need to create an Engine\n    and associate a connection with the context.\n\n    \"\"\"\n    # FIX for Postgres updates\n    url = config.get_section(config.config_ini_section).get(\"sqlalchemy.url\")\n    driver = url.split(\":\")[0]\n\n    if driver == \"postgresql+psycopg2\":\n        engine = engine_from_config(\n                    config.get_section(config.config_ini_section),\n                    prefix='sqlalchemy.',\n                    isolation_level=\"AUTOCOMMIT\",\n                    poolclass=pool.NullPool)\n    else:\n        engine = engine_from_config(\n                    config.get_section(config.config_ini_section),\n                    prefix='sqlalchemy.',\n                    poolclass=pool.NullPool)\n\n    connection = engine.connect()\n    context.configure(\n                connection=connection,\n                target_metadata=target_metadata,\n                compare_type=True\n                )\n\n    try:\n        with context.begin_transaction():\n            context.run_migrations()\n    finally:\n        connection.close()\n\nif context.is_offline_mode():\n    print(\"Running offline\")\n    run_migrations_offline()\nelse:\n    print(\"Running online\")\n    run_migrations_online()\n\n", "path": "migrations/env.py"}], "after_files": [{"content": "from __future__ import with_statement\nfrom alembic import context\nfrom sqlalchemy import engine_from_config, pool\nfrom sqlalchemy.engine.url import make_url\nfrom logging.config import fileConfig\nfrom six.moves.urllib.parse import quote\n\n# this is the Alembic Config object, which provides\n# access to the values within the .ini file in use.\n\nconfig = context.config\n\n# Interpret the config file for Python logging.\n# This line sets up loggers basically.\nfileConfig(config.config_file_name)\n\n# add your model's MetaData object here\n# for 'autogenerate' support\n# from myapp import mymodel\n# target_metadata = mymodel.Base.metadata\nfrom flask import current_app\n\n\ndef set_database_url(config):\n    url = current_app.config.get('SQLALCHEMY_DATABASE_URI')\n    try:\n        # In case of MySQL, add ``charset=utf8`` to the parameters (if no charset is set),\n        # because this is what Flask-SQLAlchemy does\n        if url.startswith(\"mysql\"):\n            parsed_url = make_url(url)\n            parsed_url.query.setdefault(\"charset\", \"utf8\")\n            # We need to quote the password in case it contains special chars\n            parsed_url.password = quote(parsed_url.password)\n            url = str(parsed_url)\n    except Exception as exx:\n        print(u\"Attempted to set charset=utf8 on connection, but failed: {}\".format(exx))\n    # set_main_option() requires escaped \"%\" signs in the string\n    config.set_main_option('sqlalchemy.url', url.replace('%', '%%'))\n\n\nset_database_url(config)\ntarget_metadata = current_app.extensions['migrate'].db.metadata\n\n# other values from the config, defined by the needs of env.py,\n# can be acquired:\n# my_important_option = config.get_main_option(\"my_important_option\")\n# ... etc.\n\n\ndef run_migrations_offline():\n    \"\"\"Run migrations in 'offline' mode.\n\n    This configures the context with just a URL\n    and not an Engine, though an Engine is acceptable\n    here as well.  By skipping the Engine creation\n    we don't even need a DBAPI to be available.\n\n    Calls to context.execute() here emit the given string to the\n    script output.\n\n    \"\"\"\n    url = config.get_main_option(\"sqlalchemy.url\")\n    context.configure(url=url)\n\n    with context.begin_transaction():\n        context.run_migrations()\n\n\ndef run_migrations_online():\n    \"\"\"Run migrations in 'online' mode.\n\n    In this scenario we need to create an Engine\n    and associate a connection with the context.\n\n    \"\"\"\n    # FIX for Postgres updates\n    url = config.get_section(config.config_ini_section).get(\"sqlalchemy.url\")\n    driver = url.split(\":\")[0]\n\n    if driver == \"postgresql+psycopg2\":\n        engine = engine_from_config(\n                    config.get_section(config.config_ini_section),\n                    prefix='sqlalchemy.',\n                    isolation_level=\"AUTOCOMMIT\",\n                    poolclass=pool.NullPool)\n    else:\n        engine = engine_from_config(\n                    config.get_section(config.config_ini_section),\n                    prefix='sqlalchemy.',\n                    poolclass=pool.NullPool)\n\n    connection = engine.connect()\n    context.configure(\n                connection=connection,\n                target_metadata=target_metadata,\n                compare_type=True\n                )\n\n    try:\n        with context.begin_transaction():\n            context.run_migrations()\n    finally:\n        connection.close()\n\n\nif context.is_offline_mode():\n    print(\"Running offline\")\n    run_migrations_offline()\nelse:\n    print(\"Running online\")\n    run_migrations_online()\n", "path": "migrations/env.py"}]}