Skip to content

Commit ad0eca2

Browse files
Leave out non-current Iceberg columns and do not retry twice
Glue keeps an Iceberg table's dropped and renamed columns, marked iceberg.field.current=false, which Athena's GetTableMetadata leaves out. Measured after DROP COLUMN and CHANGE COLUMN; the Glue path now matches. A first attempt that failed on a code its policy already retried is not retried again with the full policy; only a MetadataException the first attempt left out is. HasTableTest caught the doubled retries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 141d7ba commit ad0eca2

3 files changed

Lines changed: 40 additions & 3 deletions

File tree

‎pyathena/common.py‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,11 @@ def _route_after_athena_failure(
353353
if _get_error_code(cause, unwrap_metadata=True) in THROTTLING_ERROR_CODES:
354354
_logger.warning(f"Request to {description} was throttled; reading it from Glue.")
355355
return True
356-
# The first attempt left out MetadataException, which the policy may retry.
357-
if is_retryable_error(cause, self._retry_config):
356+
# The first attempt left out MetadataException, which the policy may retry;
357+
# a code it did retry has already had its retries.
358+
if is_retryable_error(cause, self._retry_config) and not is_retryable_error(
359+
cause, self._glue_first_attempt_retry_config()
360+
):
358361
return False
359362
if logging_:
360363
_logger.exception(f"Failed to {description}.")

‎pyathena/glue.py‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ def table_metadata(table: Mapping[str, Any]) -> AthenaTableMetadata:
9090
location and formats are always present, the SerDe library whenever
9191
the descriptor has SerDe information, and SerDe parameters with a
9292
``serde.param.`` prefix. The Glue description is not the table comment.
93+
Glue keeps an Iceberg table's dropped and renamed columns, marked as
94+
not current, which Athena leaves out.
9395
9496
Args:
9597
table: A ``Table`` from a Glue ``GetTable`` or ``GetTables`` response.
@@ -119,7 +121,11 @@ def column(c: Mapping[str, Any]) -> dict[str, Any]:
119121
"CreateTime": table.get("CreateTime"),
120122
"LastAccessTime": table.get("LastAccessTime"),
121123
"TableType": table.get("TableType"),
122-
"Columns": [column(c) for c in descriptor.get("Columns") or []],
124+
"Columns": [
125+
column(c)
126+
for c in descriptor.get("Columns") or []
127+
if (c.get("Parameters") or {}).get("iceberg.field.current") != "false"
128+
],
123129
"PartitionKeys": [column(c) for c in table.get("PartitionKeys") or []],
124130
"Parameters": parameters,
125131
}

‎tests/pyathena/test_glue.py‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,34 @@ def test_requests_address_the_catalog(self, catalog_name, catalog_kwargs):
7272
("get_databases", catalog_kwargs),
7373
]
7474

75+
def test_table_metadata_leaves_out_columns_iceberg_no_longer_has(self):
76+
# Glue's columns after DROP COLUMN b and CHANGE COLUMN a a2, as measured
77+
# for #786; Athena reports a2, c and d.
78+
def column(name, current):
79+
return {
80+
"Name": name,
81+
"Type": "int",
82+
"Parameters": {"iceberg.field.current": current, "iceberg.field.id": "1"},
83+
}
84+
85+
table = {
86+
"Name": "t",
87+
"Parameters": {"table_type": "ICEBERG"},
88+
"StorageDescriptor": {
89+
"Columns": [
90+
column("a2", "true"),
91+
column("c", "true"),
92+
column("d", "true"),
93+
column("a", "false"),
94+
column("b", "false"),
95+
]
96+
},
97+
}
98+
99+
metadata = GlueMetadataCatalog.table_metadata(table)
100+
101+
assert [c.name for c in metadata.columns] == ["a2", "c", "d"]
102+
75103
@pytest.mark.parametrize(
76104
("table", "expected_parameters"),
77105
[

0 commit comments

Comments
 (0)