Skip to content

Commit

Permalink
BigQuery: replaces table.create() with client.create_table() (#4038)
Browse files Browse the repository at this point in the history
* adds client.create_table()

* removes table.create()

* passes system tests

* fixes rebase conflicts

* fixes coverage
  • Loading branch information
alixhami authored and tswast committed Sep 22, 2017
1 parent f3fa77f commit da41ad4
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 273 deletions.
18 changes: 18 additions & 0 deletions bigquery/google/cloud/bigquery/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,24 @@ def create_dataset(self, dataset):
method='POST', path=path, data=dataset._build_resource())
return Dataset.from_api_repr(api_response)

def create_table(self, table):
"""API call: create a table via a PUT request
See
https://cloud.google.com/bigquery/docs/reference/rest/v2/tables/insert
:type table: :class:`~google.cloud.bigquery.table.Table`
:param table: A ``Table`` populated with the desired initial state.
:rtype: ":class:`~google.cloud.bigquery.table.Table`"
:returns: a new ``Table`` returned from the service.
"""
path = '/projects/%s/datasets/%s/tables' % (
table.project, table.dataset_id)
api_response = self._connection.api_request(
method='POST', path=path, data=table._build_resource())
return Table.from_api_repr(api_response, self)

def get_dataset(self, dataset_ref):
"""Fetch the dataset referenced by ``dataset_ref``
Expand Down
18 changes: 0 additions & 18 deletions bigquery/google/cloud/bigquery/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,24 +653,6 @@ def _build_resource(self):

return resource

def create(self, client=None):
"""API call: create the table via a PUT request
See
https://cloud.google.com/bigquery/docs/reference/rest/v2/tables/insert
:type client: :class:`~google.cloud.bigquery.client.Client` or
``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current dataset.
"""
client = self._require_client(client)
path = '/projects/%s/datasets/%s/tables' % (
self._project, self._dataset_id)
api_response = client._connection.api_request(
method='POST', path=path, data=self._build_resource())
self._set_properties(api_response)

def exists(self, client=None):
"""API call: test for the existence of the table via a GET request
Expand Down
83 changes: 42 additions & 41 deletions bigquery/tests/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,18 +180,19 @@ def test_list_datasets(self):

def test_create_table(self):
dataset = self.temp_dataset(_make_dataset_id('create_table'))

TABLE_NAME = 'test_table'
table_id = 'test_table'
full_name = bigquery.SchemaField('full_name', 'STRING',
mode='REQUIRED')
age = bigquery.SchemaField('age', 'INTEGER', mode='REQUIRED')
table = Table(dataset.table(TABLE_NAME), schema=[full_name, age],
client=Config.CLIENT)
self.assertFalse(table.exists())
table.create()
table_arg = Table(dataset.table(table_id), schema=[full_name, age],
client=Config.CLIENT)
self.assertFalse(table_arg.exists())

table = retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)

self.assertTrue(table.exists())
self.assertEqual(table.table_id, TABLE_NAME)
self.assertEqual(table.table_id, table_id)

def test_get_table_w_public_dataset(self):
PUBLIC = 'bigquery-public-data'
Expand Down Expand Up @@ -227,10 +228,10 @@ def test_list_dataset_tables(self):
mode='REQUIRED')
age = bigquery.SchemaField('age', 'INTEGER', mode='REQUIRED')
for table_name in tables_to_create:
created_table = Table(dataset.table(table_name),
schema=[full_name, age],
client=Config.CLIENT)
created_table.create()
table = Table(dataset.table(table_name),
schema=[full_name, age],
client=Config.CLIENT)
created_table = retry_403(Config.CLIENT.create_table)(table)
self.to_delete.insert(0, created_table)

# Retrieve the tables.
Expand All @@ -249,10 +250,10 @@ def test_patch_table(self):
full_name = bigquery.SchemaField('full_name', 'STRING',
mode='REQUIRED')
age = bigquery.SchemaField('age', 'INTEGER', mode='REQUIRED')
table = Table(dataset.table(TABLE_NAME), schema=[full_name, age],
client=Config.CLIENT)
self.assertFalse(table.exists())
table.create()
table_arg = Table(dataset.table(TABLE_NAME), schema=[full_name, age],
client=Config.CLIENT)
self.assertFalse(table_arg.exists())
table = retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)
self.assertTrue(table.exists())
self.assertIsNone(table.friendly_name)
Expand All @@ -268,10 +269,10 @@ def test_update_table(self):
full_name = bigquery.SchemaField('full_name', 'STRING',
mode='REQUIRED')
age = bigquery.SchemaField('age', 'INTEGER', mode='REQUIRED')
table = Table(dataset.table(TABLE_NAME), schema=[full_name, age],
client=Config.CLIENT)
self.assertFalse(table.exists())
table.create()
table_arg = Table(dataset.table(TABLE_NAME), schema=[full_name, age],
client=Config.CLIENT)
self.assertFalse(table_arg.exists())
table = retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)
self.assertTrue(table.exists())
voter = bigquery.SchemaField('voter', 'BOOLEAN', mode='NULLABLE')
Expand Down Expand Up @@ -309,10 +310,10 @@ def test_insert_data_then_dump_table(self):
mode='REQUIRED')
age = bigquery.SchemaField('age', 'INTEGER', mode='REQUIRED')
now = bigquery.SchemaField('now', 'TIMESTAMP')
table = Table(dataset.table(TABLE_NAME), schema=[full_name, age, now],
client=Config.CLIENT)
self.assertFalse(table.exists())
table.create()
table_arg = Table(dataset.table(TABLE_NAME),
schema=[full_name, age, now], client=Config.CLIENT)
self.assertFalse(table_arg.exists())
table = retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)
self.assertTrue(table.exists())

Expand Down Expand Up @@ -346,9 +347,9 @@ def test_load_table_from_local_file_then_dump_table(self):
full_name = bigquery.SchemaField('full_name', 'STRING',
mode='REQUIRED')
age = bigquery.SchemaField('age', 'INTEGER', mode='REQUIRED')
table = Table(dataset.table(TABLE_NAME), schema=[full_name, age],
client=Config.CLIENT)
table.create()
table_arg = Table(dataset.table(TABLE_NAME), schema=[full_name, age],
client=Config.CLIENT)
table = retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)

with _NamedTemporaryFile() as temp:
Expand Down Expand Up @@ -450,9 +451,9 @@ def test_load_table_from_storage_then_dump_table(self):
full_name = bigquery.SchemaField('full_name', 'STRING',
mode='REQUIRED')
age = bigquery.SchemaField('age', 'INTEGER', mode='REQUIRED')
table = Table(dataset.table(TABLE_NAME), schema=[full_name, age],
client=Config.CLIENT)
table.create()
table_arg = Table(dataset.table(TABLE_NAME), schema=[full_name, age],
client=Config.CLIENT)
table = retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)

job = Config.CLIENT.load_table_from_storage(
Expand Down Expand Up @@ -652,9 +653,9 @@ def test_job_cancel(self):
full_name = bigquery.SchemaField('full_name', 'STRING',
mode='REQUIRED')
age = bigquery.SchemaField('age', 'INTEGER', mode='REQUIRED')
table = Table(dataset.table(TABLE_NAME), schema=[full_name, age],
client=Config.CLIENT)
table.create()
table_arg = Table(dataset.table(TABLE_NAME), schema=[full_name, age],
client=Config.CLIENT)
table = retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)

job = Config.CLIENT.run_async_query(JOB_NAME, QUERY)
Expand Down Expand Up @@ -839,9 +840,9 @@ def _load_table_for_dml(self, rows, dataset_id, table_id):
dataset = self.temp_dataset(dataset_id)
greeting = bigquery.SchemaField(
'greeting', 'STRING', mode='NULLABLE')
table = Table(dataset.table(table_id), schema=[greeting],
client=Config.CLIENT)
table.create()
table_arg = Table(dataset.table(table_id), schema=[greeting],
client=Config.CLIENT)
table = retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)

with _NamedTemporaryFile() as temp:
Expand Down Expand Up @@ -1210,9 +1211,9 @@ def test_insert_nested_nested(self):
]
table_name = 'test_table'
dataset = self.temp_dataset(_make_dataset_id('issue_2951'))
table = Table(dataset.table(table_name), schema=schema,
client=Config.CLIENT)
table.create()
table_arg = Table(dataset.table(table_name), schema=schema,
client=Config.CLIENT)
table = retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)

table.insert_data(to_insert)
Expand All @@ -1227,9 +1228,9 @@ def test_create_table_insert_fetch_nested_schema(self):
dataset = self.temp_dataset(
_make_dataset_id('create_table_nested_schema'))
schema = _load_json_schema()
table = Table(dataset.table(table_name), schema=schema,
client=Config.CLIENT)
table.create()
table_arg = Table(dataset.table(table_name), schema=schema,
client=Config.CLIENT)
table = retry_403(Config.CLIENT.create_table)(table_arg)
self.to_delete.insert(0, table)
self.assertTrue(table.exists())
self.assertEqual(table.table_id, table_name)
Expand Down
145 changes: 145 additions & 0 deletions bigquery/tests/unit/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,151 @@ def test_create_dataset_w_attrs(self):
self.assertEqual(ds.default_table_expiration_ms, 3600)
self.assertEqual(ds.labels, LABELS)

def test_create_table_w_day_partition(self):
from google.cloud.bigquery.table import Table

project = 'PROJECT'
dataset_id = 'dataset_id'
table_id = 'table-id'
path = 'projects/%s/datasets/%s/tables' % (
project, dataset_id)
creds = _make_credentials()
client = self._make_one(project=project, credentials=creds)
resource = {
'id': '%s:%s:%s' % (project, dataset_id, table_id),
'tableReference': {
'projectId': project,
'datasetId': dataset_id,
'tableId': table_id
},
}
conn = client._connection = _Connection(resource)
table_ref = client.dataset(dataset_id).table(table_id)
table = Table(table_ref, client=client)
table.partitioning_type = 'DAY'

got = client.create_table(table)

self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'POST')
self.assertEqual(req['path'], '/%s' % path)
sent = {
'tableReference': {
'projectId': project,
'datasetId': dataset_id,
'tableId': table_id
},
'timePartitioning': {'type': 'DAY'},
}
self.assertEqual(req['data'], sent)
self.assertEqual(table.partitioning_type, "DAY")
self.assertEqual(got.table_id, table_id)

def test_create_table_w_day_partition_and_expire(self):
from google.cloud.bigquery.table import Table

project = 'PROJECT'
dataset_id = 'dataset_id'
table_id = 'table-id'
path = 'projects/%s/datasets/%s/tables' % (
project, dataset_id)
creds = _make_credentials()
client = self._make_one(project=project, credentials=creds)
resource = {
'id': '%s:%s:%s' % (project, dataset_id, table_id),
'tableReference': {
'projectId': project,
'datasetId': dataset_id,
'tableId': table_id
},
}
conn = client._connection = _Connection(resource)
table_ref = client.dataset(dataset_id).table(table_id)
table = Table(table_ref, client=client)
table.partitioning_type = 'DAY'
table.partition_expiration = 100

got = client.create_table(table)

self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'POST')
self.assertEqual(req['path'], '/%s' % path)
sent = {
'tableReference': {
'projectId': project,
'datasetId': dataset_id,
'tableId': table_id
},
'timePartitioning': {'type': 'DAY', 'expirationMs': 100},
}
self.assertEqual(req['data'], sent)
self.assertEqual(table.partitioning_type, "DAY")
self.assertEqual(table.partition_expiration, 100)
self.assertEqual(got.table_id, table_id)

def test_create_table_w_schema_and_query(self):
from google.cloud.bigquery.table import Table, SchemaField

project = 'PROJECT'
dataset_id = 'dataset_id'
table_id = 'table-id'
path = 'projects/%s/datasets/%s/tables' % (
project, dataset_id)
query = 'SELECT * from %s:%s' % (dataset_id, table_id)
creds = _make_credentials()
client = self._make_one(project=project, credentials=creds)
resource = {
'id': '%s:%s:%s' % (project, dataset_id, table_id),
'tableReference': {
'projectId': project,
'datasetId': dataset_id,
'tableId': table_id
},
'schema': {'fields': [
{'name': 'full_name', 'type': 'STRING', 'mode': 'REQUIRED'},
{'name': 'age', 'type': 'INTEGER', 'mode': 'REQUIRED'}]
},
'view': {
'query': query,
'useLegacySql': True
},
}
schema = [
SchemaField('full_name', 'STRING', mode='REQUIRED'),
SchemaField('age', 'INTEGER', mode='REQUIRED')
]
conn = client._connection = _Connection(resource)
table_ref = client.dataset(dataset_id).table(table_id)
table = Table(table_ref, schema=schema, client=client)
table.view_query = query

got = client.create_table(table)

self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'POST')
self.assertEqual(req['path'], '/%s' % path)
sent = {
'tableReference': {
'projectId': project,
'datasetId': dataset_id,
'tableId': table_id
},
'schema': {'fields': [
{'name': 'full_name', 'type': 'STRING', 'mode': 'REQUIRED'},
{'name': 'age', 'type': 'INTEGER', 'mode': 'REQUIRED'}]
},
'view': {'query': query},
}
self.assertEqual(req['data'], sent)
self.assertEqual(got.table_id, table_id)
self.assertEqual(got.project, project)
self.assertEqual(got.dataset_id, dataset_id)
self.assertEqual(got.schema, schema)
self.assertEqual(got.view_query, query)

def test_get_table(self):
project = 'PROJECT'
dataset_id = 'dataset_id'
Expand Down
Loading

0 comments on commit da41ad4

Please sign in to comment.