|
10 | 10 | import sqlparse
|
11 | 11 | from decorator import decorator
|
12 | 12 | from jinja2 import StrictUndefined, Template
|
| 13 | +from concurrent.futures import ThreadPoolExecutor |
13 | 14 |
|
14 | 15 | from . import cursor_formatters
|
15 | 16 | from omniduct.caches.base import cached_method
|
|
18 | 19 | from omniduct.utils.docs import quirk_docs
|
19 | 20 | from omniduct.utils.magics import MagicsProvider, process_line_arguments, process_line_cell_arguments
|
20 | 21 |
|
| 22 | + |
21 | 23 | logging.getLogger('requests').setLevel(logging.WARNING)
|
22 | 24 |
|
23 | 25 |
|
@@ -236,15 +238,35 @@ def query(self, statement, format=None, format_opts={}, **kwargs):
|
236 | 238 | Returns:
|
237 | 239 | The results of the query formatted as nominated.
|
238 | 240 | """
|
239 |
| - cursor = self.execute(statement, async=False, template=False, **kwargs) |
| 241 | + async = kwargs.get('async', False) |
| 242 | + cursor = self.execute(statement, template=False, **kwargs) |
| 243 | + |
| 244 | + def finish(cursor): |
| 245 | + if self._cursor_empty(cursor): |
| 246 | + return None |
| 247 | + # Some DBAPI2 cursor implementations error if attempting to extract |
| 248 | + # data from an empty cursor, and if so, we simply return None. |
| 249 | + formatter = self._get_formatter(format, cursor, **format_opts) |
| 250 | + return formatter.dump() |
240 | 251 |
|
241 |
| - # Some DBAPI2 cursor implementations error if attempting to extract |
242 |
| - # data from an empty cursor, and if so, we simply return None. |
243 |
| - if self._cursor_empty(cursor): |
244 |
| - return None |
| 252 | + if not async: |
| 253 | + return finish(cursor) |
245 | 254 |
|
246 |
| - formatter = self._get_formatter(format, cursor, **format_opts) |
247 |
| - return formatter.dump() |
| 255 | + from werkzeug.local import LocalProxy |
| 256 | + |
| 257 | + class ResultProxy(LocalProxy): |
| 258 | + |
| 259 | + def _get_future(self): |
| 260 | + return super(ResultProxy, self)._get_current_object() |
| 261 | + |
| 262 | + def _get_current_object(self): |
| 263 | + future = self._get_future() |
| 264 | + if not future.done(): |
| 265 | + raise Exception('query is not yet done') |
| 266 | + return future.result() |
| 267 | + |
| 268 | + future = ThreadPoolExecutor(max_workers=1).submit(finish, cursor) |
| 269 | + return ResultProxy(lambda: future) |
248 | 270 |
|
249 | 271 | def stream(self, statement, format=None, format_opts={}, batch=None, **kwargs):
|
250 | 272 | """
|
|
0 commit comments