Skip to content

Commit 83ec8ed

Browse files
committed
Merge pull request #4 from tylertreat/get_schema
Add API for retrieving table schema
2 parents b23a630 + 2b3e28f commit 83ec8ed

File tree

2 files changed

+74
-6
lines changed

2 files changed

+74
-6
lines changed

bigquery/client.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,31 @@ def get_query_schema(self, job_id):
136136

137137
return query_reply['schema']['fields']
138138

139+
def get_table_schema(self, dataset, table):
140+
"""Return the table schema.
141+
142+
Args:
143+
dataset: the dataset containing the table.
144+
table: the table to get the schema for.
145+
146+
Returns:
147+
A list of dicts that represent the table schema. If the table
148+
doesn't exist, None is returned.
149+
"""
150+
151+
try:
152+
result = self.bigquery.tables().get(
153+
projectId=self.project_id,
154+
tableId=table,
155+
datasetId=dataset).execute()
156+
except HttpError, e:
157+
if int(e.resp['status']) == 404:
158+
logger.warn('Table %s.%s does not exist', dataset, table)
159+
return None
160+
raise
161+
162+
return result['schema']['fields']
163+
139164
def check_job(self, job_id):
140165
"""Return the state and number of results of a query by job id.
141166

bigquery/tests/test_client.py

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ def test_query(self):
115115

116116
self.mock_job_collection.query.assert_called_once_with(
117117
projectId=self.project_id,
118-
body={'query': self.query, 'timeoutMs': 10000, 'maxResults': None,
119-
'dryRun': False}
118+
body={'query': self.query, 'timeoutMs': 10000, 'dryRun': False,
119+
'maxResults': None}
120120
)
121121
self.assertEquals(job_id, 'spiderman')
122122
self.assertEquals(results, [])
@@ -168,8 +168,8 @@ def test_query_timeout(self):
168168

169169
self.mock_job_collection.query.assert_called_once_with(
170170
projectId=self.project_id,
171-
body={'query': self.query, 'timeoutMs': timeout * 1000,
172-
'maxResults': None, 'dryRun': False}
171+
body={'query': self.query, 'timeoutMs': timeout * 1000, 'dryRun':
172+
False, 'maxResults': None}
173173
)
174174
self.assertEquals(job_id, 'spiderman')
175175
self.assertEquals(results, [])
@@ -241,8 +241,8 @@ def test_query_with_results(self):
241241

242242
self.mock_job_collection.query.assert_called_once_with(
243243
projectId=self.project_id,
244-
body={'query': self.query, 'timeoutMs': 10000, 'maxResults': None,
245-
'dryRun': False}
244+
body={'query': self.query, 'timeoutMs': 10000, 'dryRun': False,
245+
'maxResults': None}
246246
)
247247
self.assertEquals(job_id, 'spiderman')
248248
self.assertEquals(results, [{'foo': 10}])
@@ -564,6 +564,49 @@ def test_query_incomplete(self, get_query_mock):
564564
self.assertEquals(result_schema, [])
565565

566566

567+
class TestGetTableSchema(unittest.TestCase):
568+
569+
def setUp(self):
570+
self.mock_bq_service = mock.Mock()
571+
self.mock_tables = mock.Mock()
572+
self.mock_bq_service.tables.return_value = self.mock_tables
573+
self.table = 'table'
574+
self.project = 'project'
575+
self.dataset = 'dataset'
576+
self.client = client.BigQueryClient(self.mock_bq_service, self.project)
577+
578+
def test_table_exists(self):
579+
"""Ensure that the table schema is returned if the table exists."""
580+
581+
expected = [
582+
{'type': 'FLOAT', 'name': 'foo', 'mode': 'NULLABLE'},
583+
{'type': 'INTEGER', 'name': 'bar', 'mode': 'NULLABLE'},
584+
{'type': 'INTEGER', 'name': 'baz', 'mode': 'NULLABLE'},
585+
]
586+
587+
self.mock_tables.get.return_value.execute.return_value = \
588+
{'schema': {'fields': expected}}
589+
590+
self.assertEqual(
591+
expected, self.client.get_table_schema(self.dataset, self.table))
592+
self.mock_tables.get.assert_called_once_with(
593+
projectId=self.project, tableId=self.table, datasetId=self.dataset)
594+
self.mock_tables.get.return_value.execute.assert_called_once_with()
595+
596+
def test_table_does_not_exist(self):
597+
"""Ensure that None is returned if the table doesn't exist."""
598+
from apiclient.errors import HttpError
599+
600+
self.mock_tables.get.return_value.execute.side_effect = \
601+
HttpError({'status': "404"}, '{}')
602+
603+
self.assertIsNone(
604+
self.client.get_table_schema(self.dataset, self.table))
605+
self.mock_tables.get.assert_called_once_with(
606+
projectId=self.project, tableId=self.table, datasetId=self.dataset)
607+
self.mock_tables.get.return_value.execute.assert_called_once_with()
608+
609+
567610
@mock.patch('bigquery.client.BigQueryClient._get_query_results')
568611
class TestGetQueryRows(unittest.TestCase):
569612

0 commit comments

Comments
 (0)