title: Alembic autogenerate does not detect existing table with mixed-case name
body: <p>I have an error when I want to do an auto generate migration with alembic.</p>
  
  <p>Project tree :</p>
  
  <pre><code>-   alembic.ini
  -   axis.py
  -   tree.txt
  -   
      alembic
     -   env.py
     -   README
     -   script.py.mako
  
         versions
  </code></pre>
  
  <pre><code># A generic, single database configuration.
  
  [alembic]
  # path to migration scripts
  script_location = alembic
  
  # template used to generate migration files
  # file_template = %%(rev)s_%%(slug)s
  
  # timezone to use when rendering the date
  # within the migration file as well as the filename.
  # string value is passed to dateutil.tz.gettz()
  # leave blank for localtime
  # timezone =
  
  # max length of characters to apply to the
  # "slug" field
  # truncate_slug_length = 40
  
  # set to 'true' to run the environment during
  # the 'revision' command, regardless of autogenerate
  # revision_environment = false
  
  # set to 'true' to allow .pyc and .pyo files without
  # a source .py file to be detected as revisions in the
  # versions/ directory
  # sourceless = false
  
  # version location specification; this defaults
  # to alembic/versions.  When using multiple version
  # directories, initial revisions must be specified with --version-path
  # version_locations = %(here)s/bar %(here)s/bat alembic/versions
  
  # the output encoding used when revision files
  # are written from script.py.mako
  # output_encoding = utf-8
  
  sqlalchemy.url = mysql+pymysql://root:**********$@localhost/amatdb_test
  
  
  [post_write_hooks]
  # post_write_hooks defines scripts or Python functions that are run
  # on newly generated revision scripts.  See the documentation for further
  # detail and examples
  
  # format using "black" - use the console_scripts runner, against the "black" entrypoint
  # hooks=black
  # black.type=console_scripts
  # black.entrypoint=black
  # black.options=-l 79
  
  # Logging configuration
  [loggers]
  keys = root,sqlalchemy,alembic
  
  [handlers]
  keys = console
  
  [formatters]
  keys = generic
  
  [logger_root]
  level = WARN
  handlers = console
  qualname =
  
  [logger_sqlalchemy]
  level = WARN
  handlers =
  qualname = sqlalchemy.engine
  
  [logger_alembic]
  level = INFO
  handlers =
  qualname = alembic
  
  [handler_console]
  class = StreamHandler
  args = (sys.stderr,)
  level = NOTSET
  formatter = generic
  
  [formatter_generic]
  format = %(levelname)-5.5s [%(name)s] %(message)s
  datefmt = %H:%M:%S
  </code></pre>
  
  <p><strong>axis.py</strong></p>
  
  <pre class="lang-python prettyprint-override"><code>from sqlalchemy import create_engine
  import pymysql
  from sqlalchemy.ext.declarative import declarative_base
  from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint
  
  Base = declarative_base()
  engine = create_engine('mysql+pymysql://root:*******$@localhost/amatdb_test')
  
  #The axis on which the tests are executed
  class AXIS(Base):
      __tablename__ = 'Axis'
      id_axis        = Column(Integer, primary_key = True)
      name_axis      = Column(String(10), nullable=False)
  </code></pre>
  
  
  
  <p><strong>env.py</strong></p>
  
  <pre class="lang-python prettyprint-override"><code>from logging.config import fileConfig
  from sqlalchemy import engine_from_config
  from sqlalchemy import pool
  
  from alembic import context
  
  import sys
  import os
  
  sys.path.insert(0, os.getcwd())
  print(sys.path)
  from axis import Base
  
  print(Base.metadata.sorted_tables)
  
  
  # this is the Alembic Config object, which provides
  # access to the values within the .ini file in use.
  config = context.config
  
  # Interpret the config file for Python logging.
  # This line sets up loggers basically.
  fileConfig(config.config_file_name)
  
  # add your model's MetaData object here
  # for 'autogenerate' support
  # from myapp import mymodel
  # target_metadata = mymodel.Base.metadata
  target_metadata = Base.metadata
  
  # other values from the config, defined by the needs of env.py,
  # can be acquired:
  # my_important_option = config.get_main_option("my_important_option")
  # ... etc.
  
  
  def run_migrations_offline():
      """Run migrations in 'offline' mode.
  
      This configures the context with just a URL
      and not an Engine, though an Engine is acceptable
      here as well.  By skipping the Engine creation
      we don't even need a DBAPI to be available.
  
      Calls to context.execute() here emit the given string to the
      script output.
  
      """
      url = config.get_main_option("sqlalchemy.url")
      context.configure(
          url=url,
          target_metadata=target_metadata,
          literal_binds=True,
          dialect_opts={"paramstyle": "named"},
      )
  
      with context.begin_transaction():
          context.run_migrations()
  
  
  def run_migrations_online():
      """Run migrations in 'online' mode.
  
      In this scenario we need to create an Engine
      and associate a connection with the context.
  
      """
      connectable = engine_from_config(
          config.get_section(config.config_ini_section),
          prefix="sqlalchemy.",
          poolclass=pool.NullPool,
      )
  
      with connectable.connect() as connection:
          context.configure(
              connection=connection, target_metadata=target_metadata
          )
  
          with context.begin_transaction():
              context.run_migrations()
  
  
  if context.is_offline_mode():
      run_migrations_offline()
  else:
      run_migrations_online()
  </code></pre>
  
  <p><strong>Explanation of my problem</strong></p>
  
  <p>First, I create my first auto generate migration with : alembic revision --autogenerate</p>
  
  <p>The migration file seems correct.</p>
  
  <pre class="lang-python prettyprint-override"><code>"""Creation table
  
  Revision ID: dcd02a3f6ff9
  Revises: 
  Create Date: 2020-06-03 08:47:48.198022
  
  """
  from alembic import op
  import sqlalchemy as sa
  
  
  # revision identifiers, used by Alembic.
  revision = 'dcd02a3f6ff9'
  down_revision = None
  branch_labels = None
  depends_on = None
  
  
  def upgrade():
      # ### commands auto generated by Alembic - please adjust! ###
      op.create_table('Axis',
      sa.Column('id_axis', sa.Integer(), nullable=False),
      sa.Column('name_axis', sa.String(length=10), nullable=False),
      sa.PrimaryKeyConstraint('id_axis')
      )
      # ### end Alembic commands ###
  
  
  def downgrade():
      # ### commands auto generated by Alembic - please adjust! ###
      op.drop_table('Axis')
      # ### end Alembic commands ###
  </code></pre>
  
  <p>Then, I run : alembic upgrade head</p>
  
  <p>My database is created.</p>
  
  <p>So, i add a new column named "test" to my table axis.</p>
  
  <pre class="lang-python prettyprint-override"><code>test           = Column(String(10), default=None)
  </code></pre>
  
  <p>And I run a second time : <code>alembic revision --autogenerate</code></p>
  
  <p>I obtain this migration file</p>
  
  <pre class="lang-python prettyprint-override"><code>"""Ajout colonne test dans axis
  
  Revision ID: 283ca08aec66
  Revises: dcd02a3f6ff9
  Create Date: 2020-06-03 08:49:19.717515
  
  """
  from alembic import op
  import sqlalchemy as sa
  from sqlalchemy.dialects import mysql
  
  # revision identifiers, used by Alembic.
  revision = '283ca08aec66'
  down_revision = 'dcd02a3f6ff9'
  branch_labels = None
  depends_on = None
  
  
  def upgrade():
      # ### commands auto generated by Alembic - please adjust! ###
      op.create_table('Axis',
      sa.Column('id_axis', sa.Integer(), nullable=False),
      sa.Column('name_axis', sa.String(length=10), nullable=False),
      sa.Column('test', sa.String(length=10), nullable=True),
      sa.PrimaryKeyConstraint('id_axis')
      )
      op.drop_table('axis')
      # ### end Alembic commands ###
  
  
  def downgrade():
      # ### commands auto generated by Alembic - please adjust! ###
      op.create_table('axis',
      sa.Column('id_axis', mysql.INTEGER(), autoincrement=True, nullable=False),
      sa.Column('name_axis', mysql.VARCHAR(length=10), nullable=False),
      sa.PrimaryKeyConstraint('id_axis'),
      mysql_collate='utf8mb4_0900_ai_ci',
      mysql_default_charset='utf8mb4',
      mysql_engine='InnoDB'
      )
      op.drop_table('Axis')
      # ### end Alembic commands ###
  </code></pre>
  
  <p>As you can see, alembic tries to recreate the table axis. So, when I run : <code>alembic upgrade head</code></p>
  
  <p>I get an error because axis already exist.</p>
  
  <p>What did I miss ? </p>
  
  <p><strong>Why  can't Alembic detect the existing tables ?</strong></p>
  
  <p>Thank you for your time and consideration</p>