Skip to content

Commit

Permalink
feat: add property for maxStaleness in table definitions (#2087)
Browse files Browse the repository at this point in the history
* feat: add property for maxStaleness in table definitions

Signed-off-by: Yu Ishikawa <[email protected]>

* Update google/cloud/bigquery/table.py

---------

Signed-off-by: Yu Ishikawa <[email protected]>
Co-authored-by: Lingqing Gan <[email protected]>
  • Loading branch information
yu-iskw and Linchin authored Dec 6, 2024
1 parent 3359ef3 commit 729322c
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
35 changes: 35 additions & 0 deletions google/cloud/bigquery/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ class Table(_TableBase):
"view_query": "view",
"require_partition_filter": "requirePartitionFilter",
"table_constraints": "tableConstraints",
"max_staleness": "maxStaleness",
}

def __init__(self, table_ref, schema=None) -> None:
Expand Down Expand Up @@ -1115,6 +1116,40 @@ def __repr__(self):
def __str__(self):
return f"{self.project}.{self.dataset_id}.{self.table_id}"

@property
def max_staleness(self):
"""Union[str, None]: The maximum staleness of data that could be returned when the table is queried.
Staleness encoded as a string encoding of sql IntervalValue type.
This property is optional and defaults to None.
According to the BigQuery API documentation, maxStaleness specifies the maximum time
interval for which stale data can be returned when querying the table.
It helps control data freshness in scenarios like metadata-cached external tables.
Returns:
Optional[str]: A string representing the maximum staleness interval
(e.g., '1h', '30m', '15s' for hours, minutes, seconds respectively).
"""
return self._properties.get(self._PROPERTY_TO_API_FIELD["max_staleness"])

@max_staleness.setter
def max_staleness(self, value):
"""Set the maximum staleness for the table.
Args:
value (Optional[str]): A string representing the maximum staleness interval.
Must be a valid time interval string.
Examples include '1h' (1 hour), '30m' (30 minutes), '15s' (15 seconds).
Raises:
ValueError: If the value is not None and not a string.
"""
if value is not None and not isinstance(value, str):
raise ValueError("max_staleness must be a string or None")

self._properties[self._PROPERTY_TO_API_FIELD["max_staleness"]] = value


class TableListItem(_TableBase):
"""A read-only table resource from a list operation.
Expand Down
43 changes: 43 additions & 0 deletions tests/unit/test_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,49 @@ def test___str__(self):
table1 = self._make_one(TableReference(dataset, "table1"))
self.assertEqual(str(table1), "project1.dataset1.table1")

def test_max_staleness_getter(self):
"""Test getting max_staleness property."""
dataset = DatasetReference("test-project", "test_dataset")
table_ref = dataset.table("test_table")
table = self._make_one(table_ref)
# Initially None
self.assertIsNone(table.max_staleness)
# Set max_staleness using setter
table.max_staleness = "1h"
self.assertEqual(table.max_staleness, "1h")

def test_max_staleness_setter(self):
"""Test setting max_staleness property."""
dataset = DatasetReference("test-project", "test_dataset")
table_ref = dataset.table("test_table")
table = self._make_one(table_ref)
# Set valid max_staleness
table.max_staleness = "30m"
self.assertEqual(table.max_staleness, "30m")
# Set to None
table.max_staleness = None
self.assertIsNone(table.max_staleness)

def test_max_staleness_setter_invalid_type(self):
"""Test setting max_staleness with an invalid type raises ValueError."""
dataset = DatasetReference("test-project", "test_dataset")
table_ref = dataset.table("test_table")
table = self._make_one(table_ref)
# Try setting invalid type
with self.assertRaises(ValueError):
table.max_staleness = 123 # Not a string

def test_max_staleness_to_api_repr(self):
"""Test max_staleness is correctly represented in API representation."""
dataset = DatasetReference("test-project", "test_dataset")
table_ref = dataset.table("test_table")
table = self._make_one(table_ref)
# Set max_staleness
table.max_staleness = "1h"
# Convert to API representation
resource = table.to_api_repr()
self.assertEqual(resource.get("maxStaleness"), "1h")


class Test_row_from_mapping(unittest.TestCase, _SchemaBase):
PROJECT = "prahj-ekt"
Expand Down

0 comments on commit 729322c

Please sign in to comment.