This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 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 12d3e52950 [python] Support ignore_if_exists param for database and
table (#6314)
12d3e52950 is described below
commit 12d3e5295098ea138cf02bd76033c6d685d86b16
Author: umi <[email protected]>
AuthorDate: Wed Sep 24 09:48:33 2025 +0800
[python] Support ignore_if_exists param for database and table (#6314)
---
.../pypaimon/catalog/rest/rest_catalog.py | 35 +++++++++---
paimon-python/pypaimon/tests/predicates_test.py | 66 +++++++++++-----------
paimon-python/pypaimon/tests/pvfs_test.py | 14 -----
.../pypaimon/tests/py36/ao_simple_test.py | 55 ++++++++++++++++++
paimon-python/pypaimon/tests/rest/rest_server.py | 21 ++++++-
.../pypaimon/tests/rest/rest_simple_test.py | 55 ++++++++++++++++++
paimon-python/pypaimon/tests/serializable_test.py | 2 +-
7 files changed, 190 insertions(+), 58 deletions(-)
diff --git a/paimon-python/pypaimon/catalog/rest/rest_catalog.py
b/paimon-python/pypaimon/catalog/rest/rest_catalog.py
index f203169fbd..5e36559a7b 100644
--- a/paimon-python/pypaimon/catalog/rest/rest_catalog.py
+++ b/paimon-python/pypaimon/catalog/rest/rest_catalog.py
@@ -22,11 +22,12 @@ from urllib.parse import urlparse
from pypaimon.api.api_response import GetTableResponse, PagedList
from pypaimon.api.options import Options
from pypaimon.api.rest_api import RESTApi
-from pypaimon.api.rest_exception import NoSuchResourceException
+from pypaimon.api.rest_exception import NoSuchResourceException,
AlreadyExistsException
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 TableNotExistException
+from pypaimon.catalog.catalog_exception import TableNotExistException,
DatabaseAlreadyExistException, \
+ TableAlreadyExistException, DatabaseNotExistException
from pypaimon.catalog.database import Database
from pypaimon.catalog.rest.property_change import PropertyChange
from pypaimon.catalog.rest.rest_token_file_io import RESTTokenFileIO
@@ -107,7 +108,12 @@ class RESTCatalog(Catalog):
return self.rest_api.list_databases_paged(max_results, page_token,
database_name_pattern)
def create_database(self, name: str, ignore_if_exists: bool, properties:
Dict[str, str] = None):
- self.rest_api.create_database(name, properties)
+ try:
+ self.rest_api.create_database(name, properties)
+ except AlreadyExistsException as e:
+ if not ignore_if_exists:
+ # Convert REST API exception to catalog exception
+ raise DatabaseAlreadyExistException(name) from e
def get_database(self, name: str) -> Database:
response = self.rest_api.get_database(name)
@@ -117,8 +123,13 @@ class RESTCatalog(Catalog):
if response is not None:
return Database(name, options)
- def drop_database(self, name: str):
- self.rest_api.drop_database(name)
+ def drop_database(self, name: str, ignore_if_exists: bool = False):
+ try:
+ self.rest_api.drop_database(name)
+ except NoSuchResourceException as e:
+ if not ignore_if_exists:
+ # Convert REST API exception to catalog exception
+ raise DatabaseNotExistException(name) from e
def alter_database(self, name: str, changes: List[PropertyChange]):
set_properties, remove_keys =
PropertyChange.get_set_properties_to_remove_keys(changes)
@@ -154,12 +165,20 @@ class RESTCatalog(Catalog):
def create_table(self, identifier: Union[str, Identifier], schema: Schema,
ignore_if_exists: bool):
if not isinstance(identifier, Identifier):
identifier = Identifier.from_string(identifier)
- self.rest_api.create_table(identifier, schema)
+ try:
+ self.rest_api.create_table(identifier, schema)
+ except AlreadyExistsException as e:
+ if not ignore_if_exists:
+ raise TableAlreadyExistException(identifier) from e
- def drop_table(self, identifier: Union[str, Identifier]):
+ def drop_table(self, identifier: Union[str, Identifier], ignore_if_exists:
bool = False):
if not isinstance(identifier, Identifier):
identifier = Identifier.from_string(identifier)
- self.rest_api.drop_table(identifier)
+ try:
+ self.rest_api.drop_table(identifier)
+ except NoSuchResourceException as e:
+ if not ignore_if_exists:
+ raise TableNotExistException(identifier) from e
def load_table_metadata(self, identifier: Identifier) -> TableMetadata:
response = self.rest_api.get_table(identifier)
diff --git a/paimon-python/pypaimon/tests/predicates_test.py
b/paimon-python/pypaimon/tests/predicates_test.py
index 0ddebc3451..7976094290 100644
--- a/paimon-python/pypaimon/tests/predicates_test.py
+++ b/paimon-python/pypaimon/tests/predicates_test.py
@@ -81,14 +81,14 @@ class PredicateTest(unittest.TestCase):
cls.df = df
- def testWrongFieldName(self):
+ def test_wrong_field_name(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
with self.assertRaises(ValueError) as e:
predicate_builder.equal('f2', 'a')
self.assertEqual(str(e.exception), "The field f2 is not in field list
['f0', 'f1'].")
- def testAppendWithDuplicate(self):
+ def test_append_with_duplicate(self):
pa_schema = pa.schema([
('f0', pa.int64()),
('f1', pa.string()),
@@ -121,7 +121,7 @@ class PredicateTest(unittest.TestCase):
actual_df = read.to_pandas(scan.plan().splits())
self.assertEqual(len(actual_df), 0)
- def testAllFieldTypesWithEqual(self):
+ def test_all_field_types_with_equal(self):
pa_schema = pa.schema([
# int
('_tinyint', pa.int8()),
@@ -194,169 +194,169 @@ class PredicateTest(unittest.TestCase):
predicate = predicate_builder.equal('_boolean', True)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
df.loc[[0]])
- def testEqualPk(self):
+ def test_equal_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.equal('f0', 1)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[[0]])
- def testNotEqualAppend(self):
+ def test_not_equal_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.not_equal('f0', 1)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[1:4])
- def testNotEqualPk(self):
+ def test_not_equal_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.not_equal('f0', 1)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[1:4])
- def testLessThanAppend(self):
+ def test_less_than_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.less_than('f0', 3)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:1])
- def testLessThanPk(self):
+ def test_less_than_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.less_than('f0', 3)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:1])
- def testLessOrEqualAppend(self):
+ def test_less_or_equal_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.less_or_equal('f0', 3)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:2])
- def testLessOrEqualPk(self):
+ def test_less_or_equal_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.less_or_equal('f0', 3)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:2])
- def testGreaterThanAppend(self):
+ def test_greater_than_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.greater_than('f0', 3)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[3:4])
- def testGreaterThanPk(self):
+ def test_greater_than_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.greater_than('f0', 3)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[3:4])
- def testGreaterOrEqualAppend(self):
+ def test_greater_or_equal_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.greater_or_equal('f0', 3)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[2:4])
- def testGreaterOrEqualPk(self):
+ def test_greater_or_equal_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.greater_or_equal('f0', 3)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[2:4])
- def testIsNullAppend(self):
+ def test_is_null_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.is_null('f1')
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[[4]])
- def testIsNullPk(self):
+ def test_is_null_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.is_null('f1')
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[[4]])
- def testIsNotNullAppend(self):
+ def test_is_not_null_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.is_not_null('f1')
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:3])
- def testIsNotNullPk(self):
+ def test_is_not_null_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.is_not_null('f1')
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:3])
- def testStartswithAppend(self):
+ def test_startswith_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.startswith('f1', 'ab')
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:1])
- def testStartswithPk(self):
+ def test_startswith_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.startswith('f1', 'ab')
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:1])
- def testEndswithAppend(self):
+ def test_endswith_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.endswith('f1', 'bc')
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:2])
- def testEndswithPk(self):
+ def test_endswith_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.endswith('f1', 'bc')
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:2])
- def testContainsAppend(self):
+ def test_contains_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.contains('f1', 'bb')
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[[1]])
- def testContainsPk(self):
+ def test_contains_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.contains('f1', 'bb')
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[[1]])
- def testIsInAppend(self):
+ def test_is_in_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.is_in('f0', [1, 2])
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:1])
- def testIsInPk(self):
+ def test_is_in_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.is_in('f1', ['abc', 'd'])
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[[0, 3]])
- def testIsNotInAppend(self):
+ def test_is_not_in_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.is_not_in('f0', [1, 2])
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[2:4])
- def testIsNotInPk(self):
+ def test_is_not_in_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.is_not_in('f1', ['abc', 'abbc'])
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[2:4])
- def testBetweenAppend(self):
+ def test_between_append(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.between('f0', 1, 3)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:2])
- def testBetweenPk(self):
+ def test_between_pk(self):
table = self.catalog.get_table('default.test_pk')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate = predicate_builder.between('f0', 1, 3)
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[0:2])
- def testAndPredicates(self):
+ def test_and_predicates(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate1 = predicate_builder.greater_than('f0', 1)
@@ -364,7 +364,7 @@ class PredicateTest(unittest.TestCase):
predicate = predicate_builder.and_predicates([predicate1, predicate2])
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[[1]])
- def testOrPredicates(self):
+ def test_or_predicates(self):
table = self.catalog.get_table('default.test_append')
predicate_builder = table.new_read_builder().new_predicate_builder()
predicate1 = predicate_builder.greater_than('f0', 3)
@@ -373,7 +373,7 @@ class PredicateTest(unittest.TestCase):
_check_filtered_result(table.new_read_builder().with_filter(predicate),
self.df.loc[[0, 3, 4]])
- def testPkReaderWithFilter(self):
+ def test_pk_reader_with_filter(self):
pa_schema = pa.schema([
pa.field('key1', pa.int32(), nullable=False),
pa.field('key2', pa.string(), nullable=False),
diff --git a/paimon-python/pypaimon/tests/pvfs_test.py
b/paimon-python/pypaimon/tests/pvfs_test.py
index 89c96a6228..29ef979f9e 100644
--- a/paimon-python/pypaimon/tests/pvfs_test.py
+++ b/paimon-python/pypaimon/tests/pvfs_test.py
@@ -26,9 +26,6 @@ import pandas
from pypaimon import PaimonVirtualFileSystem
from pypaimon.api.api_response import ConfigResponse
from pypaimon.api.auth import BearTokenAuthProvider
-from pypaimon.catalog.rest.table_metadata import TableMetadata
-from pypaimon.schema.data_types import AtomicType, DataField
-from pypaimon.schema.table_schema import TableSchema
from pypaimon.tests.rest.api_test import RESTCatalogServer
@@ -67,17 +64,6 @@ class PVFSTest(unittest.TestCase):
self.test_databases = {
self.database: self.server.mock_database(self.database, {"k1":
"v1", "k2": "v2"}),
}
- data_fields = [
- DataField(0, "id", AtomicType('INT'), 'id'),
- DataField(1, "name", AtomicType('STRING'), 'name')
- ]
- schema = TableSchema(TableSchema.CURRENT_VERSION, len(data_fields),
data_fields, len(data_fields),
- [], [], {}, "")
- self.server.database_store.update(self.test_databases)
- self.test_tables = {
- f"{self.database}.{self.table}":
TableMetadata(uuid=str(uuid.uuid4()), is_external=True, schema=schema),
- }
- self.server.table_metadata_store.update(self.test_tables)
def tearDown(self):
if self.temp_path.exists():
diff --git a/paimon-python/pypaimon/tests/py36/ao_simple_test.py
b/paimon-python/pypaimon/tests/py36/ao_simple_test.py
index 17ebf58be7..584ba87587 100644
--- a/paimon-python/pypaimon/tests/py36/ao_simple_test.py
+++ b/paimon-python/pypaimon/tests/py36/ao_simple_test.py
@@ -18,6 +18,8 @@ limitations under the License.
import pyarrow as pa
from pypaimon import Schema
+from pypaimon.catalog.catalog_exception import TableNotExistException,
TableAlreadyExistException, \
+ DatabaseNotExistException, DatabaseAlreadyExistException
from pypaimon.tests.py36.pyarrow_compat import table_sort_by
from pypaimon.tests.rest.rest_base_test import RESTBaseTest
@@ -330,3 +332,56 @@ class AOSimpleTest(RESTBaseTest):
splits = read_builder.new_scan().with_shard(3, 4).plan().splits()
actual = table_read.to_arrow(splits)
self.assertEqual(len(actual), 2)
+
+ def test_create_drop_database_table(self):
+ # test create database
+ self.rest_catalog.create_database("db1", False)
+
+ with self.assertRaises(DatabaseAlreadyExistException) as context:
+ self.rest_catalog.create_database("db1", False)
+
+ self.assertEqual("db1", context.exception.database)
+
+ try:
+ self.rest_catalog.create_database("db1", True)
+ except DatabaseAlreadyExistException:
+ self.fail("create_database with ignore_if_exists=True should not
raise DatabaseAlreadyExistException")
+
+ # test create table
+ self.rest_catalog.create_table("db1.tbl1",
+
Schema.from_pyarrow_schema(self.pa_schema, partition_keys=['dt']),
+ False)
+ with self.assertRaises(TableAlreadyExistException) as context:
+ self.rest_catalog.create_table("db1.tbl1",
+
Schema.from_pyarrow_schema(self.pa_schema, partition_keys=['dt']),
+ False)
+ self.assertEqual("db1.tbl1",
context.exception.identifier.get_full_name())
+
+ try:
+ self.rest_catalog.create_table("db1.tbl1",
+
Schema.from_pyarrow_schema(self.pa_schema, partition_keys=['dt']),
+ True)
+ except TableAlreadyExistException:
+ self.fail("create_table with ignore_if_exists=True should not
raise TableAlreadyExistException")
+
+ # test drop table
+ self.rest_catalog.drop_table("db1.tbl1", False)
+ with self.assertRaises(TableNotExistException) as context:
+ self.rest_catalog.drop_table("db1.tbl1", False)
+ self.assertEqual("db1.tbl1",
context.exception.identifier.get_full_name())
+
+ try:
+ self.rest_catalog.drop_table("db1.tbl1", True)
+ except TableNotExistException:
+ self.fail("drop_table with ignore_if_exists=True should not raise
TableNotExistException")
+
+ # test drop database
+ self.rest_catalog.drop_database("db1", False)
+ with self.assertRaises(DatabaseNotExistException) as context:
+ self.rest_catalog.drop_database("db1", False)
+ self.assertEqual("db1", context.exception.database)
+
+ try:
+ self.rest_catalog.drop_database("db1", True)
+ except DatabaseNotExistException:
+ self.fail("drop_database with ignore_if_exists=True should not
raise DatabaseNotExistException")
diff --git a/paimon-python/pypaimon/tests/rest/rest_server.py
b/paimon-python/pypaimon/tests/rest/rest_server.py
index 7290863eb9..8f7cf23944 100644
--- a/paimon-python/pypaimon/tests/rest/rest_server.py
+++ b/paimon-python/pypaimon/tests/rest/rest_server.py
@@ -38,7 +38,8 @@ from pypaimon.api.rest_util import RESTUtil
from pypaimon.catalog.catalog_exception import (DatabaseNoPermissionException,
DatabaseNotExistException,
TableNoPermissionException,
- TableNotExistException)
+ TableNotExistException,
DatabaseAlreadyExistException,
+ TableAlreadyExistException)
from pypaimon.catalog.rest.table_metadata import TableMetadata
from pypaimon.common.identifier import Identifier
from pypaimon.common.json_util import JSON
@@ -321,6 +322,16 @@ class RESTCatalogServer:
ErrorResponse.RESOURCE_TYPE_TABLE,
e.identifier.get_table_name(), str(e), 403
)
return self._mock_response(response, 403)
+ except DatabaseAlreadyExistException as e:
+ response = ErrorResponse(
+ ErrorResponse.RESOURCE_TYPE_DATABASE, e.database, str(e), 409
+ )
+ return self._mock_response(response, 409)
+ except TableAlreadyExistException as e:
+ response = ErrorResponse(
+ ErrorResponse.RESOURCE_TYPE_TABLE,
e.identifier.get_full_name(), str(e), 409
+ )
+ return self._mock_response(response, 409)
except Exception as e:
self.logger.error(f"Unexpected error: {e}")
response = ErrorResponse(None, None, str(e), 500)
@@ -377,6 +388,8 @@ class RESTCatalogServer:
return self._generate_final_list_databases_response(parameters,
databases)
if method == "POST":
create_database = JSON.from_json(data, CreateDatabaseRequest)
+ if create_database.name in self.database_store:
+ raise DatabaseAlreadyExistException(create_database.name)
self.database_store.update({
create_database.name: self.mock_database(create_database.name,
create_database.options)
})
@@ -412,6 +425,8 @@ class RESTCatalogServer:
return self._generate_final_list_tables_response(parameters,
tables)
elif method == "POST":
create_table = JSON.from_json(data, CreateTableRequest)
+ if create_table.identifier.get_full_name() in
self.table_metadata_store:
+ raise TableAlreadyExistException(create_table.identifier)
table_metadata = self._create_table_metadata(
create_table.identifier, 1, create_table.schema,
str(uuid.uuid4()), False
)
@@ -441,7 +456,9 @@ class RESTCatalogServer:
elif method == "DELETE":
# Drop table
- if identifier.get_full_name() in self.table_metadata_store:
+ if identifier.get_full_name() not in self.table_metadata_store:
+ raise TableNotExistException(identifier)
+ else:
del self.table_metadata_store[identifier.get_full_name()]
if identifier.get_full_name() in self.table_latest_snapshot_store:
del
self.table_latest_snapshot_store[identifier.get_full_name()]
diff --git a/paimon-python/pypaimon/tests/rest/rest_simple_test.py
b/paimon-python/pypaimon/tests/rest/rest_simple_test.py
index 03685c317a..1a53b825d4 100644
--- a/paimon-python/pypaimon/tests/rest/rest_simple_test.py
+++ b/paimon-python/pypaimon/tests/rest/rest_simple_test.py
@@ -21,6 +21,8 @@ import os
import pyarrow as pa
from pypaimon import Schema
+from pypaimon.catalog.catalog_exception import DatabaseAlreadyExistException,
TableAlreadyExistException, \
+ DatabaseNotExistException, TableNotExistException
from pypaimon.tests.rest.rest_base_test import RESTBaseTest
from pypaimon.write.row_key_extractor import FixedBucketRowKeyExtractor,
DynamicBucketRowKeyExtractor
@@ -558,3 +560,56 @@ class RESTSimpleTest(RESTBaseTest):
splits = read_builder.new_scan().plan().splits()
actual = table_read.to_arrow(splits)
self.assertTrue(not actual)
+
+ def test_create_drop_database_table(self):
+ # test create database
+ self.rest_catalog.create_database("db1", False)
+
+ with self.assertRaises(DatabaseAlreadyExistException) as context:
+ self.rest_catalog.create_database("db1", False)
+
+ self.assertEqual("db1", context.exception.database)
+
+ try:
+ self.rest_catalog.create_database("db1", True)
+ except DatabaseAlreadyExistException:
+ self.fail("create_database with ignore_if_exists=True should not
raise DatabaseAlreadyExistException")
+
+ # test create table
+ self.rest_catalog.create_table("db1.tbl1",
+
Schema.from_pyarrow_schema(self.pa_schema, partition_keys=['dt']),
+ False)
+ with self.assertRaises(TableAlreadyExistException) as context:
+ self.rest_catalog.create_table("db1.tbl1",
+
Schema.from_pyarrow_schema(self.pa_schema, partition_keys=['dt']),
+ False)
+ self.assertEqual("db1.tbl1",
context.exception.identifier.get_full_name())
+
+ try:
+ self.rest_catalog.create_table("db1.tbl1",
+
Schema.from_pyarrow_schema(self.pa_schema, partition_keys=['dt']),
+ True)
+ except TableAlreadyExistException:
+ self.fail("create_table with ignore_if_exists=True should not
raise TableAlreadyExistException")
+
+ # test drop table
+ self.rest_catalog.drop_table("db1.tbl1", False)
+ with self.assertRaises(TableNotExistException) as context:
+ self.rest_catalog.drop_table("db1.tbl1", False)
+ self.assertEqual("db1.tbl1",
context.exception.identifier.get_full_name())
+
+ try:
+ self.rest_catalog.drop_table("db1.tbl1", True)
+ except TableNotExistException:
+ self.fail("drop_table with ignore_if_exists=True should not raise
TableNotExistException")
+
+ # test drop database
+ self.rest_catalog.drop_database("db1", False)
+ with self.assertRaises(DatabaseNotExistException) as context:
+ self.rest_catalog.drop_database("db1", False)
+ self.assertEqual("db1", context.exception.database)
+
+ try:
+ self.rest_catalog.drop_database("db1", True)
+ except DatabaseNotExistException:
+ self.fail("drop_database with ignore_if_exists=True should not
raise DatabaseNotExistException")
diff --git a/paimon-python/pypaimon/tests/serializable_test.py
b/paimon-python/pypaimon/tests/serializable_test.py
index eed351e330..2081270120 100644
--- a/paimon-python/pypaimon/tests/serializable_test.py
+++ b/paimon-python/pypaimon/tests/serializable_test.py
@@ -54,7 +54,7 @@ class SerializableTest(unittest.TestCase):
def tearDownClass(cls):
shutil.rmtree(cls.tempdir, ignore_errors=True)
- def testPickleSerializable(self):
+ def test_pickle_serializable(self):
schema = Schema.from_pyarrow_schema(self.pa_schema,
partition_keys=['dt'],
primary_keys=['user_id', 'dt'],