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

Josh McKenzie updated CASSANDRA-13776:
--------------------------------------
    Component/s: Local/SSTable

> Adding a field to an UDT can corrupte the tables using it
> ---------------------------------------------------------
>
>                 Key: CASSANDRA-13776
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-13776
>             Project: Cassandra
>          Issue Type: Bug
>          Components: Local/SSTable
>            Reporter: Benjamin Lerer
>            Assignee: Benjamin Lerer
>            Priority: Urgent
>             Fix For: 3.0.15, 3.11.1, 4.0
>
>
> Adding a field to an UDT which is used as a {{Set}} element or as a {{Map}} 
> element can corrupt the table.
> The problem can be reproduced using the following test case:
> {code}
>     @Test
>     public void testReadAfterAlteringUserTypeNestedWithinSet() throws 
> Throwable
>     {
>         String ut1 = createType("CREATE TYPE %s (a int)");
>         String columnType = KEYSPACE + "." + ut1;
>         try
>         {
>             createTable("CREATE TABLE %s (x int PRIMARY KEY, y set<frozen<" + 
> columnType + ">>)");
>             disableCompaction();
>             execute("INSERT INTO %s (x, y) VALUES(1, ?)", set(userType(1), 
> userType(2)));
>             assertRows(execute("SELECT * FROM %s"), row(1, set(userType(1), 
> userType(2))));
>             flush();
>             assertRows(execute("SELECT * FROM %s WHERE x = 1"),
>                        row(1, set(userType(1), userType(2))));
>             execute("ALTER TYPE " + KEYSPACE + "." + ut1 + " ADD b int");
>             execute("UPDATE %s SET y = y + ? WHERE x = 1",
>                     set(userType(1, 1), userType(1, 2), userType(2, 1)));
>             flush();
>             assertRows(execute("SELECT * FROM %s WHERE x = 1"),
>                            row(1, set(userType(1),
>                                       userType(1, 1),
>                                       userType(1, 2),
>                                       userType(2),
>                                       userType(2, 1))));
>             compact();
>             assertRows(execute("SELECT * FROM %s WHERE x = 1"),
>                        row(1, set(userType(1),
>                                   userType(1, 1),
>                                   userType(1, 2),
>                                   userType(2),
>                                   userType(2, 1))));
>         }
>         finally
>         {
>             enableCompaction();
>         }
>     }
> {code} 
> There are in fact 2 problems:
> # When the {{sets}} from the 2 versions are merged the {{ColumnDefinition}} 
> being picked up can be the older one. In which case when the tuples are 
> sorted it my lead to an {{IndexOutOfBoundsException}}.
> # During compaction, the old column definition can be the one being kept for 
> the SSTable metadata. If it is the case the SSTable will not be readable any 
> more and will be marked as {{corrupted}}.
> If one of the tables using the type has a Materialized View attached to it, 
> the MV updates can also fail with {{IndexOutOfBoundsException}}.
> This problem can be reproduced using the following test:
> {code}
>     @Test
>     public void testAlteringUserTypeNestedWithinSetWithView() throws Throwable
>     {
>         String columnType = typeWithKs(createType("CREATE TYPE %s (a int)"));
>         createTable("CREATE TABLE %s (pk int, c int, v int, s set<frozen<" + 
> columnType + ">>, PRIMARY KEY (pk, c))");
>         execute("CREATE MATERIALIZED VIEW " + keyspace() + ".view1 AS SELECT 
> c, pk, v FROM %s WHERE pk IS NOT NULL AND c IS NOT NULL AND v IS NOT NULL 
> PRIMARY KEY (c, pk)");
>         execute("INSERT INTO %s (pk, c, v, s) VALUES(?, ?, ?, ?)", 1, 1, 1, 
> set(userType(1), userType(2)));
>         flush();
>         execute("ALTER TYPE " + columnType + " ADD b int");
>         execute("UPDATE %s SET s = s + ?, v = ? WHERE pk = ? AND c = ?",
>                 set(userType(1, 1), userType(1, 2), userType(2, 1)), 2, 1, 1);
>         assertRows(execute("SELECT * FROM %s WHERE pk = ? AND c = ?", 1, 1),
>                        row(1, 1, 2, set(userType(1),
>                                         userType(1, 1),
>                                         userType(1, 2),
>                                         userType(2),
>                                         userType(2, 1))));
>     }
> {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