|
25 | 25 | from sqlalchemy.orm.exc import UnmappedClassError
|
26 | 26 | from sqlalchemy.orm.session import Session
|
27 | 27 | from sqlalchemy.event import listen
|
28 |
| -from sqlalchemy.interfaces import ConnectionProxy |
29 | 28 | from sqlalchemy.engine.url import make_url
|
30 | 29 | from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
|
31 | 30 | from sqlalchemy.util import to_list
|
@@ -130,29 +129,6 @@ def _calling_context(app_path):
|
130 | 129 | return '<unknown>'
|
131 | 130 |
|
132 | 131 |
|
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 |
| - |
156 | 132 | class _SignallingSession(Session):
|
157 | 133 |
|
158 | 134 | def __init__(self, db, autocommit=False, autoflush=False, **options):
|
@@ -222,6 +198,36 @@ def _record(mapper, target, operation):
|
222 | 198 | pk = tuple(mapper.primary_key_from_instance(target))
|
223 | 199 | orm.object_session(target)._model_changes[pk] = (target, operation)
|
224 | 200 |
|
| 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 | + |
225 | 231 | def get_debug_queries():
|
226 | 232 | """In debug mode Flask-SQLAlchemy will log all the SQL queries sent
|
227 | 233 | to the database. This information is available until the end of request
|
@@ -458,11 +464,12 @@ def get_engine(self):
|
458 | 464 | options = {'convert_unicode': True}
|
459 | 465 | self._sa.apply_pool_defaults(self._app, options)
|
460 | 466 | self._sa.apply_driver_hacks(self._app, info, options)
|
461 |
| - if _record_queries(self._app): |
462 |
| - options['proxy'] = _ConnectionDebugProxy(self._app.import_name) |
463 | 467 | if echo:
|
464 | 468 | options['echo'] = True
|
465 | 469 | self._engine = rv = sqlalchemy.create_engine(info, **options)
|
| 470 | + if _record_queries(self._app): |
| 471 | + _EngineDebuggingSignalEvents(self._engine, |
| 472 | + self._app.import_name).register() |
466 | 473 | self._connected_for = (uri, echo)
|
467 | 474 | return rv
|
468 | 475 |
|
|
0 commit comments