Skip to content

Commit 2e61ff8

Browse files
[python] Reject operations on the system database (#10841)
1 parent 676b40c commit 2e61ff8

5 files changed

Lines changed: 40 additions & 3 deletions

File tree

‎paimon-python/pypaimon/catalog/catalog_utils.py‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from typing import Optional
2222

2323
from pypaimon.api.api_response import PagedList, Partition
24+
from pypaimon.catalog.catalog import Catalog
2425
from pypaimon.common.identifier import Identifier
2526
from pypaimon.table.table import Table
2627

@@ -49,9 +50,15 @@ def check_not_branch(identifier: Identifier, method: str) -> None:
4950
.format(method, identifier.get_full_name()))
5051

5152

53+
def check_not_system_database(name: str) -> None:
54+
"""Mirrors Java ``CatalogUtils.checkNotSystemDatabase``."""
55+
if name == Catalog.SYSTEM_DATABASE_NAME:
56+
raise ValueError("Can't do operation on system database.")
57+
58+
5259
def check_not_system_table(identifier: Identifier, method: str) -> None:
5360
"""Mirrors Java ``CatalogUtils.checkNotSystemTable``."""
54-
if identifier.is_system_table():
61+
if identifier.get_database_name() == Catalog.SYSTEM_DATABASE_NAME or identifier.is_system_table():
5562
raise ValueError(
5663
"Cannot '{}' for system table '{}', please use data table."
5764
.format(method, identifier.get_full_name()))

‎paimon-python/pypaimon/catalog/filesystem_catalog.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from pypaimon.catalog.catalog import Catalog
2222
from pypaimon.catalog.catalog_context import CatalogContext
2323
from pypaimon.catalog.catalog_environment import CatalogEnvironment
24-
from pypaimon.catalog.catalog_utils import check_not_branch, check_not_system_table
24+
from pypaimon.catalog.catalog_utils import check_not_branch, check_not_system_database, check_not_system_table
2525
from pypaimon.catalog.catalog_exception import (BranchAlreadyExistException,
2626
BranchNotExistException,
2727
DatabaseAlreadyExistException,
@@ -87,6 +87,7 @@ def get_database(self, name: str) -> Database:
8787

8888
def create_database(self, name: str, ignore_if_exists: bool,
8989
properties: Optional[Dict[str, str]] = None) -> None:
90+
check_not_system_database(name)
9091
try:
9192
self.get_database(name)
9293
if not ignore_if_exists:
@@ -98,6 +99,7 @@ def create_database(self, name: str, ignore_if_exists: bool,
9899
self.file_io.mkdirs(path)
99100

100101
def drop_database(self, name: str, ignore_if_not_exists: bool = False, cascade: bool = False) -> None:
102+
check_not_system_database(name)
101103
try:
102104
self.get_database(name)
103105
except DatabaseNotExistException:

‎paimon-python/pypaimon/catalog/jdbc_catalog.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from pypaimon.catalog.catalog_environment import CatalogEnvironment
2727
from pypaimon.catalog.catalog_utils import (
2828
check_not_branch,
29+
check_not_system_database,
2930
check_not_system_table,
3031
encoded_branch_name
3132
)
@@ -324,6 +325,7 @@ def get_database(self, name: str) -> Database:
324325

325326
def create_database(self, name: str, ignore_if_exists: bool,
326327
properties: Optional[Dict[str, str]] = None) -> None:
328+
check_not_system_database(name)
327329
if self._database_exists(name):
328330
if not ignore_if_exists:
329331
raise DatabaseAlreadyExistException(name)
@@ -337,6 +339,7 @@ def create_database(self, name: str, ignore_if_exists: bool,
337339
self._insert_database_properties(name, create_props)
338340

339341
def drop_database(self, name: str, ignore_if_not_exists: bool = False, cascade: bool = False) -> None:
342+
check_not_system_database(name)
340343
if not self._database_exists(name):
341344
if not ignore_if_not_exists:
342345
raise DatabaseNotExistException(name)
@@ -362,6 +365,7 @@ def drop_database(self, name: str, ignore_if_not_exists: bool = False, cascade:
362365
)
363366

364367
def alter_database(self, name: str, changes: List[PropertyChange]) -> None:
368+
check_not_system_database(name)
365369
self.get_database(name)
366370
set_properties, remove_keys = PropertyChange.get_set_properties_to_remove_keys(changes)
367371
current = self._fetch_database_properties(name)

‎paimon-python/pypaimon/catalog/rest/rest_catalog.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from pypaimon.catalog.catalog import Catalog
2929
from pypaimon.catalog.catalog_context import CatalogContext
3030
from pypaimon.catalog.catalog_environment import CatalogEnvironment
31-
from pypaimon.catalog.catalog_utils import check_not_branch, check_not_system_table
31+
from pypaimon.catalog.catalog_utils import check_not_branch, check_not_system_database, check_not_system_table
3232
from pypaimon.catalog.catalog_exception import (
3333
ColumnAlreadyExistException, ColumnNotExistException,
3434
TableNotExistException, DatabaseAlreadyExistException,
@@ -164,6 +164,7 @@ def list_databases_paged(self, max_results: Optional[int] = None, page_token: Op
164164

165165
def create_database(self, name: str, ignore_if_exists: bool,
166166
properties: Optional[Dict[str, str]] = None) -> None:
167+
check_not_system_database(name)
167168
try:
168169
self.rest_api.create_database(name, properties)
169170
except AlreadyExistsException as e:
@@ -187,6 +188,7 @@ def get_database(self, name: str) -> Database:
187188
raise DatabaseNoPermissionException(name) from e
188189

189190
def drop_database(self, name: str, ignore_if_not_exists: bool = False, cascade: bool = False) -> None:
191+
check_not_system_database(name)
190192
if not cascade:
191193
try:
192194
tables = self.list_tables(name)
@@ -209,6 +211,7 @@ def drop_database(self, name: str, ignore_if_not_exists: bool = False, cascade:
209211
raise DatabaseNoPermissionException(name) from e
210212

211213
def alter_database(self, name: str, changes: List[PropertyChange]) -> None:
214+
check_not_system_database(name)
212215
try:
213216
set_properties, remove_keys = PropertyChange.get_set_properties_to_remove_keys(changes)
214217
self.rest_api.alter_database(name, list(remove_keys), set_properties)

‎paimon-python/pypaimon/tests/catalog_table_guard_test.py‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import pyarrow as pa
2525

2626
from pypaimon import CatalogFactory, Schema
27+
from pypaimon.catalog.catalog import Catalog
28+
from pypaimon.catalog.rest.property_change import PropertyChange
2729
from pypaimon.common.identifier import Identifier
2830
from pypaimon.schema.data_types import AtomicType
2931
from pypaimon.schema.schema_change import SchemaChange
@@ -79,6 +81,25 @@ def assert_table_guards(test, catalog, database):
7981
catalog.drop_table(Identifier(database, 'm2', branch='main'), False)
8082
test.assertEqual(catalog.list_tables(database), ['t'])
8183

84+
# As in Java, the sys database and the tables in it cannot be created, dropped or changed.
85+
operations = [
86+
lambda: catalog.create_database('sys', True),
87+
lambda: catalog.drop_database('sys', True),
88+
lambda: catalog.create_table('sys.t', schema, True),
89+
lambda: catalog.drop_table('sys.t', True),
90+
lambda: catalog.rename_table(name, 'sys.t'),
91+
lambda: catalog.alter_table('sys.t', [add_column]),
92+
]
93+
if type(catalog).alter_database is not Catalog.alter_database:
94+
operations.append(lambda: catalog.alter_database('sys', [PropertyChange.set_property('k', 'v')]))
95+
for operation in operations:
96+
with test.assertRaises(ValueError):
97+
operation()
98+
with test.assertRaisesRegex(ValueError, "Can't do operation on system database."):
99+
catalog.create_database('sys', False)
100+
test.assertNotIn('sys', catalog.list_databases())
101+
test.assertEqual(catalog.list_tables(database), ['t'])
102+
82103

83104
class CatalogTableGuardTest(unittest.TestCase):
84105

0 commit comments

Comments
 (0)