From 2fee98fd6984b32cfaf981564c6a5e450369ad5a Mon Sep 17 00:00:00 2001 From: vduda Date: Fri, 21 Aug 2015 15:11:22 -0400 Subject: [PATCH 1/4] [DB-12019] Test for cursor failing to close resultset --- tests/nuodb_cursor_test.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/nuodb_cursor_test.py b/tests/nuodb_cursor_test.py index 2462be7..cca539c 100644 --- a/tests/nuodb_cursor_test.py +++ b/tests/nuodb_cursor_test.py @@ -3,7 +3,7 @@ import unittest from .nuodb_base import NuoBase -from pynuodb.exception import DataError, ProgrammingError, BatchError +from pynuodb.exception import DataError, ProgrammingError, BatchError, OperationalError class NuoDBCursorTest(NuoBase): @@ -125,6 +125,28 @@ def test_executemany_somefail(self): cursor.execute("DROP TABLE executemany_table") + def test_result_set_gets_closed(self): + # Server will throw error after 1000 open result sets + con = self._connect() + + for j in [False, True]: + for i in range(2015): + if not j: + cursor = con.cursor() + cursor.execute('select 1 from dual;') + con.commit() + cursor.close() + else: + if i >= 1000: + with self.assertRaises(OperationalError): + cursor = con.cursor() + cursor.execute('select 1 from dual;') + con.commit() + else: + cursor = con.cursor() + cursor.execute('select 1 from dual;') + con.commit() + if __name__ == '__main__': unittest.main() From 6021c788b4c58407530e1b228b9a5714f0a81115 Mon Sep 17 00:00:00 2001 From: vduda Date: Fri, 21 Aug 2015 15:16:57 -0400 Subject: [PATCH 2/4] [DB-12019] ResultSet will be closed with cursor.close() --- pynuodb/cursor.py | 7 +++---- pynuodb/encodedsession.py | 7 +++++++ pynuodb/result_set.py | 6 ++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pynuodb/cursor.py b/pynuodb/cursor.py index e7ecea3..44949e1 100644 --- a/pynuodb/cursor.py +++ b/pynuodb/cursor.py @@ -69,6 +69,8 @@ def close(self): """Closes the cursor into the database.""" self._check_closed() self._statement_cache.shutdown() + if self._result_set: + self._result_set.close(self.session) self.closed = True def _check_closed(self): @@ -79,10 +81,7 @@ def _check_closed(self): raise Error("connection is closed") def _reset(self): - """Resets SQL transaction variables. - - Also closes any open statements and result sets. - """ + """Resets SQL transaction variables.""" self.description = None self.rowcount = -1 self.colcount = -1 diff --git a/pynuodb/encodedsession.py b/pynuodb/encodedsession.py index bb3dfec..41cc0b0 100644 --- a/pynuodb/encodedsession.py +++ b/pynuodb/encodedsession.py @@ -271,6 +271,13 @@ def close_statement(self, statement): self._putMessageId(protocol.CLOSESTATEMENT).putInt(statement.handle) self._exchangeMessages(False) + def close_result_set(self, result_set): + """ + :type result_set: ResultSet + """ + self._putMessageId(protocol.CLOSERESULTSET).putInt(result_set.handle) + self._exchangeMessages(False) + def create_prepared_statement(self, query): """ :type query: str diff --git a/pynuodb/result_set.py b/pynuodb/result_set.py index 70faa89..cde8964 100644 --- a/pynuodb/result_set.py +++ b/pynuodb/result_set.py @@ -35,3 +35,9 @@ def fetchone(self, session): res = self.results[self.results_idx] self.results_idx += 1 return res + + def close(self, session): + """ + :type session EncodedSession + """ + session.close_result_set(self) From 7507647ae44da6b4e937277034ab324cd289c5d4 Mon Sep 17 00:00:00 2001 From: vduda Date: Mon, 24 Aug 2015 16:41:24 -0400 Subject: [PATCH 3/4] [DB-12019] cursor test only fails on >2.1 --- tests/nuodb_cursor_test.py | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/tests/nuodb_cursor_test.py b/tests/nuodb_cursor_test.py index cca539c..f612f5e 100644 --- a/tests/nuodb_cursor_test.py +++ b/tests/nuodb_cursor_test.py @@ -4,6 +4,8 @@ from .nuodb_base import NuoBase from pynuodb.exception import DataError, ProgrammingError, BatchError, OperationalError +from distutils.version import LooseVersion +from os import getenv class NuoDBCursorTest(NuoBase): @@ -126,26 +128,27 @@ def test_executemany_somefail(self): cursor.execute("DROP TABLE executemany_table") def test_result_set_gets_closed(self): + current_version = getenv('NUODB_VERSION', None) # skipif <2.1 + if current_version is not None and LooseVersion(current_version) < LooseVersion("2.1"): # Server will throw error after 1000 open result sets - con = self._connect() - - for j in [False, True]: - for i in range(2015): - if not j: - cursor = con.cursor() - cursor.execute('select 1 from dual;') - con.commit() - cursor.close() - else: - if i >= 1000: - with self.assertRaises(OperationalError): - cursor = con.cursor() - cursor.execute('select 1 from dual;') - con.commit() - else: + con = self._connect() + for j in [False, True]: + for i in range(2015): + if not j: cursor = con.cursor() cursor.execute('select 1 from dual;') con.commit() + cursor.close() + else: + if i >= 1000: + with self.assertRaises(OperationalError): + cursor = con.cursor() + cursor.execute('select 1 from dual;') + con.commit() + else: + cursor = con.cursor() + cursor.execute('select 1 from dual;') + con.commit() if __name__ == '__main__': From 4e90fae6cdbd4fadf41280e127d8ede4ae47915f Mon Sep 17 00:00:00 2001 From: vduda Date: Mon, 24 Aug 2015 16:57:23 -0400 Subject: [PATCH 4/4] Isolate test to run for versions 2.1 and above --- tests/nuodb_cursor_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/nuodb_cursor_test.py b/tests/nuodb_cursor_test.py index f612f5e..6d19d3a 100644 --- a/tests/nuodb_cursor_test.py +++ b/tests/nuodb_cursor_test.py @@ -129,7 +129,7 @@ def test_executemany_somefail(self): def test_result_set_gets_closed(self): current_version = getenv('NUODB_VERSION', None) # skipif <2.1 - if current_version is not None and LooseVersion(current_version) < LooseVersion("2.1"): + if current_version is not None and not LooseVersion(current_version) < LooseVersion("2.1"): # Server will throw error after 1000 open result sets con = self._connect() for j in [False, True]: