Skip to content

Commit 1625f53

Browse files
author
Bruno Azzinnari
committed
Timing of SQL queries fixed by switching to the new Event API from SQL Alchemy introduced in version 0.7. Usage of ConnectionProxy is deprecated from that version, and using it resulted in invalid measures.
1 parent 43f8c7d commit 1625f53

File tree

1 file changed

+33
-26
lines changed

1 file changed

+33
-26
lines changed

flask_sqlalchemy.py

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
from sqlalchemy.orm.exc import UnmappedClassError
2626
from sqlalchemy.orm.session import Session
2727
from sqlalchemy.event import listen
28-
from sqlalchemy.interfaces import ConnectionProxy
2928
from sqlalchemy.engine.url import make_url
3029
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
3130
from sqlalchemy.util import to_list
@@ -130,29 +129,6 @@ def _calling_context(app_path):
130129
return '<unknown>'
131130

132131

133-
class _ConnectionDebugProxy(ConnectionProxy):
134-
"""Helps debugging the database."""
135-
136-
def __init__(self, import_name):
137-
self.app_package = import_name
138-
139-
def cursor_execute(self, execute, cursor, statement, parameters,
140-
context, executemany):
141-
start = _timer()
142-
try:
143-
return execute(cursor, statement, parameters, context)
144-
finally:
145-
ctx = connection_stack.top
146-
if ctx is not None:
147-
queries = getattr(ctx, 'sqlalchemy_queries', None)
148-
if queries is None:
149-
queries = []
150-
setattr(ctx, 'sqlalchemy_queries', queries)
151-
queries.append(_DebugQueryTuple((
152-
statement, parameters, start, _timer(),
153-
_calling_context(self.app_package))))
154-
155-
156132
class _SignallingSession(Session):
157133

158134
def __init__(self, db, autocommit=False, autoflush=False, **options):
@@ -222,6 +198,36 @@ def _record(mapper, target, operation):
222198
pk = tuple(mapper.primary_key_from_instance(target))
223199
orm.object_session(target)._model_changes[pk] = (target, operation)
224200

201+
202+
class _EngineDebuggingSignalEvents(object):
203+
"""Sets up handlers for two events that let us track the execution time of queries."""
204+
205+
def __init__(self, engine, import_name):
206+
self.engine = engine
207+
self.app_package = import_name
208+
209+
def register(self):
210+
listen(self.engine, 'before_cursor_execute', self.before_cursor_execute)
211+
listen(self.engine, 'after_cursor_execute', self.after_cursor_execute)
212+
213+
def before_cursor_execute(self, conn, cursor, statement,
214+
parameters, context, executemany):
215+
if connection_stack.top is not None:
216+
context._query_start_time = _timer()
217+
218+
def after_cursor_execute(self, conn, cursor, statement,
219+
parameters, context, executemany):
220+
ctx = connection_stack.top
221+
if ctx is not None:
222+
queries = getattr(ctx, 'sqlalchemy_queries', None)
223+
if queries is None:
224+
queries = []
225+
setattr(ctx, 'sqlalchemy_queries', queries)
226+
queries.append( _DebugQueryTuple( (
227+
statement, parameters, context._query_start_time, _timer(),
228+
_calling_context(self.app_package) ) ) )
229+
230+
225231
def get_debug_queries():
226232
"""In debug mode Flask-SQLAlchemy will log all the SQL queries sent
227233
to the database. This information is available until the end of request
@@ -458,11 +464,12 @@ def get_engine(self):
458464
options = {'convert_unicode': True}
459465
self._sa.apply_pool_defaults(self._app, options)
460466
self._sa.apply_driver_hacks(self._app, info, options)
461-
if _record_queries(self._app):
462-
options['proxy'] = _ConnectionDebugProxy(self._app.import_name)
463467
if echo:
464468
options['echo'] = True
465469
self._engine = rv = sqlalchemy.create_engine(info, **options)
470+
if _record_queries(self._app):
471+
_EngineDebuggingSignalEvents(self._engine,
472+
self._app.import_name).register()
466473
self._connected_for = (uri, echo)
467474
return rv
468475

0 commit comments

Comments
 (0)