Permalink
Browse files

Fixed a bug for very large queries. Found by @stevearc.

When a query exceeds 60000 characters, it keeps hanging and will not be executed.

See pull request #29 for more details.
  • Loading branch information...
1 parent e3dbcb0 commit ee354c032954598aa8acda9232faa6b79e1ea2d9 @FSX committed Sep 23, 2012
Showing with 29 additions and 38 deletions.
  1. +22 −31 examples/gen_example.py
  2. +7 −7 momoko/connection.py
View
@@ -7,6 +7,9 @@
"""
+import string
+import random
+
import tornado.httpserver
import tornado.ioloop
import tornado.options
@@ -28,6 +31,7 @@ def get(self):
self.write('''
<ul>
<li><a href="/query">A single query</a></li>
+ <li><a href="/large">A large single query</a></li>
<li><a href="/multi_query">Multiple queries executed with gen.Task</a></li>
<li><a href="/callback_and_wait">Multiple queries executed with gen.Callback and gen.Wait</a></li>
</ul>
@@ -42,47 +46,33 @@ def get(self):
try:
cursor1 = yield momoko.Op(self.db.execute, 'SELECT 55, 18, %s, 231;', (87,))
self.write('Query results: %s<br>' % cursor1.fetchall())
- cursor2 = yield momoko.Op(self.db.mogrify, 'SELECT 55, 18, %s, 231;', (87,))
- self.write('Mogrify results: %s<br>' % cursor2)
+ # cursor2 = yield momoko.Op(self.db.mogrify, 'SELECT 55, 18, %s, 231;', (87,))
+ # self.write('Mogrify results: %s<br>' % cursor2)
except Exception as error:
self.write(error)
self.finish()
- # @tornado.web.asynchronous
- # @gen.engine
- # def get(self):
- # try:
- # sql = yield momoko.Op(self.db.mogrify, 'SELECT 55, 18, %s, 231;', (87,))
- # self.write('SQL: %s<br>' % sql)
- # except Exception as error:
- # self.write(error)
-
- # self.finish()
- # @tornado.web.asynchronous
- # @gen.engine
- # def get(self):
- # try:
- # cursor1 = yield momoko.Op(self.db.callproc, 'insert_location', ('test_location_momoko',))
- # self.write('Query results: %s<br>' % cursor1.fetchall())
- # except Exception as error:
- # self.write(str(error))
+QUERY_SIZE = 60000
+CHARS = string.ascii_letters + string.digits + string.punctuation
- # self.finish()
- # @tornado.web.asynchronous
- # def get(self):
- # self.db.execute('SELECT 42, 12, %s, 11;', (25,), callback=self._done)
- # # self.db.execute('SELECT X;', callback=self._done)
+class LargeSingleQueryHandler(BaseHandler):
+ @tornado.web.asynchronous
+ @gen.engine
+ def get(self):
+ to_be_inserted = ''.join( [random.choice(CHARS) for i in range(QUERY_SIZE)])
- # def _done(self, cursor, error):
- # if error is None:
- # self.write('Query results: %s' % cursor.fetchall())
- # else:
- # self.write('Error: %r' % error)
+ try:
+ cursor1 = yield momoko.Op(self.db.execute, 'INSERT INTO test_table (data) VALUES (%s) RETURNING id;',
+ (to_be_inserted,))
+ self.write('Status: {0}<br>'.format(cursor1.statusmessage))
+ self.write('Results: {0}<br>'.format(cursor1.fetchall()))
+ except Exception as error:
+ self.write(error)
- # self.finish()
+ self.finish()
class MultiQueryHandler(BaseHandler):
@@ -133,6 +123,7 @@ def main():
application = tornado.web.Application([
(r'/', OverviewHandler),
(r'/query', SingleQueryHandler),
+ (r'/large', LargeSingleQueryHandler),
(r'/multi_query', MultiQueryHandler),
(r'/callback_and_wait', CallbackWaitHandler),
], debug=True)
View
@@ -313,7 +313,7 @@ def open(self, dsn, connection_factory=None, callbacks=[]):
if self._channel and self._notify_callback:
self._callbacks.append(self._setup_notify)
- # Set connection state (state should be 2 (write))
+ # Set connection state
self._ioloop.add_handler(self._fileno, self._io_callback, IOLoop.WRITE)
def _setup_notify(self, error):
@@ -324,9 +324,9 @@ def _poll_notify(self, cursor, error):
notify = self._connection.notifies.pop()
self._notify_callback(notify)
- # Set callback and connection state (state should be 1 (read))
+ # Set callback and connection state
self._callbacks = [partial(self._poll_notify, cursor)]
- self._ioloop.update_handler(self._fileno, IOLoop.READ)
+ self._ioloop.update_handler(self._fileno, IOLoop.WRITE)
def close(self):
"""
@@ -341,19 +341,19 @@ def execute(self, operation, parameters=(), cursor_factory=None,
cursor_factory or psycopg2.extensions.cursor)
cursor.execute(operation, parameters)
- # Set callback and connection state (state should be 1 (read))
+ # Set callback and connection state
self._callbacks = [partial(callback, cursor)]
- self._ioloop.update_handler(self._fileno, IOLoop.READ)
+ self._ioloop.update_handler(self._fileno, IOLoop.WRITE)
def callproc(self, procname, parameters=(), cursor_factory=None,
callback=_dummy_callback):
cursor = self._connection.cursor(cursor_factory=
cursor_factory or psycopg2.extensions.cursor)
cursor.callproc(procname, parameters)
- # Set callback and connection state (state should be 1 (read))
+ # Set callback and connection state
self._callbacks = [partial(callback, cursor)]
- self._ioloop.update_handler(self._fileno, IOLoop.READ)
+ self._ioloop.update_handler(self._fileno, IOLoop.WRITE)
def mogrify(self, operation, parameters=(), callback=_dummy_callback):
cursor = self._connection.cursor()

0 comments on commit ee354c0

Please sign in to comment.