'Execute a SQL query and fetch all rows.
:param query: SQL query.
:param values: List / dict of values to be escaped and substituted in the query.
:param as_dict: Return as a dictionary.
:param as_list: Always return as a list.
:param formatted: Format values like date etc.
:param debug: Print query and `EXPLAIN` in debug log.
:param ignore_ddl: Catch exception if table, column missing.
:param as_utf8: Encode values as UTF 8.
:param auto_commit: Commit after executing the query.
:param update: Update this dict to all rows (if returned `as_dict`).
Examples:
# return customer names as dicts
frappe.db.sql("select name from tabCustomer", as_dict=True)
# return names beginning with a
frappe.db.sql("select name from tabCustomer where name like %s", "a%")
# values as dict
frappe.db.sql("select name from tabCustomer where name like %(name)s and owner=%(owner)s",
{"name": "a%", "owner":"test@example.com"})'

def sql(self, query, values=(), as_dict=0, as_list=0, formatted=0, debug=0, ignore_ddl=0, as_utf8=0, auto_commit=0, update=None):

    if (not self._conn):
        self.connect()
    self.check_transaction_status(query)
    if auto_commit:
        self.commit()
    try:
        if (values != ()):
            if isinstance(values, dict):
                values = dict(values)
            if (not isinstance(values, (dict, tuple, list))):
                values = (values,)
            if debug:
                try:
                    self.explain_query(query, values)
                    frappe.errprint((query % values))
                except TypeError:
                    frappe.errprint([query, values])
            if ((frappe.conf.get(u'logging') or False) == 2):
                frappe.log(u'<<<<    query')
                frappe.log(query)
                frappe.log(u'with    values:')
                frappe.log(values)
                frappe.log(u'>>>>')
            self._cursor.execute(query, values)
        else:
            if debug:
                self.explain_query(query)
                frappe.errprint(query)
            if ((frappe.conf.get(u'logging') or False) == 2):
                frappe.log(u'<<<<    query')
                frappe.log(query)
                frappe.log(u'>>>>')
            self._cursor.execute(query)
    except Exception as e:
        if (ignore_ddl and (e.args[0] in (1146, 1054, 1091))):
            pass
        else:
            raise
    if auto_commit:
        self.commit()
    if as_dict:
        ret = self.fetch_as_dict(formatted, as_utf8)
        if update:
            for r in ret:
                r.update(update)
        return ret
    elif as_list:
        return self.convert_to_lists(self._cursor.fetchall(), formatted, as_utf8)
    elif as_utf8:
        return self.convert_to_lists(self._cursor.fetchall(), formatted, as_utf8)
    else:
        return self._cursor.fetchall()
