# Buggy code
def visit_on_conflict_do_update(self, on_conflict, **kw):
    clause = on_conflict

    target_text = self._on_conflict_target(on_conflict, **kw)

    action_set_ops = []

    set_parameters = dict(clause.update_values_to_set)
    # create a list of column assignment clauses as tuples

    insert_statement = self.stack[-1]["selectable"]
    cols = insert_statement.table.c
    for c in cols:
        col_key = c.key
        if col_key in set_parameters:
            value = set_parameters.pop(col_key)
            if elements._is_literal(value):
                value = elements.BindParameter(None, value, type_=c.type)

            else:
                if isinstance(value, elements.BindParameter) and value.type._isnull:
                    value = value._clone()
                    value.type = c.type
            value_text = self.process(value.self_group(), use_schema=False)

            key_text = self.preparer.quote(col_key)
            action_set_ops.append("%s = %s" % (key_text, value_text))

    # check for names that don't match columns
    if set_parameters:
        util.warn(
            "Additional column names not matching "
            "any column keys in table '%s': %s"
            % (
                self.statement.table.name,
                (", ".join("'%s'" % c for c in set_parameters)),
            )
        )
        for k, v in set_parameters.items():
            key_text = (
                self.preparer.quote(k)
                if isinstance(k, util.string_types)
                else self.process(k, use_schema=False)
            )
            value_text = self.process(elements._literal_as_binds(v), use_schema=False)
            action_set_ops.append("%s = %s" % (key_text, value_text))

    action_text = ", ".join(action_set_ops)
    if clause.update_whereclause is not None:
        action_text += " WHERE %s" % self.process(
            clause.update_whereclause, include_table=True, use_schema=False
        )

    return "ON CONFLICT %s DO UPDATE SET %s" % (target_text, action_text)


# Traceback (AttributeError)
Traceback (most recent call last):
File "./reproduction.py", line 315, in <module>
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 "<string>", line 1, in <lambda>
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 <lambda>
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'

# Fixed code
def visit_on_conflict_do_update(self, on_conflict, **kw):
    clause = on_conflict

    target_text = self._on_conflict_target(on_conflict, **kw)

    action_set_ops = []

    set_parameters = dict(clause.update_values_to_set)
    # create a list of column assignment clauses as tuples

    insert_statement = self.stack[-1]["selectable"]
    cols = insert_statement.table.c
    for c in cols:
        col_key = c.key
        if col_key in set_parameters:
            value = set_parameters.pop(col_key)
            if elements._is_literal(value):
                value = elements.BindParameter(None, value, type_=c.type)

            else:
                if isinstance(value, elements.BindParameter) and value.type._isnull:
                    value = value._clone()
                    value.type = c.type
            value_text = self.process(value.self_group(), use_schema=False)

            key_text = self.preparer.quote(col_key)
            action_set_ops.append("%s = %s" % (key_text, value_text))

    # check for names that don't match columns
    if set_parameters:
        util.warn(
            "Additional column names not matching "
            "any column keys in table '%s': %s"
            % (
                self.current_executable.table.name,
                (", ".join("'%s'" % c for c in set_parameters)),
            )
        )
        for k, v in set_parameters.items():
            key_text = (
                self.preparer.quote(k)
                if isinstance(k, util.string_types)
                else self.process(k, use_schema=False)
            )
            value_text = self.process(elements._literal_as_binds(v), use_schema=False)
            action_set_ops.append("%s = %s" % (key_text, value_text))

    action_text = ", ".join(action_set_ops)
    if clause.update_whereclause is not None:
        action_text += " WHERE %s" % self.process(
            clause.update_whereclause, include_table=True, use_schema=False
        )

    return "ON CONFLICT %s DO UPDATE SET %s" % (target_text, action_text)