Django

Code

Changeset 6601

Show
Ignore:
Timestamp:
10/23/07 14:00:31 (1 year ago)
Author:
adrian
Message:

Added a BaseDatabaseOperations?.last_executed_query() hook, which allows a database backend to specify how to get the last-executed query on a given cursor. Implemented it for the psycopg2 backend. This means that for psycopg2, the SQL statements in django.db.connection.queries will now reflect the exact SQL as sent to the server, instead of a naive and misleading string-interpolated version

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/db/backends/__init__.py

    r6195 r6601  
    128128        raise NotImplementedError('Full-text search is not implemented for this database backend') 
    129129 
     130    def last_executed_query(self, cursor, sql, params): 
     131        """ 
     132        Returns a string of the query last executed by the given cursor, with 
     133        placeholders replaced with actual values. 
     134 
     135        `sql` is the raw query containing placeholders, and `params` is the 
     136        sequence of parameters. These are used by default, but this method 
     137        exists for database backends to provide a better implementation 
     138        according to their own quoting schemes. 
     139        """ 
     140        from django.utils.encoding import smart_unicode, force_unicode 
     141 
     142        # Convert params to contain Unicode values. 
     143        to_unicode = lambda s: force_unicode(s, strings_only=True) 
     144        if isinstance(params, (list, tuple)): 
     145            u_params = tuple([to_unicode(val) for val in params]) 
     146        else: 
     147            u_params = dict([(to_unicode(k), to_unicode(v)) for k, v in params.items()]) 
     148 
     149        return smart_unicode(sql) % u_params 
     150 
    130151    def last_insert_id(self, cursor, table_name, pk_name): 
    131152        """ 
  • django/trunk/django/db/backends/postgresql_psycopg2/base.py

    r6012 r6601  
    66 
    77from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures 
    8 from django.db.backends.postgresql.operations import DatabaseOperations 
     8from django.db.backends.postgresql.operations import DatabaseOperations as PostgresqlDatabaseOperations 
    99try: 
    1010    import psycopg2 as Database 
     
    2121class DatabaseFeatures(BaseDatabaseFeatures): 
    2222    needs_datetime_string_cast = False 
     23 
     24class DatabaseOperations(PostgresqlDatabaseOperations): 
     25    def last_executed_query(self, cursor, sql, params): 
     26        # With psycopg2, cursor objects have a "query" attribute that is the 
     27        # exact query sent to the database. See docs here: 
     28        # http://www.initd.org/tracker/psycopg/wiki/psycopg2_documentation#postgresql-status-message-and-executed-query 
     29        return cursor.query 
    2330 
    2431class DatabaseWrapper(BaseDatabaseWrapper): 
  • django/trunk/django/db/backends/util.py

    r5971 r6601  
    22import md5 
    33from time import time 
    4 from django.utils.encoding import smart_unicode, force_unicode 
    54 
    65try: 
     
    1211    def __init__(self, cursor, db): 
    1312        self.cursor = cursor 
    14         self.db = db 
     13        self.db = db # Instance of a BaseDatabaseWrapper subclass 
    1514 
    1615    def execute(self, sql, params=()): 
     
    2019        finally: 
    2120            stop = time() 
     21            sql = self.db.ops.last_executed_query(self.cursor, sql, params) 
    2222            self.db.queries.append({ 
    23                 'sql': smart_unicode(sql) % convert_args(params)
     23                'sql': sql
    2424                'time': "%.3f" % (stop - start), 
    2525            }) 
     
    3232            stop = time() 
    3333            self.db.queries.append({ 
    34                 'sql': 'MANY: ' + sql + ' ' + smart_unicode(tuple(param_list)), 
     34                'sql': '%s times: %s' % (len(param_list), sql), 
    3535                'time': "%.3f" % (stop - start), 
    3636            }) 
     
    4141        else: 
    4242            return getattr(self.cursor, attr) 
    43  
    44 def convert_args(args): 
    45     """ 
    46     Convert sequence or dictionary to contain unicode values. 
    47     """ 
    48     to_unicode = lambda s: force_unicode(s, strings_only=True) 
    49     if isinstance(args, (list, tuple)): 
    50         return tuple([to_unicode(val) for val in args]) 
    51     else: 
    52         return dict([(to_unicode(k), to_unicode(v)) for k, v in args.items()]) 
    5343 
    5444###############################################