def get_literal_query(statement: Union[Query, Executable],
                      bind: Connectable = None) -> str:
    """
    Takes an SQLAlchemy statement and produces a literal SQL version, with
    values filled in.

    As per
    https://stackoverflow.com/questions/5631078/sqlalchemy-print-the-actual-query

    Notes:
    - for debugging purposes *only*
    - insecure; you should always separate queries from their values
    - please also note that this function is quite slow

    Args:
        statement: the SQL statement (a SQLAlchemy object) to use
        bind: if the statement is unbound, you will need to specify an object
            here that supports SQL execution

    Returns:
        a string literal version of the query.

    """  # noqa
    # log.debug("statement: {!r}", statement)
    # log.debug("statement.bind: {!r}", statement.bind)
    if isinstance(statement, Query):
        if bind is None:
            bind = statement.session.get_bind(statement._mapper_zero_or_none())
        statement = statement.statement
    elif bind is None:
        bind = statement.bind
    if bind is None:  # despite all that
        raise ValueError("Attempt to call get_literal_query with an unbound "
                         "statement and no 'bind' parameter")

    # noinspection PyUnresolvedReferences
    dialect = bind.dialect
    compiler = statement._compiler(dialect)

    class LiteralCompiler(compiler.__class__):
        # noinspection PyMethodMayBeStatic
        def visit_bindparam(self,
                            bindparam: BindParameter,
                            within_columns_clause: bool = False,
                            literal_binds: bool = False,
                            **kwargs) -> str:
            return super().render_literal_bindparam(
                bindparam,
                within_columns_clause=within_columns_clause,
                literal_binds=literal_binds,
                **kwargs
            )

        # noinspection PyUnusedLocal
        def render_literal_value(self, value: Any, type_) -> str:
            """Render the value of a bind parameter as a quoted literal.

            This is used for statement sections that do not accept bind
            paramters on the target driver/database.

            This should be implemented by subclasses using the quoting services
            of the DBAPI.
            """
            if isinstance(value, str):
                value = value.replace("'", "''")
                return "'%s'" % value
            elif value is None:
                return "NULL"
            elif isinstance(value, (float, int)):
                return repr(value)
            elif isinstance(value, decimal.Decimal):
                return str(value)
            elif (isinstance(value, datetime.datetime) or
                  isinstance(value, datetime.date) or
                  isinstance(value, datetime.time) or
                  isinstance(value, pendulum.DateTime) or
                  isinstance(value, pendulum.Date) or
                  isinstance(value, pendulum.Time)):
                # All have an isoformat() method.
                return f"'{value.isoformat()}'"
                # return (
                #     "TO_DATE('%s','YYYY-MM-DD HH24:MI:SS')"
                #     % value.strftime("%Y-%m-%d %H:%M:%S")
                # )
            else:
                raise NotImplementedError(
                    "Don't know how to literal-quote value %r" % value)

    compiler = LiteralCompiler(dialect, statement)
    return compiler.process(statement) + ";"