@@ -736,6 +736,72 @@ def __convert_alter_table_change_column(self, db_name, table_name, tokens):
736736 query = f'ALTER TABLE `{ db_name } `.`{ table_name } ` RENAME COLUMN { column_name } TO { new_column_name } '
737737 self .db_replicator .clickhouse_api .execute_command (query )
738738
739+ def _handle_create_table_like (self , create_statement , source_table_name , target_table_name , is_query_api = True ):
740+ """
741+ Helper method to handle CREATE TABLE LIKE statements.
742+
743+ Args:
744+ create_statement: The original CREATE TABLE LIKE statement
745+ source_table_name: Name of the source table being copied
746+ target_table_name: Name of the new table being created
747+ is_query_api: If True, returns both MySQL and CH structures; if False, returns only MySQL structure
748+
749+ Returns:
750+ Either (mysql_structure, ch_structure) if is_query_api=True, or just mysql_structure otherwise
751+ """
752+ # Try to get the actual structure from the existing table structures first
753+ if (hasattr (self , 'db_replicator' ) and
754+ self .db_replicator is not None and
755+ hasattr (self .db_replicator , 'state' ) and
756+ hasattr (self .db_replicator .state , 'tables_structure' )):
757+
758+ # Check if the source table structure is already in our state
759+ if source_table_name in self .db_replicator .state .tables_structure :
760+ # Get the existing structure
761+ source_mysql_structure , source_ch_structure = self .db_replicator .state .tables_structure [source_table_name ]
762+
763+ # Create a new structure with the target table name
764+ new_mysql_structure = copy .deepcopy (source_mysql_structure )
765+ new_mysql_structure .table_name = target_table_name
766+
767+ # Convert to ClickHouse structure
768+ new_ch_structure = copy .deepcopy (source_ch_structure )
769+ new_ch_structure .table_name = target_table_name
770+
771+ return (new_mysql_structure , new_ch_structure ) if is_query_api else new_mysql_structure
772+
773+ # If we couldn't get it from state, try with MySQL API
774+ if (hasattr (self , 'db_replicator' ) and
775+ self .db_replicator is not None and
776+ hasattr (self .db_replicator , 'mysql_api' ) and
777+ self .db_replicator .mysql_api is not None ):
778+
779+ try :
780+ # Get the CREATE statement for the source table
781+ source_create_statement = self .db_replicator .mysql_api .get_table_create_statement (source_table_name )
782+
783+ # Parse the source table structure
784+ source_structure = self .parse_mysql_table_structure (source_create_statement )
785+
786+ # Copy the structure but keep the new table name
787+ mysql_structure = copy .deepcopy (source_structure )
788+ mysql_structure .table_name = target_table_name
789+
790+ if is_query_api :
791+ # Convert to ClickHouse structure
792+ ch_structure = self .convert_table_structure (mysql_structure )
793+ return mysql_structure , ch_structure
794+ else :
795+ return mysql_structure
796+
797+ except Exception as e :
798+ error_msg = f"Could not get source table structure for LIKE statement: { str (e )} "
799+ print (f"Error: { error_msg } " )
800+ raise Exception (error_msg , create_statement )
801+
802+ # If we got here, we couldn't determine the structure
803+ raise Exception (f"Could not determine structure for source table '{ source_table_name } ' in LIKE statement" , create_statement )
804+
739805 def parse_create_table_query (self , mysql_query ) -> tuple [TableStructure , TableStructure ]:
740806 # Special handling for CREATE TABLE LIKE statements
741807 if 'LIKE' in mysql_query .upper ():
@@ -748,55 +814,8 @@ def parse_create_table_query(self, mysql_query) -> tuple[TableStructure, TableSt
748814 new_table_name = match .group (1 ).strip ('`"' )
749815 source_table_name = match .group (2 ).strip ('`"' )
750816
751- # Try to get the actual structure from the existing table structures first
752- if (hasattr (self , 'db_replicator' ) and
753- self .db_replicator is not None and
754- hasattr (self .db_replicator , 'state' ) and
755- hasattr (self .db_replicator .state , 'tables_structure' )):
756-
757- # Check if the source table structure is already in our state
758- if source_table_name in self .db_replicator .state .tables_structure :
759- # Get the existing structure
760- source_mysql_structure , source_ch_structure = self .db_replicator .state .tables_structure [source_table_name ]
761-
762- # Create a new structure with the target table name
763- new_mysql_structure = copy .deepcopy (source_mysql_structure )
764- new_mysql_structure .table_name = new_table_name
765-
766- # Convert to ClickHouse structure
767- new_ch_structure = copy .deepcopy (source_ch_structure )
768- new_ch_structure .table_name = new_table_name
769-
770- return new_mysql_structure , new_ch_structure
771-
772- # If we couldn't get it from state, try with MySQL API
773- if (hasattr (self , 'db_replicator' ) and
774- self .db_replicator is not None and
775- hasattr (self .db_replicator , 'mysql_api' ) and
776- self .db_replicator .mysql_api is not None ):
777-
778- try :
779- # Get the CREATE statement for the source table
780- source_create_statement = self .db_replicator .mysql_api .get_table_create_statement (source_table_name )
781-
782- # Parse the source table structure
783- source_structure = self .parse_mysql_table_structure (source_create_statement )
784-
785- # Create a new structure with the target table name
786- mysql_table_structure = copy .deepcopy (source_structure )
787- mysql_table_structure .table_name = new_table_name
788-
789- # Convert to ClickHouse structure
790- ch_table_structure = self .convert_table_structure (mysql_table_structure )
791-
792- return mysql_table_structure , ch_table_structure
793- except Exception as e :
794- error_msg = f"Could not get source table structure for LIKE statement: { str (e )} "
795- print (f"Error: { error_msg } " )
796- raise Exception (error_msg , mysql_query )
797-
798- # If we got here, we couldn't determine the structure
799- raise Exception (f"Could not determine structure for source table '{ source_table_name } ' in LIKE statement" , mysql_query )
817+ # Use the common helper method to handle the LIKE statement
818+ return self ._handle_create_table_like (mysql_query , source_table_name , new_table_name , True )
800819
801820 # Regular parsing for non-LIKE statements
802821 mysql_table_structure = self .parse_mysql_table_structure (mysql_query )
@@ -851,29 +870,8 @@ def parse_mysql_table_structure(self, create_statement, required_table_name=None
851870 source_table_name = strip_sql_name (tokens [4 ].get_real_name ())
852871 target_table_name = strip_sql_name (tokens [2 ].get_real_name ())
853872
854- # Try to get the actual structure - we need a valid MySQL API
855- if not (hasattr (self , 'db_replicator' ) and
856- self .db_replicator is not None and
857- hasattr (self .db_replicator , 'mysql_api' ) and
858- self .db_replicator .mysql_api is not None ):
859- raise Exception (f"Cannot parse LIKE statement - no MySQL API available to get source table structure" , create_statement )
860-
861- try :
862- # Try to get the CREATE statement from the current database
863- mysql_api = self .db_replicator .mysql_api
864- source_create_statement = mysql_api .get_table_create_statement (source_table_name )
865-
866- # Parse the source table structure
867- source_structure = self .parse_mysql_table_structure (source_create_statement )
868-
869- # Copy the structure but keep the new table name
870- structure = copy .deepcopy (source_structure )
871- structure .table_name = target_table_name
872- return structure
873- except Exception as e :
874- error_msg = f"Could not get source table structure: { str (e )} "
875- print (f"Error: { error_msg } " )
876- raise Exception (error_msg , create_statement )
873+ # Use the common helper method to handle the LIKE statement
874+ return self ._handle_create_table_like (create_statement , source_table_name , target_table_name , False )
877875
878876 if not isinstance (tokens [3 ], sqlparse .sql .Parenthesis ):
879877 raise Exception ('wrong create statement' , create_statement )
0 commit comments