Commit 76aecfbc authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #9055 -- Standardized behaviour of parameter escaping in db cursors

Previously, depending on the database backend or the cursor type,
you'd need to double the percent signs in the query before passing
it to cursor.execute. Now cursor.execute consistently need percent
doubling whenever params argument is not None (placeholder substitution
will happen).
Thanks Thomas Güttler for the report and Walter Doekes for his work
on the patch.
parent e7514e49
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -815,6 +815,8 @@ class BaseDatabaseOperations(object):
        to_unicode = lambda s: force_text(s, strings_only=True, errors='replace')
        if isinstance(params, (list, tuple)):
            u_params = tuple(to_unicode(val) for val in params)
        elif params is None:
            u_params = ()
        else:
            u_params = dict((to_unicode(k), to_unicode(v)) for k, v in params.items())

+1 −0
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ class CursorWrapper(object):

    def execute(self, query, args=None):
        try:
            # args is None means no string interpolation
            return self.cursor.execute(query, args)
        except Database.OperationalError as e:
            # Map some error codes to IntegrityError, since they seem to be
+7 −6
Original line number Diff line number Diff line
@@ -757,17 +757,18 @@ class FormatStylePlaceholderCursor(object):
        return [p.force_bytes for p in params]

    def execute(self, query, params=None):
        if params is None:
            params = []
        else:
            params = self._format_params(params)
        args = [(':arg%d' % i) for i in range(len(params))]
        # cx_Oracle wants no trailing ';' for SQL statements.  For PL/SQL, it
        # it does want a trailing ';' but not a trailing '/'.  However, these
        # characters must be included in the original query in case the query
        # is being passed to SQL*Plus.
        if query.endswith(';') or query.endswith('/'):
            query = query[:-1]
        if params is None:
            params = []
            query = convert_unicode(query, self.charset)
        else:
            params = self._format_params(params)
            args = [(':arg%d' % i) for i in range(len(params))]
            query = convert_unicode(query % tuple(args), self.charset)
        self._guess_input_sizes([params])
        try:
+3 −1
Original line number Diff line number Diff line
@@ -433,7 +433,9 @@ class SQLiteCursorWrapper(Database.Cursor):
    This fixes it -- but note that if you want to use a literal "%s" in a query,
    you'll need to use "%%s".
    """
    def execute(self, query, params=()):
    def execute(self, query, params=None):
        if params is None:
            return Database.Cursor.execute(self, query)
        query = self.convert_query(query)
        return Database.Cursor.execute(self, query, params)

+4 −1
Original line number Diff line number Diff line
@@ -35,11 +35,14 @@ class CursorWrapper(object):

class CursorDebugWrapper(CursorWrapper):

    def execute(self, sql, params=()):
    def execute(self, sql, params=None):
        self.db.set_dirty()
        start = time()
        try:
            with self.db.wrap_database_errors():
                if params is None:
                    # params default might be backend specific
                    return self.cursor.execute(sql)
                return self.cursor.execute(sql, params)
        finally:
            stop = time()
Loading