[ 
https://issues.apache.org/jira/browse/CASSANDRA-15926?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

David Capwell updated CASSANDRA-15926:
--------------------------------------
    Description: 
If the table schema had timeuuid and then an alter is done to change the column 
to uuid, then the on-disk serialization header won’t match the table schema; 
this is problematic as there isn’t logic to migrate the column from the old 
type to the new type.

The ALTER TABLE command does not directly allow this type of schema change 
(though possible before 3.0.11, see CASSANDRA-12443), but this is possible if 
the following is done

{code}
INSERT INTO system_schema.columns (keyspace_name, table_name, column_name, 
clustering_order, column_name_bytes, kind, position, type) VALUES (‘ks', 
’table', ‘col', 'none', bytes, 'regular', -1, 'uuid’);
ALTER TABLE ks.table WITH comment = 'something’; — this will trigger the schema 
to migrate across the cluster
{code}

The below is a test to show this

{code}
package org.apache.cassandra.distributed.test;

import java.util.UUID;

import org.junit.Test;

import org.apache.cassandra.distributed.Cluster;
import org.apache.cassandra.distributed.impl.IInvokableInstance;
import org.apache.cassandra.utils.UUIDGen;

public class AlterWithOnDiskMismatch extends DistributedTestBase
{
    @Test
    public void alterTypeMixedSSTablesNoConflict() throws Throwable
    {
        try (Cluster cluster = init(Cluster.create(1)))
        {
            IInvokableInstance node = cluster.get(1);

            cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".mismatch (key 
text primary key, value timeuuid)");

            // write valid timeuuid then flush
            node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
value) VALUES (?, ?)", "k1", UUIDGen.getTimeUUID());
            node.flush(KEYSPACE);

            // alter schema
            Object[] columns = node.executeInternal("SELECT keyspace_name, 
table_name, column_name, clustering_order, column_name_bytes, kind, position, 
type " +
                                 "FROM system_schema.columns WHERE 
keyspace_name=? AND table_name=? AND column_name=?", KEYSPACE, "mismatch", 
"value")[0];

            columns[columns.length - 1] = "uuid";
            node.executeInternal("INSERT INTO system_schema.columns 
(keyspace_name, table_name, column_name, clustering_order, column_name_bytes, 
kind, position, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", columns);
            cluster.schemaChange("ALTER TABLE " + KEYSPACE + ".mismatch WITH 
comment='upgrade'");

            node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
value) VALUES (?, ?)", "k2", UUID.randomUUID());
            node.flush(KEYSPACE);

            node.forceCompact(KEYSPACE, "mismatch");
        }
    }

    @Test
    public void alterTypeMixedSSTablesConflict() throws Throwable
    {
        try (Cluster cluster = init(Cluster.create(1)))
        {
            IInvokableInstance node = cluster.get(1);

            cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".mismatch (key 
text primary key, value timeuuid)");

            // write valid timeuuid then flush
            node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
value) VALUES (?, ?)", "k1", UUIDGen.getTimeUUID());
            node.flush(KEYSPACE);

            // alter schema
            Object[] columns = node.executeInternal("SELECT keyspace_name, 
table_name, column_name, clustering_order, column_name_bytes, kind, position, 
type " +
                                                    "FROM system_schema.columns 
WHERE keyspace_name=? AND table_name=? AND column_name=?", KEYSPACE, 
"mismatch", "value")[0];

            columns[columns.length - 1] = "uuid";
            node.executeInternal("INSERT INTO system_schema.columns 
(keyspace_name, table_name, column_name, clustering_order, column_name_bytes, 
kind, position, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", columns);
            cluster.schemaChange("ALTER TABLE " + KEYSPACE + ".mismatch WITH 
comment='upgrade'");

            node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
value) VALUES (?, ?)", "k1", UUID.randomUUID());
            node.flush(KEYSPACE);

            node.forceCompact(KEYSPACE, "mismatch");
        }
    }
}
{code}

The following is the exception

{code}
java.lang.IllegalArgumentException: Trying to compare 2 different types: 
org.apache.cassandra.db.marshal.TimeUUIDType and 
org.apache.cassandra.db.marshal.UUIDType
        at 
org.apache.cassandra.db.rows.AbstractTypeVersionComparator.compare(AbstractTypeVersionComparator.java:42)
        at 
org.apache.cassandra.db.rows.AbstractTypeVersionComparator.compare(AbstractTypeVersionComparator.java:30)
        at 
org.apache.cassandra.db.rows.Row$Merger$ColumnDataReducer.useColumnDefinition(Row.java:650)
        at 
org.apache.cassandra.db.rows.Row$Merger$ColumnDataReducer.reduce(Row.java:634)
        at 
org.apache.cassandra.db.rows.Row$Merger$ColumnDataReducer.reduce(Row.java:605)
        at 
org.apache.cassandra.utils.MergeIterator$ManyToOne.consume(MergeIterator.java:216)
{code}

  was:
If the table schema had timeuuid and then an alter is done to change the column 
to uuid, then the on-disk serialization header won’t match the table schema; 
this is problematic as there isn’t logic to migrate the column from the old 
type to the new type.

The ALTER TABLE command does not directly allow this type of schema change 
(though possible before 3.0.11, see CASSANDRA-12443), but this is possible if 
the following is done

{code}
INSERT INTO system_schema.columns (keyspace_name, table_name, column_name, 
clustering_order, column_name_bytes, kind, position, type) VALUES (‘ks', 
’table', ‘col', 'none', bytes, 'regular', -1, 'uuid’);
ALTER TABLE ks.table WITH comment = 'something’; — this will trigger the schema 
to migrate across the cluster
{code}

The below is a test to show this

{code}
package org.apache.cassandra.distributed.test;

import java.util.UUID;

import org.junit.Test;

import org.apache.cassandra.distributed.Cluster;
import org.apache.cassandra.distributed.impl.IInvokableInstance;
import org.apache.cassandra.utils.UUIDGen;

public class AlterWithOnDiskMismatch extends DistributedTestBase
{
    @Test
    public void alterTypeMixedSSTablesNoConflict() throws Throwable
    {
        try (Cluster cluster = init(Cluster.create(1)))
        {
            IInvokableInstance node = cluster.get(1);

            cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".mismatch (key 
text primary key, value timeuuid)");

            // write valid timeuuid then flush
            node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
value) VALUES (?, ?)", "k1", UUIDGen.getTimeUUID());
            node.flush(KEYSPACE);

            // alter schema
            Object[] columns = node.executeInternal("SELECT keyspace_name, 
table_name, column_name, clustering_order, column_name_bytes, kind, position, 
type " +
                                 "FROM system_schema.columns WHERE 
keyspace_name=? AND table_name=? AND column_name=?", KEYSPACE, "mismatch", 
"value")[0];

            columns[columns.length - 1] = "uuid";
            node.executeInternal("INSERT INTO system_schema.columns 
(keyspace_name, table_name, column_name, clustering_order, column_name_bytes, 
kind, position, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", columns);
            cluster.schemaChange("ALTER TABLE " + KEYSPACE + ".mismatch WITH 
comment='upgrade'");

            node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
value) VALUES (?, ?)", "k2", UUID.randomUUID());
            node.flush(KEYSPACE);

            node.forceCompact(KEYSPACE, "mismatch");
        }
    }

    @Test
    public void alterTypeMixedSSTablesConflict() throws Throwable
    {
        try (Cluster cluster = init(Cluster.create(1)))
        {
            IInvokableInstance node = cluster.get(1);

            cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".mismatch (key 
text primary key, value timeuuid)");

            // write valid timeuuid then flush
            node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
value) VALUES (?, ?)", "k1", UUIDGen.getTimeUUID());
            node.flush(KEYSPACE);

            // alter schema
            Object[] columns = node.executeInternal("SELECT keyspace_name, 
table_name, column_name, clustering_order, column_name_bytes, kind, position, 
type " +
                                                    "FROM system_schema.columns 
WHERE keyspace_name=? AND table_name=? AND column_name=?", KEYSPACE, 
"mismatch", "value")[0];

            columns[columns.length - 1] = "uuid";
            node.executeInternal("INSERT INTO system_schema.columns 
(keyspace_name, table_name, column_name, clustering_order, column_name_bytes, 
kind, position, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", columns);
            cluster.schemaChange("ALTER TABLE " + KEYSPACE + ".mismatch WITH 
comment='upgrade'");

            node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
value) VALUES (?, ?)", "k1", UUID.randomUUID());
            node.flush(KEYSPACE);

            node.forceCompact(KEYSPACE, "mismatch");
        }
    }
}
{code}


> When schema does not match sstable serialization header can fail when merging 
> rows
> ----------------------------------------------------------------------------------
>
>                 Key: CASSANDRA-15926
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-15926
>             Project: Cassandra
>          Issue Type: Improvement
>          Components: Cluster/Schema, Local/SSTable
>            Reporter: David Capwell
>            Priority: Normal
>
> If the table schema had timeuuid and then an alter is done to change the 
> column to uuid, then the on-disk serialization header won’t match the table 
> schema; this is problematic as there isn’t logic to migrate the column from 
> the old type to the new type.
> The ALTER TABLE command does not directly allow this type of schema change 
> (though possible before 3.0.11, see CASSANDRA-12443), but this is possible if 
> the following is done
> {code}
> INSERT INTO system_schema.columns (keyspace_name, table_name, column_name, 
> clustering_order, column_name_bytes, kind, position, type) VALUES (‘ks', 
> ’table', ‘col', 'none', bytes, 'regular', -1, 'uuid’);
> ALTER TABLE ks.table WITH comment = 'something’; — this will trigger the 
> schema to migrate across the cluster
> {code}
> The below is a test to show this
> {code}
> package org.apache.cassandra.distributed.test;
> import java.util.UUID;
> import org.junit.Test;
> import org.apache.cassandra.distributed.Cluster;
> import org.apache.cassandra.distributed.impl.IInvokableInstance;
> import org.apache.cassandra.utils.UUIDGen;
> public class AlterWithOnDiskMismatch extends DistributedTestBase
> {
>     @Test
>     public void alterTypeMixedSSTablesNoConflict() throws Throwable
>     {
>         try (Cluster cluster = init(Cluster.create(1)))
>         {
>             IInvokableInstance node = cluster.get(1);
>             cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".mismatch (key 
> text primary key, value timeuuid)");
>             // write valid timeuuid then flush
>             node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
> value) VALUES (?, ?)", "k1", UUIDGen.getTimeUUID());
>             node.flush(KEYSPACE);
>             // alter schema
>             Object[] columns = node.executeInternal("SELECT keyspace_name, 
> table_name, column_name, clustering_order, column_name_bytes, kind, position, 
> type " +
>                                  "FROM system_schema.columns WHERE 
> keyspace_name=? AND table_name=? AND column_name=?", KEYSPACE, "mismatch", 
> "value")[0];
>             columns[columns.length - 1] = "uuid";
>             node.executeInternal("INSERT INTO system_schema.columns 
> (keyspace_name, table_name, column_name, clustering_order, column_name_bytes, 
> kind, position, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", columns);
>             cluster.schemaChange("ALTER TABLE " + KEYSPACE + ".mismatch WITH 
> comment='upgrade'");
>             node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
> value) VALUES (?, ?)", "k2", UUID.randomUUID());
>             node.flush(KEYSPACE);
>             node.forceCompact(KEYSPACE, "mismatch");
>         }
>     }
>     @Test
>     public void alterTypeMixedSSTablesConflict() throws Throwable
>     {
>         try (Cluster cluster = init(Cluster.create(1)))
>         {
>             IInvokableInstance node = cluster.get(1);
>             cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".mismatch (key 
> text primary key, value timeuuid)");
>             // write valid timeuuid then flush
>             node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
> value) VALUES (?, ?)", "k1", UUIDGen.getTimeUUID());
>             node.flush(KEYSPACE);
>             // alter schema
>             Object[] columns = node.executeInternal("SELECT keyspace_name, 
> table_name, column_name, clustering_order, column_name_bytes, kind, position, 
> type " +
>                                                     "FROM 
> system_schema.columns WHERE keyspace_name=? AND table_name=? AND 
> column_name=?", KEYSPACE, "mismatch", "value")[0];
>             columns[columns.length - 1] = "uuid";
>             node.executeInternal("INSERT INTO system_schema.columns 
> (keyspace_name, table_name, column_name, clustering_order, column_name_bytes, 
> kind, position, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", columns);
>             cluster.schemaChange("ALTER TABLE " + KEYSPACE + ".mismatch WITH 
> comment='upgrade'");
>             node.executeInternal("INSERT INTO " + KEYSPACE + ".mismatch (key, 
> value) VALUES (?, ?)", "k1", UUID.randomUUID());
>             node.flush(KEYSPACE);
>             node.forceCompact(KEYSPACE, "mismatch");
>         }
>     }
> }
> {code}
> The following is the exception
> {code}
> java.lang.IllegalArgumentException: Trying to compare 2 different types: 
> org.apache.cassandra.db.marshal.TimeUUIDType and 
> org.apache.cassandra.db.marshal.UUIDType
>       at 
> org.apache.cassandra.db.rows.AbstractTypeVersionComparator.compare(AbstractTypeVersionComparator.java:42)
>       at 
> org.apache.cassandra.db.rows.AbstractTypeVersionComparator.compare(AbstractTypeVersionComparator.java:30)
>       at 
> org.apache.cassandra.db.rows.Row$Merger$ColumnDataReducer.useColumnDefinition(Row.java:650)
>       at 
> org.apache.cassandra.db.rows.Row$Merger$ColumnDataReducer.reduce(Row.java:634)
>       at 
> org.apache.cassandra.db.rows.Row$Merger$ColumnDataReducer.reduce(Row.java:605)
>       at 
> org.apache.cassandra.utils.MergeIterator$ManyToOne.consume(MergeIterator.java:216)
> {code}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to