[ https://issues.apache.org/jira/browse/CASSANDRA-13776?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Benjamin Lerer updated CASSANDRA-13776: --------------------------------------- Resolution: Fixed Fix Version/s: 4.0 3.11.1 3.0.15 Status: Resolved (was: Ready to Commit) Committed into 3.0 at cf0b6d107bade419dada49a5da40d2579c80ade8 and merged into 3.11 and trunk > 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 > Reporter: Benjamin Lerer > Assignee: Benjamin Lerer > Priority: Critical > 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 (v6.4.14#64029) --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org