Skip to content

Commit a98defd

Browse files
yu-iskwLinchin
authored andcommitted
feat: add property for maxStaleness in table definitions (googleapis#2087)
* feat: add property for maxStaleness in table definitions Signed-off-by: Yu Ishikawa <yu-iskw@users.noreply.github.com> * Update google/cloud/bigquery/table.py --------- Signed-off-by: Yu Ishikawa <yu-iskw@users.noreply.github.com> Co-authored-by: Lingqing Gan <lingqing.gan@gmail.com>
1 parent fd5fbd0 commit a98defd

2 files changed

Lines changed: 78 additions & 0 deletions

File tree

google/cloud/bigquery/table.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ class Table(_TableBase):
407407
"view_query": "view",
408408
"require_partition_filter": "requirePartitionFilter",
409409
"table_constraints": "tableConstraints",
410+
"max_staleness": "maxStaleness",
410411
}
411412

412413
def __init__(self, table_ref, schema=None) -> None:
@@ -1127,6 +1128,40 @@ def __repr__(self):
11271128
def __str__(self):
11281129
return f"{self.project}.{self.dataset_id}.{self.table_id}"
11291130

1131+
@property
1132+
def max_staleness(self):
1133+
"""Union[str, None]: The maximum staleness of data that could be returned when the table is queried.
1134+
1135+
Staleness encoded as a string encoding of sql IntervalValue type.
1136+
This property is optional and defaults to None.
1137+
1138+
According to the BigQuery API documentation, maxStaleness specifies the maximum time
1139+
interval for which stale data can be returned when querying the table.
1140+
It helps control data freshness in scenarios like metadata-cached external tables.
1141+
1142+
Returns:
1143+
Optional[str]: A string representing the maximum staleness interval
1144+
(e.g., '1h', '30m', '15s' for hours, minutes, seconds respectively).
1145+
"""
1146+
return self._properties.get(self._PROPERTY_TO_API_FIELD["max_staleness"])
1147+
1148+
@max_staleness.setter
1149+
def max_staleness(self, value):
1150+
"""Set the maximum staleness for the table.
1151+
1152+
Args:
1153+
value (Optional[str]): A string representing the maximum staleness interval.
1154+
Must be a valid time interval string.
1155+
Examples include '1h' (1 hour), '30m' (30 minutes), '15s' (15 seconds).
1156+
1157+
Raises:
1158+
ValueError: If the value is not None and not a string.
1159+
"""
1160+
if value is not None and not isinstance(value, str):
1161+
raise ValueError("max_staleness must be a string or None")
1162+
1163+
self._properties[self._PROPERTY_TO_API_FIELD["max_staleness"]] = value
1164+
11301165

11311166
class TableListItem(_TableBase):
11321167
"""A read-only table resource from a list operation.

tests/unit/test_table.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,49 @@ def test___str__(self):
14891489
table1 = self._make_one(TableReference(dataset, "table1"))
14901490
self.assertEqual(str(table1), "project1.dataset1.table1")
14911491

1492+
def test_max_staleness_getter(self):
1493+
"""Test getting max_staleness property."""
1494+
dataset = DatasetReference("test-project", "test_dataset")
1495+
table_ref = dataset.table("test_table")
1496+
table = self._make_one(table_ref)
1497+
# Initially None
1498+
self.assertIsNone(table.max_staleness)
1499+
# Set max_staleness using setter
1500+
table.max_staleness = "1h"
1501+
self.assertEqual(table.max_staleness, "1h")
1502+
1503+
def test_max_staleness_setter(self):
1504+
"""Test setting max_staleness property."""
1505+
dataset = DatasetReference("test-project", "test_dataset")
1506+
table_ref = dataset.table("test_table")
1507+
table = self._make_one(table_ref)
1508+
# Set valid max_staleness
1509+
table.max_staleness = "30m"
1510+
self.assertEqual(table.max_staleness, "30m")
1511+
# Set to None
1512+
table.max_staleness = None
1513+
self.assertIsNone(table.max_staleness)
1514+
1515+
def test_max_staleness_setter_invalid_type(self):
1516+
"""Test setting max_staleness with an invalid type raises ValueError."""
1517+
dataset = DatasetReference("test-project", "test_dataset")
1518+
table_ref = dataset.table("test_table")
1519+
table = self._make_one(table_ref)
1520+
# Try setting invalid type
1521+
with self.assertRaises(ValueError):
1522+
table.max_staleness = 123 # Not a string
1523+
1524+
def test_max_staleness_to_api_repr(self):
1525+
"""Test max_staleness is correctly represented in API representation."""
1526+
dataset = DatasetReference("test-project", "test_dataset")
1527+
table_ref = dataset.table("test_table")
1528+
table = self._make_one(table_ref)
1529+
# Set max_staleness
1530+
table.max_staleness = "1h"
1531+
# Convert to API representation
1532+
resource = table.to_api_repr()
1533+
self.assertEqual(resource.get("maxStaleness"), "1h")
1534+
14921535

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

0 commit comments

Comments
 (0)