Content-Length: 567890 | pFad | http://github.com/googleapis/google-cloud-python/commit/019e905f84f3bd24e071d975cfd632b8eb28f205

AD Call get_table in list_rows if the schema is not available (#7621) · googleapis/google-cloud-python@019e905 · GitHub
Skip to content

Commit 019e905

Browse files
authored
Call get_table in list_rows if the schema is not available (#7621)
This is kinder than raising an error message saying to call get_table yourself. Also, it guarantees the schema is as up-to-date as possible. This also fixes an issue where rows could not be listed on the TableListItem objects that are returned from list_tables.
1 parent 28ad1a8 commit 019e905

File tree

3 files changed

+77
-20
lines changed

3 files changed

+77
-20
lines changed

bigquery/google/cloud/bigquery/client.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,15 +1694,19 @@ def list_rows(
16941694
Args:
16951695
table (Union[ \
16961696
:class:`~google.cloud.bigquery.table.Table`, \
1697+
:class:`~google.cloud.bigquery.table.TableListItem`, \
16971698
:class:`~google.cloud.bigquery.table.TableReference`, \
16981699
str, \
16991700
]):
1700-
The table to list, or a reference to it.
1701+
The table to list, or a reference to it. When the table
1702+
object does not contain a schema and ``selected_fields`` is
1703+
not supplied, this method calls ``get_table`` to fetch the
1704+
table schema.
17011705
selected_fields (Sequence[ \
17021706
:class:`~google.cloud.bigquery.schema.SchemaField` \
17031707
]):
1704-
The fields to return. Required if ``table`` is a
1705-
:class:`~google.cloud.bigquery.table.TableReference`.
1708+
The fields to return. If not supplied, data for all columns
1709+
are downloaded.
17061710
max_results (int):
17071711
(Optional) maximum number of rows to return.
17081712
page_token (str):
@@ -1741,14 +1745,11 @@ def list_rows(
17411745
if selected_fields is not None:
17421746
schema = selected_fields
17431747

1744-
# Allow listing rows of an empty table by not raising if the table exists.
1745-
elif len(schema) == 0 and table.created is None:
1746-
raise ValueError(
1747-
(
1748-
"Could not determine schema for table '{}'. Call client.get_table() "
1749-
"or pass in a list of schema fields to the selected_fields argument."
1750-
).format(table)
1751-
)
1748+
# No schema, but no selected_fields. Assume the developer wants all
1749+
# columns, so get the table resource for them rather than failing.
1750+
elif len(schema) == 0:
1751+
table = self.get_table(table.reference, retry=retry)
1752+
schema = table.schema
17521753

17531754
params = {}
17541755
if selected_fields is not None:

bigquery/google/cloud/bigquery/table.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,5 +1752,9 @@ def _table_arg_to_table(value, default_project=None):
17521752
value = TableReference.from_string(value, default_project=default_project)
17531753
if isinstance(value, TableReference):
17541754
value = Table(value)
1755+
if isinstance(value, TableListItem):
1756+
newvalue = Table(value.reference)
1757+
newvalue._properties = value._properties
1758+
value = newvalue
17551759

17561760
return value

bigquery/tests/unit/test_client.py

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4276,20 +4276,72 @@ def test_list_rows_w_record_schema(self):
42764276
method="GET", path="/%s" % PATH, query_params={}
42774277
)
42784278

4279-
def test_list_rows_errors(self):
4280-
from google.cloud.bigquery.table import Table
4279+
def test_list_rows_with_missing_schema(self):
4280+
from google.cloud.bigquery.table import Table, TableListItem
4281+
4282+
table_path = "/projects/{}/datasets/{}/tables/{}".format(
4283+
self.PROJECT, self.DS_ID, self.TABLE_ID
4284+
)
4285+
tabledata_path = "{}/data".format(table_path)
4286+
4287+
table_list_item_data = {
4288+
"id": "%s:%s:%s" % (self.PROJECT, self.DS_ID, self.TABLE_ID),
4289+
"tableReference": {
4290+
"projectId": self.PROJECT,
4291+
"datasetId": self.DS_ID,
4292+
"tableId": self.TABLE_ID,
4293+
},
4294+
}
4295+
table_data = copy.deepcopy(table_list_item_data)
4296+
# Intentionally make wrong, since total_rows can update during iteration.
4297+
table_data["numRows"] = 2
4298+
table_data["schema"] = {
4299+
"fields": [
4300+
{"name": "name", "type": "STRING"},
4301+
{"name": "age", "type": "INTEGER"},
4302+
]
4303+
}
4304+
rows_data = {
4305+
"totalRows": 3,
4306+
"pageToken": None,
4307+
"rows": [
4308+
{"f": [{"v": "Phred Phlyntstone"}, {"v": "32"}]},
4309+
{"f": [{"v": "Bharney Rhubble"}, {"v": "31"}]},
4310+
{"f": [{"v": "Wylma Phlyntstone"}, {"v": None}]},
4311+
],
4312+
}
42814313

42824314
creds = _make_credentials()
42834315
http = object()
4284-
client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
42854316

4286-
# table ref with no selected fields
4287-
with self.assertRaises(ValueError):
4288-
client.list_rows(self.TABLE_REF)
4317+
schemaless_tables = (
4318+
"{}.{}".format(self.DS_ID, self.TABLE_ID),
4319+
self.TABLE_REF,
4320+
Table(self.TABLE_REF),
4321+
TableListItem(table_list_item_data),
4322+
)
42894323

4290-
# table with no schema
4291-
with self.assertRaises(ValueError):
4292-
client.list_rows(Table(self.TABLE_REF))
4324+
for table in schemaless_tables:
4325+
client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
4326+
conn = client._connection = _make_connection(table_data, rows_data)
4327+
4328+
row_iter = client.list_rows(table)
4329+
4330+
conn.api_request.assert_called_once_with(method="GET", path=table_path)
4331+
conn.api_request.reset_mock()
4332+
self.assertIsNone(row_iter.total_rows, msg=repr(table))
4333+
4334+
rows = list(row_iter)
4335+
conn.api_request.assert_called_once_with(
4336+
method="GET", path=tabledata_path, query_params={}
4337+
)
4338+
self.assertEqual(row_iter.total_rows, 3, msg=repr(table))
4339+
self.assertEqual(rows[0].name, "Phred Phlyntstone", msg=repr(table))
4340+
self.assertEqual(rows[1].age, 31, msg=repr(table))
4341+
self.assertIsNone(rows[2].age, msg=repr(table))
4342+
4343+
def test_list_rows_error(self):
4344+
client = self._make_one()
42934345

42944346
# neither Table nor tableReference
42954347
with self.assertRaises(TypeError):

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/googleapis/google-cloud-python/commit/019e905f84f3bd24e071d975cfd632b8eb28f205

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy