diff --git a/google/cloud/spanner_dbapi/cursor.py b/google/cloud/spanner_dbapi/cursor.py index 64df68b362..36b28af712 100644 --- a/google/cloud/spanner_dbapi/cursor.py +++ b/google/cloud/spanner_dbapi/cursor.py @@ -44,8 +44,6 @@ from google.rpc.code_pb2 import ABORTED, OK -_UNSET_COUNT = -1 - ColumnDetails = namedtuple("column_details", ["null_ok", "spanner_type"]) Statement = namedtuple("Statement", "sql, params, param_types, checksum, is_insert") @@ -60,7 +58,6 @@ class Cursor(object): def __init__(self, connection): self._itr = None self._result_set = None - self._row_count = _UNSET_COUNT self.lastrowid = None self.connection = connection self._is_closed = False @@ -119,12 +116,15 @@ def description(self): @property def rowcount(self): - """The number of rows produced by the last `.execute()`. + """The number of rows produced by the last `execute()` call. - :rtype: int - :returns: The number of rows produced by the last .execute*(). + :raises: :class:`NotImplemented`. """ - return self._row_count + raise NotImplementedError( + "The `rowcount` property is non-operational. Request " + "resulting rows are streamed by the `fetch*()` methods " + "and can't be counted before they are all streamed." + ) def _raise_if_closed(self): """Raise an exception if this cursor is closed. @@ -153,11 +153,7 @@ def _do_execute_update(self, transaction, sql, params): result = transaction.execute_update( sql, params=params, param_types=get_param_types(params) ) - self._itr = None - if type(result) == int: - self._row_count = result - - return result + self._itr = iter([result]) def _do_batch_update(self, transaction, statements, many_result_set): status, res = transaction.batch_update(statements) @@ -421,9 +417,6 @@ def _handle_DQL_with_snapshot(self, snapshot, sql, params): # Read the first element so that the StreamedResultSet can # return the metadata after a DQL statement. See issue #155. self._itr = PeekIterator(self._result_set) - # Unfortunately, Spanner doesn't seem to send back - # information about the number of rows available. - self._row_count = _UNSET_COUNT def _handle_DQL(self, sql, params): if self.connection.read_only and not self.connection.autocommit: diff --git a/tests/unit/spanner_dbapi/test_cursor.py b/tests/unit/spanner_dbapi/test_cursor.py index 1a79c64e1b..c340c4e5ce 100644 --- a/tests/unit/spanner_dbapi/test_cursor.py +++ b/tests/unit/spanner_dbapi/test_cursor.py @@ -62,11 +62,10 @@ def test_property_description(self): self.assertIsInstance(cursor.description[0], ColumnInfo) def test_property_rowcount(self): - from google.cloud.spanner_dbapi.cursor import _UNSET_COUNT - connection = self._make_connection(self.INSTANCE, self.DATABASE) cursor = self._make_one(connection) - self.assertEqual(cursor.rowcount, _UNSET_COUNT) + with self.assertRaises(NotImplementedError): + cursor.rowcount def test_callproc(self): from google.cloud.spanner_dbapi.exceptions import InterfaceError @@ -94,26 +93,25 @@ def test_close(self, mock_client): cursor.execute("SELECT * FROM database") def test_do_execute_update(self): - from google.cloud.spanner_dbapi.cursor import _UNSET_COUNT + from google.cloud.spanner_dbapi.checksum import ResultsChecksum connection = self._make_connection(self.INSTANCE, self.DATABASE) cursor = self._make_one(connection) + cursor._checksum = ResultsChecksum() transaction = mock.MagicMock() def run_helper(ret_value): transaction.execute_update.return_value = ret_value - res = cursor._do_execute_update( + cursor._do_execute_update( transaction=transaction, sql="SELECT * WHERE true", params={}, ) - return res + return cursor.fetchall() expected = "good" - self.assertEqual(run_helper(expected), expected) - self.assertEqual(cursor._row_count, _UNSET_COUNT) + self.assertEqual(run_helper(expected), [expected]) expected = 1234 - self.assertEqual(run_helper(expected), expected) - self.assertEqual(cursor._row_count, expected) + self.assertEqual(run_helper(expected), [expected]) def test_execute_programming_error(self): from google.cloud.spanner_dbapi.exceptions import ProgrammingError @@ -706,7 +704,6 @@ def test_setoutputsize(self): def test_handle_dql(self): from google.cloud.spanner_dbapi import utils - from google.cloud.spanner_dbapi.cursor import _UNSET_COUNT connection = self._make_connection(self.INSTANCE, mock.MagicMock()) connection.database.snapshot.return_value.__enter__.return_value = ( @@ -718,7 +715,6 @@ def test_handle_dql(self): cursor._handle_DQL("sql", params=None) self.assertEqual(cursor._result_set, ["0"]) self.assertIsInstance(cursor._itr, utils.PeekIterator) - self.assertEqual(cursor._row_count, _UNSET_COUNT) def test_context(self): connection = self._make_connection(self.INSTANCE, self.DATABASE)