11from __future__ import annotations
22
33import logging
4+ import re
45import time
56from dataclasses import dataclass , field
6- from typing import TYPE_CHECKING , ClassVar , Optional , Tuple , Union
7+ from typing import TYPE_CHECKING , ClassVar , List , Optional , Tuple , Union
78
89from firebolt .db import Connection , connect
910from firebolt .model .V2 import FireboltBaseModel
@@ -26,15 +27,17 @@ class Engine(FireboltBaseModel):
2627
2728 START_SQL : ClassVar [str ] = 'START ENGINE "{}"'
2829 STOP_SQL : ClassVar [str ] = 'STOP ENGINE "{}"'
29- ALTER_PREFIX_SQL : ClassVar [str ] = 'ALTER ENGINE "{}" SET '
30+ ALTER_PREFIX_SQL : ClassVar [str ] = 'ALTER ENGINE "{}" '
3031 ALTER_PARAMETER_NAMES : ClassVar [Tuple ] = (
3132 "NODES" ,
3233 "TYPE" ,
3334 "AUTO_STOP" ,
34- "RENAME_TO" ,
3535 )
3636 DROP_SQL : ClassVar [str ] = 'DROP ENGINE "{}"'
3737
38+ # Engine names can only contain alphanumeric characters and underscores
39+ _engine_name_re = re .compile (r"^[a-zA-Z0-9_]+$" )
40+
3841 _service : EngineService = field (repr = False , compare = False )
3942
4043 name : str = field (metadata = {"db_name" : "engine_name" })
@@ -69,11 +72,11 @@ def database(self) -> Optional[Database]:
6972 pass
7073 return None
7174
72- def refresh (self ) -> None :
75+ def refresh (self , name : Optional [ str ] = None ) -> None :
7376 """Update attributes of the instance from Firebolt."""
7477 field_name_overrides = self ._get_field_overrides ()
75- for name , value in self ._service ._get_dict (self .name ).items ():
76- setattr (self , field_name_overrides .get (name , name ), value )
78+ for field_name , value in self ._service ._get_dict (name or self .name ).items ():
79+ setattr (self , field_name_overrides .get (field_name , field_name ), value )
7780
7881 self .__post_init__ ()
7982
@@ -194,6 +197,9 @@ def update(
194197 # Nothing to be updated
195198 return self
196199
200+ if name is not None and any (x is not None for x in (scale , spec , auto_stop )):
201+ raise ValueError ("Cannot update name and other parameters at the same time" )
202+
197203 self .refresh ()
198204 self ._wait_for_start_stop ()
199205 if self .current_status in (EngineStatus .DROPPING , EngineStatus .REPAIRING ):
@@ -203,21 +209,31 @@ def update(
203209 )
204210
205211 sql = self .ALTER_PREFIX_SQL .format (self .name )
206- parameters = []
207- for param , value in zip (
208- self .ALTER_PARAMETER_NAMES ,
209- (scale , spec , auto_stop , name ),
210- ):
211- if value is not None :
212- sql_part , new_params = self ._service ._format_engine_attribute_sql (
213- param , value
212+ parameters : List [Union [str , int ]] = []
213+ if name is not None :
214+ if not self ._engine_name_re .match (name ):
215+ raise ValueError (
216+ f"Engine name { name } is invalid, "
217+ "it must only contain alphanumeric characters and underscores."
214218 )
215- sql += sql_part
216- parameters .extend (new_params )
219+ sql += f" RENAME TO { name } "
220+ else :
221+ sql += " SET "
222+ parameters = []
223+ for param , value in zip (
224+ self .ALTER_PARAMETER_NAMES ,
225+ (scale , spec , auto_stop ),
226+ ):
227+ if value is not None :
228+ sql_part , new_params = self ._service ._format_engine_attribute_sql (
229+ param , value
230+ )
231+ sql += sql_part
232+ parameters .extend (new_params )
217233
218234 with self ._service ._connection .cursor () as c :
219235 c .execute (sql , parameters )
220- self .refresh ()
236+ self .refresh (name )
221237 return self
222238
223239 def delete (self ) -> None :
0 commit comments