1919import logging
2020import socket
2121import time
22+ from collections import namedtuple
2223from types import TracebackType
2324from typing import (
2425 TYPE_CHECKING ,
3334)
3435from urllib .parse import urlparse
3536
36- from hive_metastore .v4 .ThriftHiveMetastore import Client
37- from hive_metastore .v4 .ttypes import (
37+ from hive_metastore .v3 .ThriftHiveMetastore import Client
38+ from hive_metastore .v3 .ttypes import (
3839 AlreadyExistsException ,
3940 CheckLockRequest ,
4041 EnvironmentContext ,
5455 StorageDescriptor ,
5556 UnlockRequest ,
5657)
57- from hive_metastore .v4 .ttypes import (
58+ from hive_metastore .v3 .ttypes import (
5859 Database as HiveDatabase ,
5960)
60- from hive_metastore .v4 .ttypes import (
61+ from hive_metastore .v3 .ttypes import (
6162 Table as HiveTable ,
6263)
6364from tenacity import retry , retry_if_exception_type , stop_after_attempt , wait_exponential
148149DEFAULT_LOCK_CHECK_RETRIES = 4
149150DO_NOT_UPDATE_STATS = "DO_NOT_UPDATE_STATS"
150151DO_NOT_UPDATE_STATS_DEFAULT = "true"
152+ HiveVersion = namedtuple ("HiveVersion" , "major minor patch" )
151153
152154logger = logging .getLogger (__name__ )
153155
@@ -157,7 +159,7 @@ class _HiveClient:
157159
158160 _transport : TTransport
159161 _ugi : Optional [List [str ]]
160- _hive_version : int = 4
162+ _hive_version : HiveVersion = HiveVersion ( 4 , 0 , 0 )
161163 _hms_v3 : object
162164 _hms_v4 : object
163165
@@ -177,13 +179,15 @@ def __init__(
177179 self .hms_v4 = importlib .import_module ("hive_metastore.v4.ThriftHiveMetastore" )
178180 self ._hive_version = self ._get_hive_version ()
179181
180- def _get_hive_version (self ) -> int :
182+ def _get_hive_version (self ) -> HiveVersion :
181183 with self as open_client :
182- major , * _ = open_client .getVersion ().split ("." )
183- return int ( major )
184+ version = map ( int , open_client .getVersion ().split ("." ) )
185+ return HiveVersion ( * version )
184186
185187 def _init_thrift_transport (self ) -> TTransport :
186188 url_parts = urlparse (self ._uri )
189+ if not url_parts .hostname or not url_parts .port :
190+ raise ValueError ("hive hostname and port must be set" )
187191 socket = TSocket .TSocket (url_parts .hostname , url_parts .port )
188192 if not self ._kerberos_auth :
189193 return TTransport .TBufferedTransport (socket )
@@ -192,7 +196,7 @@ def _init_thrift_transport(self) -> TTransport:
192196
193197 def _client (self ) -> Client :
194198 protocol = TBinaryProtocol .TBinaryProtocol (self ._transport )
195- hms = self .hms_v3 if self ._hive_version < 4 else self .hms_v4
199+ hms = self .hms_v4 if all (( self ._hive_version . major >= 4 , self . _hive_version . patch > 0 )) else self .hms_v3
196200 client : Client = hms .Client (protocol )
197201 if self ._ugi :
198202 client .set_ugi (* self ._ugi )
@@ -407,14 +411,17 @@ def _create_hive_table(self, open_client: Client, hive_table: HiveTable) -> None
407411 raise TableAlreadyExistsError (f"Table { hive_table .dbName } .{ hive_table .tableName } already exists" ) from e
408412
409413 def _get_hive_table (self , open_client : Client , * , dbname : str , tbl_name : str ) -> HiveTable :
410- if open_client ._hive_version < 4 :
414+ try :
415+ if all ((self ._client ._hive_version .major >= 4 , self ._client ._hive_version .patch > 0 )):
416+ return open_client .get_table_req (GetTableRequest (dbName = dbname , tblName = tbl_name )).table
411417 return open_client .get_table (dbname = dbname , tbl_name = tbl_name )
412- return open_client .get_table_req (GetTableRequest (dbName = dbname , tblName = tbl_name )).table
418+ except NoSuchObjectException as e :
419+ raise NoSuchTableError (f"Table does not exists: { tbl_name } " ) from e
413420
414421 def _get_table_objects_by_name (self , open_client : Client , * , dbname : str , tbl_names : list [str ]) -> list [HiveTable ]:
415- if open_client . _hive_version < 4 :
416- return open_client .get_table_objects_by_name ( dbname = dbname , tbl_names = tbl_names )
417- return open_client .get_table_objects_by_name_req ( GetTablesRequest ( dbName = dbname , tblNames = tbl_names )). tables
422+ if all (( self . _client . _hive_version . major >= 4 , self . _client . _hive_version . patch > 0 )) :
423+ return open_client .get_table_objects_by_name_req ( GetTablesRequest ( dbName = dbname , tblNames = tbl_names )). tables
424+ return open_client .get_table_objects_by_name ( dbname = dbname , tbl_names = tbl_names )
418425
419426 def create_table (
420427 self ,
@@ -458,7 +465,7 @@ def create_table(
458465
459466 with self ._client as open_client :
460467 self ._create_hive_table (open_client , tbl )
461- hive_table : HiveTable = self ._get_hive_table (open_client , dbname = database_name , tbl_name = table_name )
468+ hive_table = self ._get_hive_table (open_client , dbname = database_name , tbl_name = table_name )
462469
463470 return self ._convert_hive_into_iceberg (hive_table )
464471
@@ -488,7 +495,7 @@ def register_table(self, identifier: Union[str, Identifier], metadata_location:
488495 tbl = self ._convert_iceberg_into_hive (staged_table )
489496 with self ._client as open_client :
490497 self ._create_hive_table (open_client , tbl )
491- hive_table : HiveTable = self ._get_hive_table (open_client , dbname = database_name , tbl_name = table_name )
498+ hive_table = self ._get_hive_table (open_client , dbname = database_name , tbl_name = table_name )
492499
493500 return self ._convert_hive_into_iceberg (hive_table )
494501
@@ -674,12 +681,17 @@ def rename_table(self, from_identifier: Union[str, Identifier], to_identifier: U
674681 ValueError: When from table identifier is invalid.
675682 NoSuchTableError: When a table with the name does not exist.
676683 NoSuchNamespaceError: When the destination namespace doesn't exist.
684+ TableAlreadyExistsError: When the destination table already exists.
677685 """
678686 from_database_name , from_table_name = self .identifier_to_database_and_table (from_identifier , NoSuchTableError )
679687 to_database_name , to_table_name = self .identifier_to_database_and_table (to_identifier )
688+
689+ if self .table_exists (to_identifier ):
690+ raise TableAlreadyExistsError (f"Table already exists: { to_table_name } " )
691+
680692 try :
681693 with self ._client as open_client :
682- tbl : HiveTable = self ._get_hive_table (open_client , dbname = from_database_name , tbl_name = from_table_name )
694+ tbl = self ._get_hive_table (open_client , dbname = from_database_name , tbl_name = from_table_name )
683695 tbl .dbName = to_database_name
684696 tbl .tableName = to_table_name
685697 open_client .alter_table_with_environment_context (
@@ -823,7 +835,7 @@ def update_namespace_properties(
823835 if removals :
824836 for key in removals :
825837 if key in parameters :
826- parameters [ key ] = None
838+ parameters . pop ( key )
827839 removed .add (key )
828840 if updates :
829841 for key , value in updates .items ():
0 commit comments