<p dir="auto">At work we use <a href="https://pypi.org/project/sqlalchemy-stubs/" rel="nofollow">https://pypi.org/project/sqlalchemy-stubs/</a> and we prohibit any-generics for code hygiene.  This means we somewhat regularly have stanzas that look like this:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="if TYPE_CHECKING:
     PopulatedColumnGeneric = Column[Any]
     PopulatedBinaryExpression = BinaryExpression[bool, ColumnClause[Any], Any]
 else:
     PopulatedColumnGeneric = Column
     PopulatedBinaryExpression = BinaryExpression"><pre class="notranslate"><span class="pl-k">if</span> <span class="pl-v">TYPE_CHECKING</span>:
     <span class="pl-v">PopulatedColumnGeneric</span> <span class="pl-c1">=</span> <span class="pl-v">Column</span>[<span class="pl-v">Any</span>]
     <span class="pl-v">PopulatedBinaryExpression</span> <span class="pl-c1">=</span> <span class="pl-v">BinaryExpression</span>[<span class="pl-s1">bool</span>, <span class="pl-v">ColumnClause</span>[<span class="pl-v">Any</span>], <span class="pl-v">Any</span>]
 <span class="pl-k">else</span>:
     <span class="pl-v">PopulatedColumnGeneric</span> <span class="pl-c1">=</span> <span class="pl-v">Column</span>
     <span class="pl-v">PopulatedBinaryExpression</span> <span class="pl-c1">=</span> <span class="pl-v">BinaryExpression</span></pre></div>
<p dir="auto">so that anything which reads the types using introspection sees actual types, but we've explicitly populated the generic elements of the type.</p>
<p dir="auto">I realize that sqlalchemy-stubs is a 3rd-party extension here, and you're not responsible for its choices, but I think its generics roughly accurately describe the types within sqlalchemy, and it would be handy and helpful for <code class="notranslate">[]</code> to be defined at runtime so we don't need to pull out this escape hatch all the time.</p>
<p dir="auto">Thank you for your consideration!</p>
<p dir="auto"><strong>Describe the bug</strong><br>
When building an optimised highscore using triggers I've got an explosion in the compiler, when trying to compile an upsert statement. Precisely an exception here:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="  File &quot;…/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py&quot;, line 1400, in visit_on_duplicate_key_update
    cols = self.statement.table.c
AttributeError: 'MySQLCompiler_mysqldb' object has no attribute 'statement'"><pre class="notranslate"><code class="notranslate">  File "…/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py", line 1400, in visit_on_duplicate_key_update
    cols = self.statement.table.c
AttributeError: 'MySQLCompiler_mysqldb' object has no attribute 'statement'
</code></pre></div>
<p dir="auto"><strong>Expected behavior</strong><br>
Compilation should work. I've found a workaround, by setting the <code class="notranslate">.statement</code> variable manually before the call. I was expecting this workaround not being neccessary.</p>
<p dir="auto"><strong>To Reproduce</strong><br>
See reproduction in attachment <a href="https://github.com/sqlalchemy/sqlalchemy/files/5401377/reproduction.py.zip">reproduction.py.zip</a>. It will need access to a mysql instance. Sorry for the length.</p>
<p dir="auto">Please pay special attention to the variable <code class="notranslate">expose_bug</code> which disables the workaround I have found and exposes the issue.</p>
<p dir="auto"><strong>Error</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Traceback (most recent call last):
  File &quot;./reproduction.py&quot;, line 315, in &lt;module&gt;
    Score.__table__.create()
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/schema.py&quot;, line 925, in create
    bind._run_visitor(ddl.SchemaGenerator, self, checkfirst=checkfirst)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/engine/base.py&quot;, line 2095, in _run_visitor
    conn._run_visitor(visitorcallable, element, **kwargs)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/engine/base.py&quot;, line 1656, in _run_visitor
    visitorcallable(self.dialect, self, **kwargs).traverse_single(element)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/visitors.py&quot;, line 145, in traverse_single
    return meth(obj, **kw)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py&quot;, line 854, in visit_table
    _is_metadata_operation=_is_metadata_operation,
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/event/attr.py&quot;, line 322, in __call__
    fn(*args, **kw)
  File &quot;./reproduction.py&quot;, line 152, in create_after_all_dependencies
    CreateTrigger(self)(*args, **kwargs)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py&quot;, line 256, in __call__
    return bind.execute(self.against(target))
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/engine/base.py&quot;, line 1011, in execute
    return meth(self, multiparams, params)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py&quot;, line 72, in _execute_on_connection
    return connection._execute_ddl(self, multiparams, params)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/engine/base.py&quot;, line 1066, in _execute_ddl
    else None,
  File &quot;&lt;string&gt;&quot;, line 1, in &lt;lambda&gt;
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/elements.py&quot;, line 481, in compile
    return self._compiler(dialect, bind=bind, **kw)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py&quot;, line 29, in _compiler
    return dialect.ddl_compiler(dialect, self, **kw)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py&quot;, line 325, in __init__
    self.string = self.process(self.statement, **compile_kwargs)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py&quot;, line 355, in process
    return obj._compiler_dispatch(self, **kwargs)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/ext/compiler.py&quot;, line 441, in &lt;lambda&gt;
    lambda *arg, **kw: existing(*arg, **kw),
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/ext/compiler.py&quot;, line 486, in __call__
    return fn(element, compiler, **kw)
  File &quot;./reproduction.py&quot;, line 199, in visit_create_trigger_mysql
    compiled_query = sql_compiler.process(element.trigger.query, literal_binds=True)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py&quot;, line 355, in process
    return obj._compiler_dispatch(self, **kwargs)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/visitors.py&quot;, line 96, in _compiler_dispatch
    return meth(self, **kw)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py&quot;, line 2515, in visit_insert
    insert_stmt._post_values_clause, **kw
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py&quot;, line 355, in process
    return obj._compiler_dispatch(self, **kwargs)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/visitors.py&quot;, line 96, in _compiler_dispatch
    return meth(self, **kw)
  File &quot;….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py&quot;, line 1400, in visit_on_duplicate_key_update
    cols = self.statement.table.c
AttributeError: 'MySQLCompiler_mysqldb' object has no attribute 'statement'"><pre class="notranslate"><code class="notranslate">Traceback (most recent call last):
  File "./reproduction.py", line 315, in &lt;module&gt;
    Score.__table__.create()
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/schema.py", line 925, in create
    bind._run_visitor(ddl.SchemaGenerator, self, checkfirst=checkfirst)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 2095, in _run_visitor
    conn._run_visitor(visitorcallable, element, **kwargs)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1656, in _run_visitor
    visitorcallable(self.dialect, self, **kwargs).traverse_single(element)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/visitors.py", line 145, in traverse_single
    return meth(obj, **kw)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py", line 854, in visit_table
    _is_metadata_operation=_is_metadata_operation,
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/event/attr.py", line 322, in __call__
    fn(*args, **kw)
  File "./reproduction.py", line 152, in create_after_all_dependencies
    CreateTrigger(self)(*args, **kwargs)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py", line 256, in __call__
    return bind.execute(self.against(target))
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1011, in execute
    return meth(self, multiparams, params)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py", line 72, in _execute_on_connection
    return connection._execute_ddl(self, multiparams, params)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1066, in _execute_ddl
    else None,
  File "&lt;string&gt;", line 1, in &lt;lambda&gt;
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/elements.py", line 481, in compile
    return self._compiler(dialect, bind=bind, **kw)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py", line 29, in _compiler
    return dialect.ddl_compiler(dialect, self, **kw)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 325, in __init__
    self.string = self.process(self.statement, **compile_kwargs)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 355, in process
    return obj._compiler_dispatch(self, **kwargs)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/ext/compiler.py", line 441, in &lt;lambda&gt;
    lambda *arg, **kw: existing(*arg, **kw),
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/ext/compiler.py", line 486, in __call__
    return fn(element, compiler, **kw)
  File "./reproduction.py", line 199, in visit_create_trigger_mysql
    compiled_query = sql_compiler.process(element.trigger.query, literal_binds=True)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 355, in process
    return obj._compiler_dispatch(self, **kwargs)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/visitors.py", line 96, in _compiler_dispatch
    return meth(self, **kw)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 2515, in visit_insert
    insert_stmt._post_values_clause, **kw
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 355, in process
    return obj._compiler_dispatch(self, **kwargs)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/sql/visitors.py", line 96, in _compiler_dispatch
    return meth(self, **kw)
  File "….virtualenvs/yeepa/lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py", line 1400, in visit_on_duplicate_key_update
    cols = self.statement.table.c
AttributeError: 'MySQLCompiler_mysqldb' object has no attribute 'statement'
</code></pre></div>
<p dir="auto"><strong>Versions.</strong></p>
<ul dir="auto">
<li>OS: MacOS 10.15.7</li>
<li>Python: 2.7.16</li>
<li>SQLAlchemy: 1.3.20</li>
<li>Database: MariaDB 10.5.6</li>
<li>DBAPI: PyMySQL 0.10.1</li>
</ul>