+ def query(self, sql, parameters=[], noretry=False):
+ # Callers use %s-style (paramstyle='format') placeholders in queries.
+ # There's no provision for a literal '%s' present inside the query; stuff it in a parameter instead.
+ if db_api.paramstyle == 'format' or db_api.paramstyle == 'pyformat': # mysql, postgresql
+ # psycopg actually asks for a mapping with %(name)s style (pyformat) but it will accept %s style.
+ pass
+ elif db_api.paramstyle == 'qmark': # sqlite doesn't like %s style.
+ parameters = [str(p) for p in parameters]
+ sql = sql.replace('%s', '?') # hope that wasn't literal, oopsie
+
+ log_noretry = ''
+ if noretry:
+ log_noretry = ', noretry=True'
+ self.log("[SQL]", "?", "query(%r, %r%s)" % (sql, parameters, log_noretry))
+
+ try:
+ curs = self.db.cursor()
+ res = curs.execute(sql, parameters)
+ if res:
+ return curs
+ else:
+ return res
+ except db_api.DataError as e:
+ self.log("[SQL]", ".", "DB DataError: %r" % (e))
+ return False
+ except db_api.Error as e:
+ self.log("[SQL]", "!", "DB error! %r" % (e))
+ if not noretry:
+ dbsetup()
+ return self.query(sql, parameters, noretry=True)
+ else:
+ raise e
+
+ def querycb(self, cb, *args, **kwargs):
+ # TODO this should either get thrown out with getdb()/returndb(), or else be adjusted to make use of it.
+ def run_query():
+ cb(self.query(*args, **kwargs))
+ threading.Thread(target=run_query).start()
+