This is an automated email from the ASF dual-hosted git repository.
JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new a03d897bd1 [python] Map column and database errors in REST alter_table
and create_table (#10816)
a03d897bd1 is described below
commit a03d897bd187bb9bd07bb82555bc26a8f2cb9c3b
Author: Jiajia Li <[email protected]>
AuthorDate: Tue Oct 27 14:14:35 2026 +0800
[python] Map column and database errors in REST alter_table and
create_table (#10816)
---
.../pypaimon/catalog/rest/rest_catalog.py | 9 +++++++
.../pypaimon/tests/rest/rest_catalog_test.py | 30 ++++++++++++++++++++++
paimon-python/pypaimon/tests/rest/rest_server.py | 12 +++++++++
3 files changed, 51 insertions(+)
diff --git a/paimon-python/pypaimon/catalog/rest/rest_catalog.py
b/paimon-python/pypaimon/catalog/rest/rest_catalog.py
index 0766140e00..c561a1d03f 100644
--- a/paimon-python/pypaimon/catalog/rest/rest_catalog.py
+++ b/paimon-python/pypaimon/catalog/rest/rest_catalog.py
@@ -29,6 +29,7 @@ from pypaimon.catalog.catalog import Catalog
from pypaimon.catalog.catalog_context import CatalogContext
from pypaimon.catalog.catalog_environment import CatalogEnvironment
from pypaimon.catalog.catalog_exception import (
+ ColumnAlreadyExistException, ColumnNotExistException,
TableNotExistException, DatabaseAlreadyExistException,
TableAlreadyExistException, DatabaseNotExistException,
TableNoPermissionException, DatabaseNoPermissionException,
@@ -299,6 +300,8 @@ class RESTCatalog(Catalog):
except AlreadyExistsException as e:
if not ignore_if_exists:
raise TableAlreadyExistException(identifier) from e
+ except NoSuchResourceException as e:
+ raise DatabaseNotExistException(identifier.get_database_name())
from e
def rename_table(self, source_identifier: Union[str, Identifier],
target_identifier: Union[str, Identifier]) -> None:
@@ -424,7 +427,13 @@ class RESTCatalog(Catalog):
self.rest_api.alter_table(identifier, changes)
except NoSuchResourceException as e:
if not ignore_if_not_exists:
+ if e.resource_type == ErrorResponse.RESOURCE_TYPE_COLUMN:
+ raise ColumnNotExistException(e.resource_name) from e
raise TableNotExistException(identifier) from e
+ except AlreadyExistsException as e:
+ if e.resource_type == ErrorResponse.RESOURCE_TYPE_COLUMN:
+ raise ColumnAlreadyExistException(e.resource_name) from e
+ raise
except ForbiddenException as e:
raise TableNoPermissionException(identifier) from e
diff --git a/paimon-python/pypaimon/tests/rest/rest_catalog_test.py
b/paimon-python/pypaimon/tests/rest/rest_catalog_test.py
index a691c38ab8..521be62ab5 100644
--- a/paimon-python/pypaimon/tests/rest/rest_catalog_test.py
+++ b/paimon-python/pypaimon/tests/rest/rest_catalog_test.py
@@ -371,6 +371,36 @@ class RESTCatalogTest(RESTBaseTest):
with self.assertRaises(TableIdNoPermissionException):
self.rest_catalog.get_table_by_id(table_id)
+ def test_alter_table_column_errors(self):
+ from pypaimon.catalog.catalog_exception import
(ColumnAlreadyExistException,
+
ColumnNotExistException,
+ TableNotExistException)
+ from pypaimon.schema.data_types import AtomicType
+ from pypaimon.schema.schema_change import SchemaChange
+ identifier = "default.alter_table_column_errors"
+ pa_schema = pa.schema([('col1', pa.int32())])
+ self.rest_catalog.create_table(identifier,
Schema.from_pyarrow_schema(pa_schema), False)
+
+ with self.assertRaises(ColumnNotExistException) as context:
+ self.rest_catalog.alter_table(identifier,
[SchemaChange.drop_column('missing')])
+ self.assertIn("missing", str(context.exception))
+ with self.assertRaises(ColumnAlreadyExistException) as context:
+ self.rest_catalog.alter_table(identifier,
[SchemaChange.add_column('col1', AtomicType('INT'))])
+ self.assertIn("col1", str(context.exception))
+
+ missing = "default.no_such_table"
+ with self.assertRaises(TableNotExistException):
+ self.rest_catalog.alter_table(missing,
[SchemaChange.drop_column('col1')])
+ self.rest_catalog.alter_table(missing,
[SchemaChange.drop_column('col1')], True)
+
+ def test_create_table_in_missing_database(self):
+ from pypaimon.catalog.catalog_exception import
DatabaseNotExistException
+ pa_schema = pa.schema([('col1', pa.int32())])
+ with self.assertRaises(DatabaseNotExistException) as context:
+ self.rest_catalog.create_table(
+ "no_such_db.table", Schema.from_pyarrow_schema(pa_schema),
False)
+ self.assertIn("no_such_db", str(context.exception))
+
def test_catalog_load_snapshot_after_rollback(self):
"""Test load_snapshot returns correct snapshot after rollback."""
table_name = "default.table_load_snapshot_after_rollback"
diff --git a/paimon-python/pypaimon/tests/rest/rest_server.py
b/paimon-python/pypaimon/tests/rest/rest_server.py
index f38c648ed8..893ad85b99 100755
--- a/paimon-python/pypaimon/tests/rest/rest_server.py
+++ b/paimon-python/pypaimon/tests/rest/rest_server.py
@@ -62,6 +62,8 @@ from pypaimon.api.resource_paths import ResourcePaths
from pypaimon.api.rest_util import RESTUtil
from pypaimon.catalog.catalog_exception import (BranchAlreadyExistException,
BranchNotExistException,
+ ColumnAlreadyExistException,
+ ColumnNotExistException,
DatabaseNoPermissionException,
DatabaseNotExistException,
TableNoPermissionException,
@@ -1231,6 +1233,16 @@ class RESTCatalogServer:
ErrorResponse.RESOURCE_TYPE_DEFINITION, e.name, str(e), 404
)
return self._mock_response(response, 404)
+ except ColumnNotExistException as e:
+ response = ErrorResponse(
+ ErrorResponse.RESOURCE_TYPE_COLUMN, e.column, str(e), 404
+ )
+ return self._mock_response(response, 404)
+ except ColumnAlreadyExistException as e:
+ response = ErrorResponse(
+ ErrorResponse.RESOURCE_TYPE_COLUMN, e.column, str(e), 409
+ )
+ return self._mock_response(response, 409)
except ValueError as e:
response = ErrorResponse(None, None, str(e), 400)
return self._mock_response(response, 400)