@@ -1074,6 +1074,153 @@ func TestCreateConstraintInMultiOperationMigrations(t *testing.T) {
1074
1074
{"id" : 3 , "item_name" : "carrot" },
1075
1075
}, rows )
1076
1076
1077
+ // The table has been cleaned up
1078
+ TableMustBeCleanedUp (t , db , schema , "products" , "name" )
1079
+ },
1080
+ },
1081
+ {
1082
+ name : "rename table, rename column, create foreign key constraint" ,
1083
+ migrations : []migrations.Migration {
1084
+ {
1085
+ Name : "01_create_tables" ,
1086
+ Operations : migrations.Operations {
1087
+ & migrations.OpCreateTable {
1088
+ Name : "users" ,
1089
+ Columns : []migrations.Column {
1090
+ {
1091
+ Name : "id" ,
1092
+ Type : "int" ,
1093
+ Pk : true ,
1094
+ },
1095
+ {
1096
+ Name : "name" ,
1097
+ Type : "varchar(255)" ,
1098
+ Nullable : true ,
1099
+ },
1100
+ },
1101
+ },
1102
+ & migrations.OpCreateTable {
1103
+ Name : "items" ,
1104
+ Columns : []migrations.Column {
1105
+ {
1106
+ Name : "id" ,
1107
+ Type : "int" ,
1108
+ Pk : true ,
1109
+ },
1110
+ {
1111
+ Name : "name" ,
1112
+ Type : "varchar(255)" ,
1113
+ Nullable : true ,
1114
+ },
1115
+ {
1116
+ Name : "owner" ,
1117
+ Type : "int" ,
1118
+ Nullable : true ,
1119
+ },
1120
+ },
1121
+ },
1122
+ },
1123
+ },
1124
+ {
1125
+ Name : "02_multi_operation" ,
1126
+ Operations : migrations.Operations {
1127
+ & migrations.OpRenameTable {
1128
+ From : "items" ,
1129
+ To : "products" ,
1130
+ },
1131
+ & migrations.OpRenameColumn {
1132
+ Table : "products" ,
1133
+ From : "owner" ,
1134
+ To : "owner_id" ,
1135
+ },
1136
+ & migrations.OpCreateConstraint {
1137
+ Table : "products" ,
1138
+ Type : migrations .OpCreateConstraintTypeForeignKey ,
1139
+ Name : "fk_item_owner" ,
1140
+ Columns : []string {"owner_id" },
1141
+ References : & migrations.TableForeignKeyReference {
1142
+ Table : "users" ,
1143
+ Columns : []string {"id" },
1144
+ },
1145
+ Up : map [string ]string {
1146
+ "owner_id" : "SELECT CASE WHEN EXISTS (SELECT 1 FROM users WHERE users.id = owner_id) THEN owner_id ELSE NULL END" ,
1147
+ },
1148
+ Down : map [string ]string {
1149
+ "owner_id" : "owner_id" ,
1150
+ },
1151
+ },
1152
+ },
1153
+ },
1154
+ },
1155
+ afterStart : func (t * testing.T , db * sql.DB , schema string ) {
1156
+ // Can insert a row into the users table
1157
+ MustInsert (t , db , schema , "02_multi_operation" , "users" , map [string ]string {
1158
+ "id" : "1" ,
1159
+ "name" : "alice" ,
1160
+ })
1161
+
1162
+ // Can insert a row that meets the constraint into the new schema
1163
+ MustInsert (t , db , schema , "02_multi_operation" , "products" , map [string ]string {
1164
+ "id" : "1" ,
1165
+ "name" : "apple" ,
1166
+ "owner_id" : "1" ,
1167
+ })
1168
+
1169
+ // Can't insert a row that violates the constraint into the new schema
1170
+ MustNotInsert (t , db , schema , "02_multi_operation" , "products" , map [string ]string {
1171
+ "id" : "2" ,
1172
+ "name" : "banana" ,
1173
+ "owner_id" : "2" , // no such user
1174
+ }, testutils .FKViolationErrorCode )
1175
+
1176
+ // Can insert a row that violates the constraint into the old schema
1177
+ MustInsert (t , db , schema , "01_create_tables" , "items" , map [string ]string {
1178
+ "id" : "2" ,
1179
+ "name" : "banana" ,
1180
+ "owner" : "2" ,
1181
+ })
1182
+
1183
+ // The new view has the expected rows
1184
+ rows := MustSelect (t , db , schema , "02_multi_operation" , "products" )
1185
+ assert .Equal (t , []map [string ]any {
1186
+ {"id" : 1 , "name" : "apple" , "owner_id" : 1 },
1187
+ {"id" : 2 , "name" : "banana" , "owner_id" : nil },
1188
+ }, rows )
1189
+
1190
+ // The old view has the expected rows
1191
+ rows = MustSelect (t , db , schema , "01_create_tables" , "items" )
1192
+ assert .Equal (t , []map [string ]any {
1193
+ {"id" : 1 , "name" : "apple" , "owner" : 1 },
1194
+ {"id" : 2 , "name" : "banana" , "owner" : 2 },
1195
+ }, rows )
1196
+ },
1197
+ afterRollback : func (t * testing.T , db * sql.DB , schema string ) {
1198
+ // The table has been cleaned up
1199
+ TableMustBeCleanedUp (t , db , schema , "items" , "name" )
1200
+ },
1201
+ afterComplete : func (t * testing.T , db * sql.DB , schema string ) {
1202
+ // Can insert a row that meets the constraint into the new schema
1203
+ MustInsert (t , db , schema , "02_multi_operation" , "products" , map [string ]string {
1204
+ "id" : "3" ,
1205
+ "name" : "carrot" ,
1206
+ "owner_id" : "1" ,
1207
+ })
1208
+
1209
+ // Can't insert a row into the new schema that violates the constraint
1210
+ MustNotInsert (t , db , schema , "02_multi_operation" , "products" , map [string ]string {
1211
+ "id" : "4" ,
1212
+ "name" : "durian" ,
1213
+ "owner_id" : "2" , // no such user
1214
+ }, testutils .FKViolationErrorCode )
1215
+
1216
+ // The new view has the expected rows
1217
+ rows := MustSelect (t , db , schema , "02_multi_operation" , "products" )
1218
+ assert .Equal (t , []map [string ]any {
1219
+ {"id" : 1 , "name" : "apple" , "owner_id" : 1 },
1220
+ {"id" : 2 , "name" : "banana" , "owner_id" : nil },
1221
+ {"id" : 3 , "name" : "carrot" , "owner_id" : 1 },
1222
+ }, rows )
1223
+
1077
1224
// The table has been cleaned up
1078
1225
TableMustBeCleanedUp (t , db , schema , "products" , "name" )
1079
1226
},
0 commit comments