|
32 | 32 | from google.cloud.streaming.transfer import RESUMABLE_UPLOAD |
33 | 33 | from google.cloud.streaming.transfer import Upload |
34 | 34 | from google.cloud.bigquery.schema import SchemaField |
35 | | -from google.cloud.bigquery._helpers import _rows_from_json |
| 35 | +from google.cloud.bigquery._helpers import _row_from_json |
| 36 | +from google.cloud.iterator import HTTPIterator |
36 | 37 |
|
37 | 38 |
|
38 | 39 | _TABLE_HAS_NO_SCHEMA = "Table has no schema: call 'table.reload()'" |
@@ -653,47 +654,36 @@ def fetch_data(self, max_results=None, page_token=None, client=None): |
653 | 654 | up-to-date with the schema as defined on the back-end: if the |
654 | 655 | two schemas are not identical, the values returned may be |
655 | 656 | incomplete. To ensure that the local copy of the schema is |
656 | | - up-to-date, call the table's ``reload`` method. |
| 657 | + up-to-date, call :meth:`reload`. |
657 | 658 |
|
658 | 659 | :type max_results: int |
659 | | - :param max_results: (Optional) maximum number of rows to return. |
| 660 | + :param max_results: (Optional) Maximum number of rows to return. |
660 | 661 |
|
661 | 662 | :type page_token: str |
662 | | - :param page_token: |
663 | | - (Optional) token representing a cursor into the table's rows. |
664 | | -
|
665 | | - :type client: :class:`~google.cloud.bigquery.client.Client` or |
666 | | - ``NoneType`` |
667 | | - :param client: the client to use. If not passed, falls back to the |
668 | | - ``client`` stored on the current dataset. |
669 | | -
|
670 | | - :rtype: tuple |
671 | | - :returns: ``(row_data, total_rows, page_token)``, where ``row_data`` |
672 | | - is a list of tuples, one per result row, containing only |
673 | | - the values; ``total_rows`` is a count of the total number |
674 | | - of rows in the table; and ``page_token`` is an opaque |
675 | | - string which can be used to fetch the next batch of rows |
676 | | - (``None`` if no further batches can be fetched). |
| 663 | + :param page_token: (Optional) Token representing a cursor into the |
| 664 | + table's rows. |
| 665 | +
|
| 666 | + :type client: :class:`~google.cloud.bigquery.client.Client` |
| 667 | + :param client: (Optional) The client to use. If not passed, falls |
| 668 | + back to the ``client`` stored on the current dataset. |
| 669 | +
|
| 670 | + :rtype: :class:`~google.cloud.iterator.Iterator` |
| 671 | + :returns: Iterator of row data :class:`tuple`s. During each page, the |
| 672 | + iterator will have the ``total_rows`` attribute set, |
| 673 | + which counts the total number of rows **in the table** |
| 674 | + (this is distinct from the total number of rows in the |
| 675 | + current page: ``iterator.page.num_items``). |
677 | 676 | """ |
678 | 677 | client = self._require_client(client) |
679 | | - params = {} |
680 | | - |
681 | | - if max_results is not None: |
682 | | - params['maxResults'] = max_results |
683 | | - |
684 | | - if page_token is not None: |
685 | | - params['pageToken'] = page_token |
686 | | - |
687 | | - response = client.connection.api_request(method='GET', |
688 | | - path='%s/data' % self.path, |
689 | | - query_params=params) |
690 | | - total_rows = response.get('totalRows') |
691 | | - if total_rows is not None: |
692 | | - total_rows = int(total_rows) |
693 | | - page_token = response.get('pageToken') |
694 | | - rows_data = _rows_from_json(response.get('rows', ()), self._schema) |
695 | | - |
696 | | - return rows_data, total_rows, page_token |
| 678 | + path = '%s/data' % (self.path,) |
| 679 | + iterator = HTTPIterator(client=client, path=path, |
| 680 | + item_to_value=_item_to_row, items_key='rows', |
| 681 | + page_token=page_token, max_results=max_results, |
| 682 | + page_start=_rows_page_start) |
| 683 | + iterator.schema = self._schema |
| 684 | + # Over-ride the key used to retrieve the next page token. |
| 685 | + iterator._NEXT_TOKEN = 'pageToken' |
| 686 | + return iterator |
697 | 687 |
|
698 | 688 | def insert_data(self, |
699 | 689 | rows, |
@@ -1083,6 +1073,47 @@ def _build_schema_resource(fields): |
1083 | 1073 | return infos |
1084 | 1074 |
|
1085 | 1075 |
|
| 1076 | +def _item_to_row(iterator, resource): |
| 1077 | + """Convert a JSON row to the native object. |
| 1078 | +
|
| 1079 | + .. note:: |
| 1080 | +
|
| 1081 | + This assumes that the ``schema`` attribute has been |
| 1082 | + added to the iterator after being created, which |
| 1083 | + should be done by the caller. |
| 1084 | +
|
| 1085 | + :type iterator: :class:`~google.cloud.iterator.Iterator` |
| 1086 | + :param iterator: The iterator that is currently in use. |
| 1087 | +
|
| 1088 | + :type resource: dict |
| 1089 | + :param resource: An item to be converted to a row. |
| 1090 | +
|
| 1091 | + :rtype: tuple |
| 1092 | + :returns: The next row in the page. |
| 1093 | + """ |
| 1094 | + return _row_from_json(resource, iterator.schema) |
| 1095 | + |
| 1096 | + |
| 1097 | +# pylint: disable=unused-argument |
| 1098 | +def _rows_page_start(iterator, page, response): |
| 1099 | + """Grab total rows after a :class:`~google.cloud.iterator.Page` started. |
| 1100 | +
|
| 1101 | + :type iterator: :class:`~google.cloud.iterator.Iterator` |
| 1102 | + :param iterator: The iterator that is currently in use. |
| 1103 | +
|
| 1104 | + :type page: :class:`~google.cloud.iterator.Page` |
| 1105 | + :param page: The page that was just created. |
| 1106 | +
|
| 1107 | + :type response: dict |
| 1108 | + :param response: The JSON API response for a page of rows in a table. |
| 1109 | + """ |
| 1110 | + total_rows = response.get('totalRows') |
| 1111 | + if total_rows is not None: |
| 1112 | + total_rows = int(total_rows) |
| 1113 | + iterator.total_rows = total_rows |
| 1114 | +# pylint: enable=unused-argument |
| 1115 | + |
| 1116 | + |
1086 | 1117 | class _UploadConfig(object): |
1087 | 1118 | """Faux message FBO apitools' 'configure_request'.""" |
1088 | 1119 | accept = ['*/*'] |
|
0 commit comments