Skip to content

Commit 17c4380

Browse files
committed
HCD-241: Preserve user-defined types during keyspace schema migration
When updating keyspace schemas, UDTs from the previous schema are now preserved if they don't exist in the new schema. This prevents issues where inherited tables depend on types that would otherwise be lost during schema transformations.
1 parent 7708434 commit 17c4380

2 files changed

Lines changed: 52 additions & 0 deletions

File tree

src/java/org/apache/cassandra/schema/SchemaTransformations.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020

2121
import java.util.Optional;
2222

23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
25+
2326
import org.apache.cassandra.db.marshal.UserType;
2427
import org.apache.cassandra.exceptions.AlreadyExistsException;
2528
import org.apache.cassandra.exceptions.ConfigurationException;
@@ -31,6 +34,8 @@
3134
*/
3235
public class SchemaTransformations
3336
{
37+
private static final Logger logger = LoggerFactory.getLogger(SchemaTransformations.class);
38+
3439
/**
3540
* Creates a schema transformation that adds the provided keyspace.
3641
*
@@ -227,6 +232,22 @@ public Keyspaces apply(Keyspaces schema)
227232
updatedKeyspace = updatedKeyspace.withSwapped(updatedKeyspace.tables.with(updatedBuilder.build()));
228233
}
229234
}
235+
236+
if (curKeyspace.types != null)
237+
{
238+
for (UserType currType : curKeyspace.types)
239+
{
240+
UserType desiredType = updatedKeyspace.types.getNullable(currType.name);
241+
// if the type exist we keep the existing definition, otherwise we inherit the type
242+
// the motivation behind it is that there might be tables (inherited above) that depend on it
243+
if (desiredType == null)
244+
{
245+
logger.debug("Preserving type {} for keyspace {}", currType.getNameAsString(), curKeyspace.name);
246+
updatedKeyspace = updatedKeyspace.withSwapped(updatedKeyspace.types.with(currType));
247+
}
248+
}
249+
}
250+
230251
}
231252
return schema.withAddedOrUpdated(updatedKeyspace);
232253
}

test/unit/org/apache/cassandra/schema/MigrationManagerTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import java.nio.ByteBuffer;
2222
import java.util.HashMap;
23+
import java.util.List;
2324
import java.util.Map;
2425
import java.util.function.Supplier;
2526

@@ -40,7 +41,9 @@
4041
import org.apache.cassandra.db.lifecycle.LifecycleTransaction;
4142
import org.apache.cassandra.db.marshal.ByteType;
4243
import org.apache.cassandra.db.marshal.BytesType;
44+
import org.apache.cassandra.db.marshal.Int32Type;
4345
import org.apache.cassandra.db.marshal.UTF8Type;
46+
import org.apache.cassandra.db.marshal.UserType;
4447
import org.apache.cassandra.exceptions.ConfigurationException;
4548
import org.apache.cassandra.io.sstable.Component;
4649
import org.apache.cassandra.io.sstable.Descriptor;
@@ -51,7 +54,9 @@
5154
import static org.apache.cassandra.Util.throwAssert;
5255
import static org.apache.cassandra.cql3.CQLTester.assertRows;
5356
import static org.apache.cassandra.cql3.CQLTester.row;
57+
import static org.apache.cassandra.cql3.FieldIdentifier.forUnquoted;
5458
import static org.apache.cassandra.db.ColumnFamilyStore.FlushReason.UNIT_TESTS;
59+
import static org.apache.cassandra.utils.ByteBufferUtil.bytes;
5560
import static org.junit.Assert.assertEquals;
5661
import static org.junit.Assert.assertFalse;
5762
import static org.junit.Assert.assertNotNull;
@@ -617,6 +622,32 @@ public void testEvolveSystemKeyspaceChanged()
617622
assertEquals(keyspace1, diff.altered.get(0).after);
618623
}
619624

625+
@Test
626+
public void testInheritTypesFromPreviousKeyspace()
627+
{
628+
// given
629+
TableMetadata table0 = addTestTable("ks2", "t", "");
630+
UserType udt = new UserType("ks2",
631+
bytes("PreviousType"),
632+
List.of(forUnquoted("a"), forUnquoted("b")),
633+
List.of(Int32Type.instance, Int32Type.instance),
634+
true);
635+
KeyspaceMetadata previousKeyspace = KeyspaceMetadata.create("ks2", KeyspaceParams.simple(1), Tables.of(table0), Views.none(), Types.of(udt), UserFunctions.none());
636+
KeyspaceMetadata currentKeyspace = KeyspaceMetadata.create("ks2", KeyspaceParams.simple(1), Tables.of(table0));
637+
638+
// when
639+
SchemaTransformation transformation = SchemaTransformations.updateSystemKeyspace(currentKeyspace, 1);
640+
Keyspaces after = transformation.apply(Keyspaces.of(previousKeyspace));
641+
642+
// then
643+
KeyspaceMetadata keyspaceAfterTransformation = after.getNullable("ks2");
644+
assertNotNull(keyspaceAfterTransformation);
645+
assertEquals(currentKeyspace.types.stream().count() + 1, keyspaceAfterTransformation.types.stream().count());
646+
UserType inheritedUdt = keyspaceAfterTransformation.types.getNullable(udt.name);
647+
assertNotNull(inheritedUdt);
648+
assertEquals(udt, inheritedUdt);
649+
}
650+
620651
private TableMetadata addTestTable(String ks, String cf, String comment)
621652
{
622653
return

0 commit comments

Comments
 (0)