def test_ctor(self): from google.cloud.bigquery.dbapi import connect from google.cloud.bigquery.dbapi import Cursor connection = connect(self._mock_client()) cursor = self._make_one(connection) self.assertIsInstance(cursor, Cursor) self.assertIs(cursor.connection, connection)
def test_connect_wo_client(self, mock_client): from google.cloud.bigquery.dbapi import connect from google.cloud.bigquery.dbapi import Connection connection = connect() self.assertIsInstance(connection, Connection) self.assertIsNotNone(connection._client)
def test_close(self): from google.cloud.bigquery.dbapi import connect connection = connect(self._mock_client()) cursor = connection.cursor() # close() is a no-op, there is nothing to test. cursor.close()
def test_connect_w_client(self): from google.cloud.bigquery.dbapi import connect from google.cloud.bigquery.dbapi import Connection mock_client = self._mock_client() connection = connect(client=mock_client) self.assertIsInstance(connection, Connection) self.assertIs(connection._client, mock_client)
def test_fetchall_w_bqstorage_client_fetch_error_no_fallback(self): from google.cloud.bigquery import dbapi from google.cloud.bigquery import table row_data = [table.Row([1.1, 1.2], {"foo": 0, "bar": 1})] def fake_ensure_bqstorage_client(bqstorage_client=None, **kwargs): return bqstorage_client mock_client = self._mock_client(rows=row_data) mock_client._ensure_bqstorage_client.side_effect = fake_ensure_bqstorage_client mock_bqstorage_client = self._mock_bqstorage_client( stream_count=1, rows=row_data, ) no_access_error = exceptions.Forbidden("invalid credentials") mock_bqstorage_client.create_read_session.side_effect = no_access_error connection = dbapi.connect( client=mock_client, bqstorage_client=mock_bqstorage_client, ) cursor = connection.cursor() cursor.execute("SELECT foo, bar FROM some_table") with self.assertRaisesRegex(exceptions.Forbidden, "invalid credentials"): cursor.fetchall() # the default client was not used mock_client.list_rows.assert_not_called()
def test_raises_error_if_closed(self): from google.cloud.bigquery.dbapi import connect from google.cloud.bigquery.dbapi.exceptions import ProgrammingError connection = connect(self._mock_client()) cursor = connection.cursor() cursor.close() method_names = ( "close", "execute", "executemany", "fetchall", "fetchmany", "fetchone", "setinputsizes", "setoutputsize", "__iter__", ) for method in method_names: with self.assertRaisesRegex( ProgrammingError, r"Operating on a closed cursor\." ): getattr(cursor, method)()
def test_execute_custom_job_id(self): from google.cloud.bigquery.dbapi import connect client = self._mock_client(rows=[], num_dml_affected_rows=0) connection = connect(client) cursor = connection.cursor() cursor.execute('SELECT 1;', job_id='foo') self.assertEqual(client.run_async_query.mock_calls[0][1][0], 'foo')
def test_execute_w_query_dry_run(self): from google.cloud.bigquery.job import QueryJobConfig from google.cloud.bigquery.schema import SchemaField from google.cloud.bigquery import dbapi connection = dbapi.connect( self._mock_client( rows=[("hello", "world", 1), ("howdy", "y'all", 2)], schema=[ SchemaField("a", "STRING", mode="NULLABLE"), SchemaField("b", "STRING", mode="REQUIRED"), SchemaField("c", "INTEGER", mode="NULLABLE"), ], dry_run_job=True, total_bytes_processed=12345, ) ) cursor = connection.cursor() cursor.execute( "SELECT a, b, c FROM hello_world WHERE d > 3;", job_config=QueryJobConfig(dry_run=True), ) self.assertEqual(cursor.rowcount, 0) self.assertIsNone(cursor.description) rows = cursor.fetchall() self.assertEqual(list(rows), [])
def test_fetchall_w_bqstorage_client_v1beta1_fetch_success(self): from google.cloud.bigquery import dbapi from google.cloud.bigquery import table # use unordered data to also test any non-determenistic key order in dicts row_data = [ table.Row([1.4, 1.1, 1.3, 1.2], {"bar": 3, "baz": 2, "foo": 1, "quux": 0}), table.Row([2.4, 2.1, 2.3, 2.2], {"bar": 3, "baz": 2, "foo": 1, "quux": 0}), ] bqstorage_streamed_rows = [ { "bar": _to_pyarrow(1.2), "foo": _to_pyarrow(1.1), "quux": _to_pyarrow(1.4), "baz": _to_pyarrow(1.3), }, { "bar": _to_pyarrow(2.2), "foo": _to_pyarrow(2.1), "quux": _to_pyarrow(2.4), "baz": _to_pyarrow(2.3), }, ] mock_client = self._mock_client(rows=row_data) mock_bqstorage_client = self._mock_bqstorage_client( stream_count=1, rows=bqstorage_streamed_rows, v1beta1=True ) connection = dbapi.connect( client=mock_client, bqstorage_client=mock_bqstorage_client, ) cursor = connection.cursor() cursor.execute("SELECT foo, bar FROM some_table") with warnings.catch_warnings(record=True) as warned: rows = cursor.fetchall() # a deprecation warning should have been emitted expected_warnings = [ warning for warning in warned if issubclass(warning.category, DeprecationWarning) and "v1beta1" in str(warning) ] self.assertEqual(len(expected_warnings), 1, "Deprecation warning not raised.") # the default client was not used mock_client.list_rows.assert_not_called() # check the data returned field_value = op.itemgetter(1) sorted_row_data = [sorted(row.items(), key=field_value) for row in rows] expected_row_data = [ [("foo", 1.1), ("bar", 1.2), ("baz", 1.3), ("quux", 1.4)], [("foo", 2.1), ("bar", 2.2), ("baz", 2.3), ("quux", 2.4)], ] self.assertEqual(sorted_row_data, expected_row_data)
def test_execute_w_dml(self): from google.cloud.bigquery.dbapi import connect connection = connect( self._mock_client(rows=[], num_dml_affected_rows=12)) cursor = connection.cursor() cursor.execute('DELETE FROM UserSessions WHERE user_id = \'test\';') self.assertIsNone(cursor.description) self.assertEqual(cursor.rowcount, 12)
def test_fetchmany_w_row(self): from google.cloud.bigquery import dbapi connection = dbapi.connect(self._mock_client(rows=[(1, )])) cursor = connection.cursor() cursor.execute('SELECT 1;') rows = cursor.fetchmany() self.assertEqual(len(rows), 1) self.assertEqual(rows[0], (1, ))
def test_executemany_empty(self): from google.cloud.bigquery.dbapi import connect connection = connect(self._mock_client(rows=[], num_dml_affected_rows=12)) cursor = connection.cursor() cursor.executemany((), ()) self.assertIsNone(cursor.description) self.assertEqual(cursor.rowcount, -1)
def test_fetchone_w_row(self): from google.cloud.bigquery import dbapi connection = dbapi.connect(self._mock_client(rows=[(1, )])) cursor = connection.cursor() cursor.execute('SELECT 1;') row = cursor.fetchone() self.assertEqual(row, (1, )) self.assertIsNone(cursor.fetchone())
def test_fetchmany_w_row(self): from google.cloud.bigquery import dbapi connection = dbapi.connect( self._mock_client(rows=[(1,)])) cursor = connection.cursor() cursor.execute('SELECT 1;') rows = cursor.fetchmany() self.assertEqual(len(rows), 1) self.assertEqual(rows[0], (1,))
def test_execute_custom_job_id(self): from google.cloud.bigquery.dbapi import connect client = self._mock_client(rows=[], num_dml_affected_rows=0) connection = connect(client) cursor = connection.cursor() cursor.execute('SELECT 1;', job_id='foo') args, kwargs = client.query.call_args self.assertEqual(args[0], 'SELECT 1;') self.assertEqual(kwargs['job_id'], 'foo')
def test_fetchone_w_row(self): from google.cloud.bigquery import dbapi connection = dbapi.connect( self._mock_client(rows=[(1,)])) cursor = connection.cursor() cursor.execute('SELECT 1;') row = cursor.fetchone() self.assertEqual(row, (1,)) self.assertIsNone(cursor.fetchone())
def test_execute_w_dml(self): from google.cloud.bigquery.dbapi import connect connection = connect( self._mock_client(rows=[], num_dml_affected_rows=12)) cursor = connection.cursor() cursor.execute('DELETE FROM UserSessions WHERE user_id = \'test\';') rows = cursor.fetchall() self.assertIsNone(cursor.description) self.assertEqual(cursor.rowcount, 12) self.assertEqual(rows, [])
def test_fetchall_w_row(self): from google.cloud.bigquery import dbapi connection = dbapi.connect(self._mock_client(rows=[(1, )])) cursor = connection.cursor() cursor.execute('SELECT 1;') self.assertIsNone(cursor.description) self.assertEqual(cursor.rowcount, 1) rows = cursor.fetchall() self.assertEqual(len(rows), 1) self.assertEqual(rows[0], (1, ))
def test_executemany_w_dml(self): from google.cloud.bigquery.dbapi import connect connection = connect( self._mock_client(rows=[], num_dml_affected_rows=12)) cursor = connection.cursor() cursor.executemany( 'DELETE FROM UserSessions WHERE user_id = %s;', (('test',), ('anothertest',))) self.assertIsNone(cursor.description) self.assertEqual(cursor.rowcount, 12)
def connection(client=None): ''' use this to create a BQ connection object to use functions from DBUtil in BQ, close() and commit() are no-op client does not need to be specified ''' conn = dbapi.connect(client) return conn
def test_fetchall_w_row(self): from google.cloud.bigquery import dbapi connection = dbapi.connect( self._mock_client(rows=[(1,)])) cursor = connection.cursor() cursor.execute('SELECT 1;') self.assertIsNone(cursor.description) self.assertEqual(cursor.rowcount, 1) rows = cursor.fetchall() self.assertEqual(len(rows), 1) self.assertEqual(rows[0], (1,))
def test_executemany_w_dml(self): from google.cloud.bigquery.dbapi import connect connection = connect(self._mock_client(rows=[], num_dml_affected_rows=12)) cursor = connection.cursor() cursor.executemany( "DELETE FROM UserSessions WHERE user_id = %s;", (("test",), ("anothertest",)), ) self.assertIsNone(cursor.description) self.assertEqual(cursor.rowcount, 12)
def test_connect_w_client(self): from google.cloud.bigquery.dbapi import connect from google.cloud.bigquery.dbapi import Connection mock_client = self._mock_client() mock_bqstorage_client = self._mock_bqstorage_client() mock_client._create_bqstorage_client.return_value = mock_bqstorage_client connection = connect(client=mock_client) self.assertIsInstance(connection, Connection) self.assertIs(connection._client, mock_client) self.assertIs(connection._bqstorage_client, mock_bqstorage_client)
def test_execute_custom_job_config_wo_default_config(self): from google.cloud.bigquery.dbapi import connect from google.cloud.bigquery import job config = job.QueryJobConfig(use_legacy_sql=True) client = self._mock_client(rows=[], num_dml_affected_rows=0) connection = connect(client) cursor = connection.cursor() cursor.execute("SELECT 1;", job_id="foo", job_config=config) args, kwargs = client.query.call_args self.assertEqual(args[0], "SELECT 1;") self.assertEqual(kwargs["job_id"], "foo") self.assertEqual(kwargs["job_config"], config)
def __init__(self, google_credentials_json=None, *args, **kwargs): from google.cloud.bigquery import dbapi, Client parsed_google_json = ( safe_loads(google_credentials_json) if google_credentials_json is not None else None ) cred = get_google_credentials(parsed_google_json) client = Client(project=cred.project_id, credentials=cred) self._conn = dbapi.connect(client=client) super(BigQueryClient, self).__init__()
def test_fetchall_w_bqstorage_client_fetch_success(self): from google.cloud.bigquery import dbapi from google.cloud.bigquery import table # use unordered data to also test any non-determenistic key order in dicts row_data = [ table.Row([1.4, 1.1, 1.3, 1.2], {"bar": 3, "baz": 2, "foo": 1, "quux": 0}), table.Row([2.4, 2.1, 2.3, 2.2], {"bar": 3, "baz": 2, "foo": 1, "quux": 0}), ] bqstorage_streamed_rows = [ { "bar": _to_pyarrow(1.2), "foo": _to_pyarrow(1.1), "quux": _to_pyarrow(1.4), "baz": _to_pyarrow(1.3), }, { "bar": _to_pyarrow(2.2), "foo": _to_pyarrow(2.1), "quux": _to_pyarrow(2.4), "baz": _to_pyarrow(2.3), }, ] mock_client = self._mock_client(rows=row_data) mock_bqstorage_client = self._mock_bqstorage_client( stream_count=1, rows=bqstorage_streamed_rows, ) mock_client._ensure_bqstorage_client.return_value = mock_bqstorage_client connection = dbapi.connect( client=mock_client, bqstorage_client=mock_bqstorage_client, ) cursor = connection.cursor() cursor.execute("SELECT foo, bar FROM some_table") rows = cursor.fetchall() # the default client was not used mock_client.list_rows.assert_not_called() # check the data returned field_value = op.itemgetter(1) sorted_row_data = [sorted(row.items(), key=field_value) for row in rows] expected_row_data = [ [("foo", 1.1), ("bar", 1.2), ("baz", 1.3), ("quux", 1.4)], [("foo", 2.1), ("bar", 2.2), ("baz", 2.3), ("quux", 2.4)], ] self.assertEqual(sorted_row_data, expected_row_data)
def test_fetchall_w_bqstorage_client_no_arrow_compression(self): from google.cloud.bigquery import dbapi from google.cloud.bigquery import table # Use unordered data to also test any non-determenistic key order in dicts. row_data = [table.Row([1.2, 1.1], {"bar": 1, "foo": 0})] bqstorage_streamed_rows = [{ "bar": _to_pyarrow(1.2), "foo": _to_pyarrow(1.1) }] mock_client = self._mock_client(rows=row_data) mock_bqstorage_client = self._mock_bqstorage_client( stream_count=1, rows=bqstorage_streamed_rows, ) connection = dbapi.connect( client=mock_client, bqstorage_client=mock_bqstorage_client, ) cursor = connection.cursor() cursor.execute("SELECT foo, bar FROM some_table") with mock.patch( "google.cloud.bigquery.dbapi.cursor._ARROW_COMPRESSION_SUPPORT", new=False): rows = cursor.fetchall() mock_client.list_rows.assert_not_called( ) # The default client was not used. # Check the BQ Storage session config. expected_session = bigquery_storage.ReadSession( table="projects/P/datasets/DS/tables/T", data_format=bigquery_storage.DataFormat.ARROW, ) mock_bqstorage_client.create_read_session.assert_called_once_with( parent="projects/P", read_session=expected_session, max_stream_count=1) # Check the data returned. field_value = op.itemgetter(1) sorted_row_data = [ sorted(row.items(), key=field_value) for row in rows ] expected_row_data = [[("foo", 1.1), ("bar", 1.2)]] self.assertEqual(sorted_row_data, expected_row_data)
def test_fetchmany_w_size(self): from google.cloud.bigquery import dbapi connection = dbapi.connect( self._mock_client(rows=[(1, 2, 3), (4, 5, 6), (7, 8, 9)])) cursor = connection.cursor() cursor.execute("SELECT a, b, c;") rows = cursor.fetchmany(size=2) self.assertEqual(len(rows), 2) self.assertEqual(rows[0], (1, 2, 3)) self.assertEqual(rows[1], (4, 5, 6)) second_page = cursor.fetchmany(size=2) self.assertEqual(len(second_page), 1) self.assertEqual(second_page[0], (7, 8, 9)) third_page = cursor.fetchmany(size=2) self.assertEqual(third_page, [])
def test_execute_raises_if_result_raises(self): import google.cloud.exceptions from google.cloud.bigquery import client from google.cloud.bigquery import job from google.cloud.bigquery.dbapi import connect from google.cloud.bigquery.dbapi import exceptions job = mock.create_autospec(job.QueryJob) job.result.side_effect = google.cloud.exceptions.GoogleCloudError('') client = mock.create_autospec(client.Client) client.query.return_value = job connection = connect(client) cursor = connection.cursor() with self.assertRaises(exceptions.DatabaseError): cursor.execute('SELECT 1')
def test_execute_raises_if_result_raises(self): import google.cloud.exceptions from google.cloud.bigquery import client from google.cloud.bigquery import job from google.cloud.bigquery.dbapi import connect from google.cloud.bigquery.dbapi import exceptions job = mock.create_autospec(job.QueryJob) job.result.side_effect = google.cloud.exceptions.GoogleCloudError("") client = mock.create_autospec(client.Client) client.query.return_value = job connection = connect(client) cursor = connection.cursor() with self.assertRaises(exceptions.DatabaseError): cursor.execute("SELECT 1")
def test_fetchmany_w_size(self): from google.cloud.bigquery import dbapi connection = dbapi.connect( self._mock_client(rows=[(1, 2, 3), (4, 5, 6), (7, 8, 9)]) ) cursor = connection.cursor() cursor.execute("SELECT a, b, c;") rows = cursor.fetchmany(size=2) self.assertEqual(len(rows), 2) self.assertEqual(rows[0], (1, 2, 3)) self.assertEqual(rows[1], (4, 5, 6)) second_page = cursor.fetchmany(size=2) self.assertEqual(len(second_page), 1) self.assertEqual(second_page[0], (7, 8, 9)) third_page = cursor.fetchmany(size=2) self.assertEqual(third_page, [])
def _upload(client, dataset, table, row): """Uploads row to BigQuery.""" conn = connect(client=client) cursor = conn.cursor() sql = """INSERT into {}.{} (result_id, test_id, test_harness, test_environment, result_info, user, timestamp, system_info, test_info, extras) VALUES (@result_id, @test_id, @test_harness, @test_environment, @result_info, @user, @timestamp, @system_info, @test_info, @extras) """.format(dataset, table) cursor.execute(sql, parameters=row) conn.commit() # Cursor and connection close on their own as well. cursor.close() conn.close()
def upload_execution_summary(bigquery_project_name, bigquery_table_name, execution_summary): """Upload benchmark summary. Note: Using stream=False has a 1000 per day insert limit per table. Using stream=True, the documented limit is 50K+. With streaming there can be a small and possibly not noticeable delay to seeing the results the BigQuery UI, but there can be a 90 minute more or less delay in the results being part of exports. Note: BigQuery maps unicode() to STRING for python2. If str is used that is mapped to BYTE. """ credentials = google.auth.default()[0] sql = """INSERT into {} (result_id, test_id, test_harness, test_environment, result_info, user, timestamp, system_info, test_info, extras) VALUES (@result_id, @test_id, @test_harness, @test_environment, @result_info, @user, @timestamp, @system_info, @test_info, @extras) """.format(bigquery_table_name) entry = _translate_summary_into_old_bigquery_format( execution_summary, credentials) logging.info('Bigquery entry is {}'.format(json.dumps(entry, indent=2))) if not bigquery_project_name: logging.info( 'Skipped uploading benchmark result to bigquery because bigquery project id is not set.' ) return client = bigquery.Client(project=bigquery_project_name, credentials=credentials) conn = connect(client=client) cursor = conn.cursor() cursor.execute(sql, parameters=entry) conn.commit() cursor.close() conn.close() logging.info( 'Uploaded benchmark result to the table {} of the bigquery project {}.' .format(bigquery_table_name, bigquery_project_name))
def test_connect_w_both_clients(self): from google.cloud.bigquery.dbapi import connect from google.cloud.bigquery.dbapi import Connection mock_client = self._mock_client() mock_bqstorage_client = self._mock_bqstorage_client() mock_client._ensure_bqstorage_client.return_value = mock_bqstorage_client connection = connect( client=mock_client, bqstorage_client=mock_bqstorage_client, ) mock_client._ensure_bqstorage_client.assert_called_once_with( mock_bqstorage_client) self.assertIsInstance(connection, Connection) self.assertIs(connection._client, mock_client) self.assertIs(connection._bqstorage_client, mock_bqstorage_client)
def test_execute_w_query(self): from google.cloud.bigquery.schema import SchemaField from google.cloud.bigquery import dbapi connection = dbapi.connect( self._mock_client( rows=[("hello", "world", 1), ("howdy", "y'all", 2)], schema=[ SchemaField("a", "STRING", mode="NULLABLE"), SchemaField("b", "STRING", mode="REQUIRED"), SchemaField("c", "INTEGER", mode="NULLABLE"), ], ) ) cursor = connection.cursor() cursor.execute("SELECT a, b, c FROM hello_world WHERE d > 3;") # Verify the description. self.assertEqual(len(cursor.description), 3) a_name, a_type, _, _, _, _, a_null_ok = cursor.description[0] self.assertEqual(a_name, "a") self.assertEqual(a_type, "STRING") self.assertEqual(a_type, dbapi.STRING) self.assertTrue(a_null_ok) b_name, b_type, _, _, _, _, b_null_ok = cursor.description[1] self.assertEqual(b_name, "b") self.assertEqual(b_type, "STRING") self.assertEqual(b_type, dbapi.STRING) self.assertFalse(b_null_ok) c_name, c_type, _, _, _, _, c_null_ok = cursor.description[2] self.assertEqual(c_name, "c") self.assertEqual(c_type, "INTEGER") self.assertEqual(c_type, dbapi.NUMBER) self.assertTrue(c_null_ok) # Verify the results. self.assertEqual(cursor.rowcount, 2) row = cursor.fetchone() self.assertEqual(row, ("hello", "world", 1)) row = cursor.fetchone() self.assertEqual(row, ("howdy", "y'all", 2)) row = cursor.fetchone() self.assertIsNone(row)
def test_fetchall_w_bqstorage_client_fetch_no_rows(self): from google.cloud.bigquery import dbapi mock_client = self._mock_client(rows=[]) mock_bqstorage_client = self._mock_bqstorage_client(stream_count=0) connection = dbapi.connect( client=mock_client, bqstorage_client=mock_bqstorage_client, ) cursor = connection.cursor() cursor.execute("SELECT foo, bar FROM some_table") rows = cursor.fetchall() # # the default client was not used mock_client.list_rows.assert_not_called() # check the data returned self.assertEqual(rows, [])
def test_execute_w_default_config(self): from google.cloud.bigquery.dbapi import connect from google.cloud.bigquery import job default_config = job.QueryJobConfig(use_legacy_sql=False, flatten_results=True) client = self._mock_client( rows=[], num_dml_affected_rows=0, default_query_job_config=default_config ) connection = connect(client) cursor = connection.cursor() cursor.execute("SELECT 1;", job_id="foo") _, kwargs = client.query.call_args used_config = kwargs["job_config"] expected_config = job.QueryJobConfig( use_legacy_sql=False, flatten_results=True, query_parameters=[] ) self.assertEqual(used_config._properties, expected_config._properties)
def test_execute_w_query(self): from google.cloud.bigquery.schema import SchemaField from google.cloud.bigquery import dbapi connection = dbapi.connect(self._mock_client( rows=[('hello', 'world', 1), ('howdy', 'y\'all', 2)], schema=[ SchemaField('a', 'STRING', mode='NULLABLE'), SchemaField('b', 'STRING', mode='REQUIRED'), SchemaField('c', 'INTEGER', mode='NULLABLE')])) cursor = connection.cursor() cursor.execute('SELECT a, b, c FROM hello_world WHERE d > 3;') # Verify the description. self.assertEqual(len(cursor.description), 3) a_name, a_type, _, _, _, _, a_null_ok = cursor.description[0] self.assertEqual(a_name, 'a') self.assertEqual(a_type, 'STRING') self.assertEqual(a_type, dbapi.STRING) self.assertTrue(a_null_ok) b_name, b_type, _, _, _, _, b_null_ok = cursor.description[1] self.assertEqual(b_name, 'b') self.assertEqual(b_type, 'STRING') self.assertEqual(b_type, dbapi.STRING) self.assertFalse(b_null_ok) c_name, c_type, _, _, _, _, c_null_ok = cursor.description[2] self.assertEqual(c_name, 'c') self.assertEqual(c_type, 'INTEGER') self.assertEqual(c_type, dbapi.NUMBER) self.assertTrue(c_null_ok) # Verify the results. self.assertEqual(cursor.rowcount, 2) row = cursor.fetchone() self.assertEqual(row, ('hello', 'world', 1)) row = cursor.fetchone() self.assertEqual(row, ('howdy', 'y\'all', 2)) row = cursor.fetchone() self.assertIsNone(row)
def test_fetchone_wo_execute_raises_error(self): from google.cloud.bigquery import dbapi connection = dbapi.connect(self._mock_client()) cursor = connection.cursor() self.assertRaises(dbapi.Error, cursor.fetchone)