@@ -770,6 +770,114 @@ func (suite *ApplierTestSuite) TestCreateGhostTable() {
770770 suite .Require ().Equal ("CREATE TABLE `_testing_gho` (\n `id` int DEFAULT NULL,\n `item_id` int DEFAULT NULL\n ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci" , createDDL )
771771}
772772
773+ // TestCreateTargetTable_HappyPath exercises #8207 AC #1:
774+ // "A move table run targeting a clean target schema creates the migrated table
775+ // with a SHOW CREATE TABLE output equivalent to the source's."
776+ //
777+ // It calls CreateTargetTable (not just IsMoveTablesMode()), asserts the table
778+ // exists on the target database, verifies schema equivalence via SHOW CREATE TABLE,
779+ // and confirms no table was accidentally created on the source.
780+ func (suite * ApplierTestSuite ) TestCreateTargetTable_HappyPath () {
781+ ctx := context .Background ()
782+
783+ _ , err := suite .db .ExecContext (ctx , fmt .Sprintf ("CREATE TABLE %s (id INT PRIMARY KEY, name VARCHAR(64), updated_at DATETIME);" , getTestTableName ()))
784+ suite .Require ().NoError (err )
785+
786+ connectionConfig , err := getTestConnectionConfig (ctx , suite .mysqlContainer )
787+ suite .Require ().NoError (err )
788+
789+ migrationContext := newTestMigrationContext ()
790+ migrationContext .MoveTables .TableNames = []string {testMysqlTableName }
791+ migrationContext .MoveTables .TargetDatabase = testMysqlDatabaseOther
792+ migrationContext .ApplierConnectionConfig = connectionConfig
793+ migrationContext .MoveTables .ConnectionConfig = connectionConfig
794+ migrationContext .SetConnectionConfig ("innodb" )
795+ migrationContext .OriginalTableColumns = sql .NewColumnList ([]string {"id" , "name" , "updated_at" })
796+
797+ applier := NewApplier (migrationContext )
798+ defer applier .Teardown ()
799+
800+ err = applier .InitDBConnections ()
801+ suite .Require ().NoError (err )
802+
803+ var dummy , sourceCreateDDL string
804+ err = suite .db .QueryRow (fmt .Sprintf ("SHOW CREATE TABLE %s" , getTestTableName ())).Scan (& dummy , & sourceCreateDDL )
805+ suite .Require ().NoError (err )
806+
807+ var count int
808+ err = suite .otherDB .QueryRow (
809+ "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=? AND table_name=?" ,
810+ testMysqlDatabaseOther , testMysqlTableName ,
811+ ).Scan (& count )
812+ suite .Require ().NoError (err )
813+ suite .Require ().Equal (0 , count , "precondition: target table must not exist before CreateTargetTable" )
814+
815+ err = applier .CreateTargetTable (sourceCreateDDL )
816+ suite .Require ().NoError (err )
817+
818+ var targetTableName , targetCreateDDL string
819+ err = suite .otherDB .QueryRow (fmt .Sprintf ("SHOW CREATE TABLE `%s`.`%s`" , testMysqlDatabaseOther , testMysqlTableName )).Scan (& targetTableName , & targetCreateDDL )
820+ suite .Require ().NoError (err )
821+ suite .Require ().Equal (testMysqlTableName , targetTableName )
822+ suite .Require ().Equal (sourceCreateDDL , targetCreateDDL , "target table schema must be equivalent to source" )
823+
824+ err = suite .otherDB .QueryRow (
825+ "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=? AND table_name=?" ,
826+ testMysqlDatabaseOther , testMysqlTableName ,
827+ ).Scan (& count )
828+ suite .Require ().NoError (err )
829+ suite .Require ().Equal (1 , count , "target table must exist exactly once on the target database" )
830+ }
831+
832+ // TestCreateTargetTable_AbortsIfExists exercises #8207 AC #2:
833+ // "A move table run aborts before any data is copied if the target table already exists."
834+ //
835+ // It pre-creates the target table, then calls CreateTargetTable and asserts it
836+ // returns a descriptive error (not just MySQL's raw ERROR 1050).
837+ func (suite * ApplierTestSuite ) TestCreateTargetTable_AbortsIfExists () {
838+ ctx := context .Background ()
839+
840+ _ , err := suite .db .ExecContext (ctx , fmt .Sprintf ("CREATE TABLE %s (id INT PRIMARY KEY);" , getTestTableName ()))
841+ suite .Require ().NoError (err )
842+
843+ _ , err = suite .otherDB .ExecContext (ctx , fmt .Sprintf ("CREATE TABLE `%s`.`%s` (id INT PRIMARY KEY);" , testMysqlDatabaseOther , testMysqlTableName ))
844+ suite .Require ().NoError (err )
845+
846+ var count int
847+ err = suite .otherDB .QueryRow (
848+ "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=? AND table_name=?" ,
849+ testMysqlDatabaseOther , testMysqlTableName ,
850+ ).Scan (& count )
851+ suite .Require ().NoError (err )
852+ suite .Require ().Equal (1 , count , "precondition: target table must exist before CreateTargetTable" )
853+
854+ connectionConfig , err := getTestConnectionConfig (ctx , suite .mysqlContainer )
855+ suite .Require ().NoError (err )
856+
857+ migrationContext := newTestMigrationContext ()
858+ migrationContext .MoveTables .TableNames = []string {testMysqlTableName }
859+ migrationContext .MoveTables .TargetDatabase = testMysqlDatabaseOther
860+ migrationContext .ApplierConnectionConfig = connectionConfig
861+ migrationContext .MoveTables .ConnectionConfig = connectionConfig
862+ migrationContext .SetConnectionConfig ("innodb" )
863+ migrationContext .OriginalTableColumns = sql .NewColumnList ([]string {"id" })
864+
865+ applier := NewApplier (migrationContext )
866+ defer applier .Teardown ()
867+
868+ err = applier .InitDBConnections ()
869+ suite .Require ().NoError (err )
870+
871+ var dummy , sourceCreateDDL string
872+ err = suite .db .QueryRow (fmt .Sprintf ("SHOW CREATE TABLE %s" , getTestTableName ())).Scan (& dummy , & sourceCreateDDL )
873+ suite .Require ().NoError (err )
874+
875+ err = applier .CreateTargetTable (sourceCreateDDL )
876+ suite .Require ().Error (err , "CreateTargetTable must return an error when target table already exists" )
877+ suite .Require ().Contains (err .Error (), "already exists" , "error message must mention 'already exists'" )
878+ suite .Require ().Contains (err .Error (), testMysqlTableName , "error message must name the table" )
879+ }
880+
773881func (suite * ApplierTestSuite ) TestPanicOnWarningsInApplyIterationInsertQuerySucceedsWithUniqueKeyWarningInsertedByDMLEvent () {
774882 ctx := context .Background ()
775883
0 commit comments