|
34 | 34 | _MARKER = object()
|
35 | 35 |
|
36 | 36 |
|
| 37 | +def _view_use_legacy_sql_getter(table): |
| 38 | + """Specifies whether to execute the view with Legacy or Standard SQL. |
| 39 | +
|
| 40 | + If this table is not a view, None is returned. |
| 41 | +
|
| 42 | + Returns: |
| 43 | + bool: True if the view is using legacy SQL, or None if not a view |
| 44 | + """ |
| 45 | + view = table._properties.get('view') |
| 46 | + if view is not None: |
| 47 | + # The server-side default for useLegacySql is True. |
| 48 | + return view.get('useLegacySql', True) |
| 49 | + # In some cases, such as in a table list no view object is present, but the |
| 50 | + # resource still represents a view. Use the type as a fallback. |
| 51 | + if table.table_type == 'VIEW': |
| 52 | + # The server-side default for useLegacySql is True. |
| 53 | + return True |
| 54 | + |
| 55 | + |
37 | 56 | class TableReference(object):
|
38 | 57 | """TableReferences are pointers to tables.
|
39 | 58 |
|
@@ -531,23 +550,7 @@ def view_query(self):
|
531 | 550 | """Delete SQL query defining the table as a view."""
|
532 | 551 | self._properties.pop('view', None)
|
533 | 552 |
|
534 |
| - @property |
535 |
| - def view_use_legacy_sql(self): |
536 |
| - """Specifies whether to execute the view with Legacy or Standard SQL. |
537 |
| -
|
538 |
| - The default is False for views (use Standard SQL). |
539 |
| - If this table is not a view, None is returned. |
540 |
| -
|
541 |
| - :rtype: bool or ``NoneType`` |
542 |
| - :returns: The boolean for view.useLegacySql, or None if not a view. |
543 |
| - """ |
544 |
| - view = self._properties.get('view') |
545 |
| - if view is not None: |
546 |
| - # useLegacySql is never missing from the view dict if this table |
547 |
| - # was created client-side, because the view_query setter populates |
548 |
| - # it. So a missing or None can only come from the server, whose |
549 |
| - # default is True. |
550 |
| - return view.get('useLegacySql', True) |
| 553 | + view_use_legacy_sql = property(_view_use_legacy_sql_getter) |
551 | 554 |
|
552 | 555 | @view_use_legacy_sql.setter
|
553 | 556 | def view_use_legacy_sql(self, value):
|
@@ -713,6 +716,133 @@ def _build_resource(self, filter_fields):
|
713 | 716 | return resource
|
714 | 717 |
|
715 | 718 |
|
| 719 | +class TableListItem(object): |
| 720 | + """A read-only table resource from a list operation. |
| 721 | +
|
| 722 | + For performance reasons, the BigQuery API only includes some of the table |
| 723 | + properties when listing tables. Notably, |
| 724 | + :attr:`~google.cloud.bigquery.table.Table.schema` and |
| 725 | + :attr:`~google.cloud.bigquery.table.Table.num_rows` are missing. |
| 726 | +
|
| 727 | + For a full list of the properties that the BigQuery API returns, see the |
| 728 | + `REST documentation for tables.list |
| 729 | + <https://cloud.google.com/bigquery/docs/reference/rest/v2/tables/list>`_. |
| 730 | +
|
| 731 | +
|
| 732 | + Args: |
| 733 | + resource (dict): |
| 734 | + A table-like resource object from a table list response. |
| 735 | + """ |
| 736 | + |
| 737 | + def __init__(self, resource): |
| 738 | + self._properties = resource |
| 739 | + |
| 740 | + @property |
| 741 | + def project(self): |
| 742 | + """The project ID of the project this table belongs to. |
| 743 | +
|
| 744 | + Returns: |
| 745 | + str: the project ID of the table. |
| 746 | + """ |
| 747 | + return self._properties.get('tableReference', {}).get('projectId') |
| 748 | + |
| 749 | + @property |
| 750 | + def dataset_id(self): |
| 751 | + """The dataset ID of the dataset this table belongs to. |
| 752 | +
|
| 753 | + Returns: |
| 754 | + str: the dataset ID of the table. |
| 755 | + """ |
| 756 | + return self._properties.get('tableReference', {}).get('datasetId') |
| 757 | + |
| 758 | + @property |
| 759 | + def table_id(self): |
| 760 | + """The table ID. |
| 761 | +
|
| 762 | + Returns: |
| 763 | + str: the table ID. |
| 764 | + """ |
| 765 | + return self._properties.get('tableReference', {}).get('tableId') |
| 766 | + |
| 767 | + @property |
| 768 | + def reference(self): |
| 769 | + """A :class:`~google.cloud.bigquery.table.TableReference` pointing to |
| 770 | + this table. |
| 771 | +
|
| 772 | + Returns: |
| 773 | + google.cloud.bigquery.table.TableReference: pointer to this table |
| 774 | + """ |
| 775 | + from google.cloud.bigquery import dataset |
| 776 | + |
| 777 | + dataset_ref = dataset.DatasetReference(self.project, self.dataset_id) |
| 778 | + return TableReference(dataset_ref, self.table_id) |
| 779 | + |
| 780 | + @property |
| 781 | + def labels(self): |
| 782 | + """Labels for the table. |
| 783 | +
|
| 784 | + This method always returns a dict. To change a table's labels, |
| 785 | + modify the dict, then call ``Client.update_table``. To delete a |
| 786 | + label, set its value to ``None`` before updating. |
| 787 | +
|
| 788 | + Returns: |
| 789 | + Map[str, str]: A dictionary of the the table's labels |
| 790 | + """ |
| 791 | + return self._properties.get('labels', {}) |
| 792 | + |
| 793 | + @property |
| 794 | + def full_table_id(self): |
| 795 | + """ID for the table, in the form ``project_id:dataset_id:table_id``. |
| 796 | +
|
| 797 | + Returns: |
| 798 | + str: The fully-qualified ID of the table |
| 799 | + """ |
| 800 | + return self._properties.get('id') |
| 801 | + |
| 802 | + @property |
| 803 | + def table_type(self): |
| 804 | + """The type of the table. |
| 805 | +
|
| 806 | + Possible values are "TABLE", "VIEW", or "EXTERNAL". |
| 807 | +
|
| 808 | + Returns: |
| 809 | + str: The kind of table |
| 810 | + """ |
| 811 | + return self._properties.get('type') |
| 812 | + |
| 813 | + @property |
| 814 | + def partitioning_type(self): |
| 815 | + """Time partitioning of the table. |
| 816 | +
|
| 817 | + Returns: |
| 818 | + str: |
| 819 | + Type of partitioning if the table is partitioned, None |
| 820 | + otherwise. |
| 821 | + """ |
| 822 | + return self._properties.get('timePartitioning', {}).get('type') |
| 823 | + |
| 824 | + @property |
| 825 | + def partition_expiration(self): |
| 826 | + """Expiration time in ms for a partition |
| 827 | +
|
| 828 | + Returns: |
| 829 | + int: The time in ms for partition expiration |
| 830 | + """ |
| 831 | + return int( |
| 832 | + self._properties.get('timePartitioning', {}).get('expirationMs')) |
| 833 | + |
| 834 | + @property |
| 835 | + def friendly_name(self): |
| 836 | + """Title of the table. |
| 837 | +
|
| 838 | + Returns: |
| 839 | + str: The name as set by the user, or None (the default) |
| 840 | + """ |
| 841 | + return self._properties.get('friendlyName') |
| 842 | + |
| 843 | + view_use_legacy_sql = property(_view_use_legacy_sql_getter) |
| 844 | + |
| 845 | + |
716 | 846 | def _row_from_mapping(mapping, schema):
|
717 | 847 | """Convert a mapping to a row tuple using the schema.
|
718 | 848 |
|
|
0 commit comments