# Buggy code
def present(name, character_set=None, collate=None, **connection_args):
    """
    Ensure that the named database is present with the specified properties

    name
        The name of the database to manage
    """
    ret = {
        "name": name,
        "changes": {},
        "result": True,
        "comment": "Database {0} is already present".format(name),
    }
    # check if database exists
    existing = __salt__["mysql.db_get"](name, **connection_args)
    if existing:
        alter = False
        if character_set and character_set != existing.get("character_set"):
            log.debug(
                "character set differes from %s : %s",
                character_set,
                existing.get("character_set"),
            )
            alter = True
        if collate and collate != existing.get("collate"):
            log.debug(
                "collate set differs from %s : %s", collate, existing.get("collate")
            )
            alter = True
        if alter:
            __salt__["mysql.alter_db"](
                name, character_set=character_set, collate=collate, **connection_args
            )
        current = __salt__["mysql.db_get"](name, **connection_args)
        if existing.get("collate", None) != current.get("collate", None):
            ret["changes"].update(
                {
                    "collate": {
                        "before": existing.get("collate", None),
                        "now": current.get("collate", None),
                    }
                }
            )
        if existing.get("character_set", None) != current.get("character_set", None):
            ret["changes"].update(
                {
                    "character_set": {
                        "before": existing.get("character_set", None),
                        "now": current.get("character_set", None),
                    }
                }
            )
        return ret
    else:
        err = _get_mysql_error()
        if err is not None:
            ret["comment"] = err
            ret["result"] = False
            return ret

    if __opts__["test"]:
        ret["result"] = None
        ret["comment"] = ("Database {0} is not present and needs to be created").format(
            name
        )
        return ret
    # The database is not present, make it!
    if __salt__["mysql.db_create"](
        name, character_set=character_set, collate=collate, **connection_args
    ):
        ret["comment"] = "The database {0} has been created".format(name)
        ret["changes"][name] = "Present"
    else:
        ret["comment"] = "Failed to create database {0}".format(name)
        err = _get_mysql_error()
        if err is not None:
            ret["comment"] += " ({0})".format(err)
        ret["result"] = False

    return ret


# Traceback (_mysql_exceptions.ProgrammingError)
2019-07-11 09:06:57,236 [salt.state       :1838][INFO    ][11082] Executing state mysql_database.present for [cebeluya]
2019-07-11 09:06:57,237 [salt.loaded.int.module.mysql:608 ][DEBUG   ][11082] Doing query: SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME=%(dbname)s; args: {'dbname': 'cebeluya'}
2019-07-11 09:06:57,238 [salt.loaded.int.states.mysql_database:60  ][DEBUG   ][11082] character set differes from utf8mb4 : utf8mb4
2019-07-11 09:06:57,239 [salt.loaded.int.module.mysql:608 ][DEBUG   ][11082] Doing query: SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME=%(dbname)s; args: {'dbname': 'cebeluya'}
2019-07-11 09:06:57,239 [salt.loaded.int.module.mysql:605 ][DEBUG   ][11082] Doing query: ALTER DATABASE `cebeluya` CHARACTER SET utf8mb4 COLLATE b'utf8mb4_general_ci';
2019-07-11 09:06:57,239 [salt.state       :1925][DEBUG   ][11082] An exception occurred in this state: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'b'utf8mb4_general_ci'' at line 1")
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/salt/state.py", line 1919, in call
**cdata['kwargs'])
File "/usr/lib/python3/dist-packages/salt/loader.py", line 1918, in wrapper
return f(*args, **kwargs)
File "/usr/lib/python3/dist-packages/salt/states/mysql_database.py", line 72, in present
**connection_args)
File "/usr/lib/python3/dist-packages/salt/modules/mysql.py", line 1021, in alter_db
_execute(cur, qry, args)
File "/usr/lib/python3/dist-packages/salt/modules/mysql.py", line 606, in _execute
return cur.execute(qry)
File "/usr/lib/python3/dist-packages/MySQLdb/cursors.py", line 250, in execute
self.errorhandler(self, exc, value)
File "/usr/lib/python3/dist-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler
raise errorvalue
File "/usr/lib/python3/dist-packages/MySQLdb/cursors.py", line 247, in execute
res = self._query(query)
File "/usr/lib/python3/dist-packages/MySQLdb/cursors.py", line 411, in _query
rowcount = self._do_query(q)
File "/usr/lib/python3/dist-packages/MySQLdb/cursors.py", line 374, in _do_query
db.query(q)
File "/usr/lib/python3/dist-packages/MySQLdb/connections.py", line 292, in query
_mysql.connection.query(self, query)
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'b'utf8mb4_general_ci'' at line 1")

# Fixed code
def present(name, character_set=None, collate=None, **connection_args):
    """
    Ensure that the named database is present with the specified properties

    name
        The name of the database to manage
    """
    ret = {
        "name": name,
        "changes": {},
        "result": True,
        "comment": "Database {} is already present".format(name),
    }
    # check if database exists
    existing = __salt__["mysql.db_get"](name, **connection_args)
    if existing:
        alter_charset = False
        alter_collate = False
        existing_charset = bytes(str(existing.get("character_set")).encode()).decode()
        if character_set and character_set != existing_charset:
            alter_charset = True
            log.debug(
                "character set differes from %s : %s",
                character_set,
                existing_charset,
            )

            comment = ("Database character set {} != {} needs to be updated").format(
                character_set, existing_charset
            )
            if __opts__.get("test", False):
                ret["result"] = None
                ret["comment"] = comment
            else:
                ret["comment"] = comment

        existing_collate = bytes(str(existing.get("collate")).encode()).decode()
        if collate and collate != existing_collate:
            alter_collate = True
            log.debug(
                "collate set differs from %s : %s",
                collate,
                existing_collate,
            )

            comment = ("Database collate {} != {} needs to be updated").format(
                collate, existing_collate
            )
            if __opts__.get("test", False):
                ret["result"] = None
                ret["comment"] += "\n{}".format(comment)
                return ret
            else:
                ret["comment"] += "\n{}".format(comment)

        if alter_charset or alter_collate:
            if __opts__.get("test", False):
                ret["comment"] += "\nDatabase {} is going to be updated".format(name)
            else:
                __salt__["mysql.alter_db"](
                    name,
                    character_set=character_set,
                    collate=collate,
                    **connection_args,
                )

        current = __salt__["mysql.db_get"](name, **connection_args)
        if existing.get("collate", None) != current.get("collate", None):
            ret["changes"].update(
                {
                    "collate": {
                        "before": existing.get("collate", None),
                        "now": current.get("collate", None),
                    }
                }
            )
        if existing.get("character_set", None) != current.get("character_set", None):
            ret["changes"].update(
                {
                    "character_set": {
                        "before": existing.get("character_set", None),
                        "now": current.get("character_set", None),
                    }
                }
            )
        return ret
    else:
        err = _get_mysql_error()
        if err is not None:
            ret["comment"] = err
            ret["result"] = False
            return ret

    if __opts__.get("test", False):
        ret["result"] = None
        ret["comment"] = ("Database {} is not present and needs to be created").format(
            name
        )
        return ret

    # The database is not present, make it!
    if __salt__["mysql.db_create"](
        name, character_set=character_set, collate=collate, **connection_args
    ):
        ret["comment"] = "The database {} has been created".format(name)
        ret["changes"][name] = "Present"
    else:
        ret["comment"] = "Failed to create database {}".format(name)
        err = _get_mysql_error()
        if err is not None:
            ret["comment"] += " ({})".format(err)
        ret["result"] = False

    return ret