Opened 8 years ago

Closed 8 years ago

Last modified 6 years ago

#4465 closed (duplicate)

Invalid sql string formatting (TypeError) if sql contains '%' signs in /django/db/backends/util.py

Reported by: MockSoul Owned by: adrian
Component: Database layer (models, ORM) Version: 0.96
Severity: Keywords:
Cc: mocksoul@… Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

I have tested 0.96 version, but all files which I tweak are the same in SVN version as in 0.96.

Well, perhaps, tupo:

LIB/django/db/backends/util.py

class CursorDebugWrapper(object):
...
    def execute(self, sql, params=()):
        start = time()
        try:
            return self.cursor.execute(sql, params)
        finally:
            stop = time()
            # If params was a list, convert it to a tuple, because string
            # formatting with '%' only works with tuples or dicts.
            if not isinstance(params, (tuple, dict)):
                params = tuple(params)
            self.db.queries.append({
                'sql': sql % params,
                'time': "%.3f" % (stop - start),
            })

if sql contains any '%' characters, but params is empty list - we will have "TypeError: not enough arguments for format string" here.

This errors occurs for me than I have custom init SQL for models containing '%' sign. So we need fix LIB/django/core/management.py

  1. Fix get_custom_sql_for_model() function
  2. Fix reset() function (source:/django/trunk/django/core/management.py@5355#L661)

I suppose you must fix the second one, just

But, probably this is better? (LIB/django/db/backends/util.py)

class CursorDebugWrapper(object):
...
    def execute(self, sql, params = None):
        start = time()
        try:
            return self.cursor.execute(sql, params)
        finally:
            stop = time()

            # We only try param substitution if have any params
            if params is not None:
                # If params was a list, convert it to a tuple, because string
                # formatting with '%' only works with tuples or dicts.
                if not isinstance(params, (tuple, dict)):
                    params = tuple(params)
                sql = sql % params

            self.db.queries.append({
                'sql': sql,
                'time': "%.3f" % (stop - start),
            })

When passing params=None to cursor, I think, cursor will do this check automatically (for example, MySQLDb.cursors.BaseCursor.execute() do). After that fix, all works perfect. Again. :).

btw, great framework, thanks guys!

Change History (2)

comment:1 Changed 8 years ago by Vadim Burmakin <mocksoul@…>

  • Cc mocksoul@… added
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

comment:2 Changed 8 years ago by Craig Ogg <cogg@…>

  • Resolution set to duplicate
  • Status changed from new to closed

Duplicate of #3485

Note: See TracTickets for help on using tickets.
Back to Top