This is an automated email from the ASF dual-hosted git repository.
ifesdjeen pushed a commit to branch cassandra-3.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/cassandra-3.0 by this push:
new 0c54cc9 Queries on hidden columns act as if these columns do not exist
0c54cc9 is described below
commit 0c54cc98595b4879c9a634737674fd36fd1c46d0
Author: Aleksandr Sorokoumov <[email protected]>
AuthorDate: Fri Oct 13 17:32:50 2017 +0200
Queries on hidden columns act as if these columns do not exist
Patch by Aleksandr Sorokoumov, reviewed by Alex Petrov for CASSANDRA-13917.
---
.../org/apache/cassandra/config/CFMetaData.java | 30 ++++++++-
.../cql3/validation/operations/AlterTest.java | 27 ++++++++
.../cql3/validation/operations/CreateTest.java | 13 ++++
.../cql3/validation/operations/DeleteTest.java | 64 ++++++++++++++++++
.../cql3/validation/operations/InsertTest.java | 68 +++++++++++++++++++
.../cql3/validation/operations/SelectTest.java | 76 ++++++++++++++++++++++
.../cql3/validation/operations/UpdateTest.java | 57 ++++++++++++++++
.../cassandra/db/PartitionRangeReadTest.java | 6 --
8 files changed, 334 insertions(+), 7 deletions(-)
diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java
b/src/java/org/apache/cassandra/config/CFMetaData.java
index ecb0fbf..5888f42 100644
--- a/src/java/org/apache/cassandra/config/CFMetaData.java
+++ b/src/java/org/apache/cassandra/config/CFMetaData.java
@@ -120,6 +120,8 @@ public final class CFMetaData
// for those tables in practice).
private volatile ColumnDefinition compactValueColumn;
+ private volatile Set<ColumnDefinition> hiddenColumns;
+
/**
* These two columns are "virtual" (e.g. not persisted together with
schema).
*
@@ -383,6 +385,24 @@ public final class CFMetaData
this.comparator = new
ClusteringComparator(clusteringColumns.get(0).type);
else
this.comparator = new
ClusteringComparator(extractTypes(clusteringColumns));
+
+ Set<ColumnDefinition> hiddenColumns;
+ if (isCompactTable() && isDense &&
CompactTables.hasEmptyCompactValue(this))
+ {
+ hiddenColumns = Collections.singleton(compactValueColumn);
+ }
+ else if (isCompactTable() && !isDense && !isSuper)
+ {
+ hiddenColumns =
Sets.newHashSetWithExpectedSize(clusteringColumns.size() + 1);
+ hiddenColumns.add(compactValueColumn);
+ hiddenColumns.addAll(clusteringColumns);
+
+ }
+ else
+ {
+ hiddenColumns = Collections.emptySet();
+ }
+ this.hiddenColumns = hiddenColumns;
}
public Indexes getIndexes()
@@ -762,6 +782,11 @@ public final class CFMetaData
return compactValueColumn;
}
+ private boolean isHiddenColumn(ColumnDefinition def)
+ {
+ return hiddenColumns.contains(def);
+ }
+
public ClusteringComparator getKeyValidatorAsClusteringComparator()
{
boolean isCompound = keyValidator instanceof CompositeType;
@@ -963,7 +988,10 @@ public final class CFMetaData
// for instance) so...
public ColumnDefinition getColumnDefinition(ByteBuffer name)
{
- return columnMetadata.get(name);
+ ColumnDefinition cd = columnMetadata.get(name);
+ if (cd == null || isHiddenColumn(cd))
+ return null;
+ return cd;
}
public static boolean isNameValid(String name)
diff --git
a/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
b/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
index 1262258..da27dac 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
@@ -476,4 +476,31 @@ public class AlterTest extends CQLTester
assertEmpty(execute("SELECT * FROM %s"));
}
+
+ /**
+ * Test for CASSANDRA-13917
+ */
+ @Test
+ public void testAlterWithCompactStaticFormat() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int) WITH
COMPACT STORAGE");
+
+ assertInvalidMessage("Cannot rename unknown column column1 in
keyspace",
+ "ALTER TABLE %s RENAME column1 TO column2");
+ }
+
+ /**
+ * Test for CASSANDRA-13917
+ */
+ @Test
+ public void testAlterWithCompactNonStaticFormat() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, PRIMARY KEY (a, b)) WITH
COMPACT STORAGE");
+ assertInvalidMessage("Cannot rename unknown column column1 in
keyspace",
+ "ALTER TABLE %s RENAME column1 TO column2");
+
+ createTable("CREATE TABLE %s (a int, b int, v int, PRIMARY KEY (a, b))
WITH COMPACT STORAGE");
+ assertInvalidMessage("Cannot rename unknown column column1 in
keyspace",
+ "ALTER TABLE %s RENAME column1 TO column2");
+ }
}
diff --git
a/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
b/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
index 33a41d8..1f436b9 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
@@ -494,6 +494,19 @@ public class CreateTest extends CQLTester
assertRows(execute("SELECT * FROM %s WHERE b = ?", 4), row(2, 4));
}
+ /**
+ * Test for CASSANDRA-13917
+ */
+ @Test
+ public void testCreateIndextWithCompactStaticFormat() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int) WITH
COMPACT STORAGE");
+ assertInvalidMessage("No column definition found for column column1",
+ "CREATE INDEX column1_index on %s (column1)");
+ assertInvalidMessage("No column definition found for column value",
+ "CREATE INDEX value_index on %s (value)");
+ }
+
@Test
// tests CASSANDRA-9565
public void testDoubleWith() throws Throwable
diff --git
a/test/unit/org/apache/cassandra/cql3/validation/operations/DeleteTest.java
b/test/unit/org/apache/cassandra/cql3/validation/operations/DeleteTest.java
index 4c9f4d6..9d495b3 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/DeleteTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/DeleteTest.java
@@ -1452,6 +1452,70 @@ public class DeleteTest extends CQLTester
execute("DELETE FROM %s WHERE k = ? AND a >= ? AND a < ?", "a", 0, 2);
}
+ /**
+ * Test for CASSANDRA-13917
+ */
+ @Test
+ public void testWithCompactStaticFormat() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int) WITH
COMPACT STORAGE");
+ testWithCompactFormat();
+
+ // if column1 is present, hidden column is called column2
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int, column1
int) WITH COMPACT STORAGE");
+ assertInvalidMessage("Undefined name column2 in where clause ('column2
= 1')",
+ "DELETE FROM %s WHERE a = 1 AND column2= 1");
+ assertInvalidMessage("Undefined name column2 in where clause ('column2
= 1')",
+ "DELETE FROM %s WHERE a = 1 AND column2 = 1 AND
value1 = 1");
+ assertInvalidMessage("Unknown identifier column2",
+ "DELETE column2 FROM %s WHERE a = 1");
+
+ // if value is present, hidden column is called value1
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int, value
int) WITH COMPACT STORAGE");
+ assertInvalidMessage("Undefined name value1 in where clause ('value1 =
1')",
+ "DELETE FROM %s WHERE a = 1 AND value1 = 1");
+ assertInvalidMessage("Undefined name value1 in where clause ('value1 =
1')",
+ "DELETE FROM %s WHERE a = 1 AND value1 = 1 AND
column1 = 1");
+ assertInvalidMessage("Unknown identifier value1",
+ "DELETE value1 FROM %s WHERE a = 1");
+ }
+
+ /**
+ * Test for CASSANDRA-13917
+ */
+ @Test
+ public void testWithCompactNonStaticFormat() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, PRIMARY KEY (a, b)) WITH
COMPACT STORAGE");
+ execute("INSERT INTO %s (a, b) VALUES (1, 1)");
+ execute("INSERT INTO %s (a, b) VALUES (2, 1)");
+ assertRows(execute("SELECT a, b FROM %s"),
+ row(1, 1),
+ row(2, 1));
+ testWithCompactFormat();
+
+ createTable("CREATE TABLE %s (a int, b int, v int, PRIMARY KEY (a, b))
WITH COMPACT STORAGE");
+ execute("INSERT INTO %s (a, b, v) VALUES (1, 1, 3)");
+ execute("INSERT INTO %s (a, b, v) VALUES (2, 1, 4)");
+ assertRows(execute("SELECT a, b, v FROM %s"),
+ row(1, 1, 3),
+ row(2, 1, 4));
+ testWithCompactFormat();
+ }
+
+ private void testWithCompactFormat() throws Throwable
+ {
+ assertInvalidMessage("Undefined name value in where clause ('value =
1')",
+ "DELETE FROM %s WHERE a = 1 AND value = 1");
+ assertInvalidMessage("Undefined name column1 in where clause ('column1
= 1')",
+ "DELETE FROM %s WHERE a = 1 AND column1= 1");
+ assertInvalidMessage("Undefined name value in where clause ('value =
1')",
+ "DELETE FROM %s WHERE a = 1 AND value = 1 AND
column1 = 1");
+ assertInvalidMessage("Unknown identifier value",
+ "DELETE value FROM %s WHERE a = 1");
+ assertInvalidMessage("Unknown identifier column1",
+ "DELETE column1 FROM %s WHERE a = 1");
+ }
/**
* Checks if the memtable is empty or not
diff --git
a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertTest.java
b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertTest.java
index c9a9faf..8c42668 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertTest.java
@@ -22,6 +22,7 @@ import org.junit.Test;
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.utils.ByteBufferUtil;
public class InsertTest extends CQLTester
{
@@ -195,6 +196,73 @@ public class InsertTest extends CQLTester
"INSERT INTO %s (partitionKey, clustering_1,
clustering_2, valuex) VALUES (0, 0, 0, 2)");
}
+ /**
+ * Test for CASSANDRA-13917
+ */
+ @Test
+ public void testInsertWithCompactStaticFormat() throws Throwable
+ {
+ testWithCompactTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c
int) WITH COMPACT STORAGE");
+
+ // if column1 is present, hidden column is called column2
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int, column1
int) WITH COMPACT STORAGE");
+ execute("INSERT INTO %s (a, b, c, column1) VALUES (1, 1, 1, 1)");
+ assertInvalidMessage("Unknown identifier column2",
+ "INSERT INTO %s (a, b, c, column2) VALUES (1, 1,
1, 1)");
+
+ // if value is present, hidden column is called value1
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int, value
int) WITH COMPACT STORAGE");
+ execute("INSERT INTO %s (a, b, c, value) VALUES (1, 1, 1, 1)");
+ assertInvalidMessage("Unknown identifier value1",
+ "INSERT INTO %s (a, b, c, value1) VALUES (1, 1,
1, 1)");
+ }
+
+ /**
+ * Test for CASSANDRA-13917
+ */
+ @Test
+ public void testInsertWithCompactNonStaticFormat() throws Throwable
+ {
+ testWithCompactTable("CREATE TABLE %s (a int, b int, PRIMARY KEY (a,
b)) WITH COMPACT STORAGE");
+ testWithCompactTable("CREATE TABLE %s (a int, b int, v int, PRIMARY
KEY (a, b)) WITH COMPACT STORAGE");
+ }
+
+ private void testWithCompactTable(String tableQuery) throws Throwable
+ {
+ createTable(tableQuery);
+
+ // pass correct types to the hidden columns
+ assertInvalidMessage("Unknown identifier column1",
+ "INSERT INTO %s (a, b, column1) VALUES (?, ?, ?)",
+ 1, 1, 1, ByteBufferUtil.bytes('a'));
+ assertInvalidMessage("Unknown identifier value",
+ "INSERT INTO %s (a, b, value) VALUES (?, ?, ?)",
+ 1, 1, 1, ByteBufferUtil.bytes('a'));
+ assertInvalidMessage("Unknown identifier column1",
+ "INSERT INTO %s (a, b, column1, value) VALUES (?,
?, ?, ?)",
+ 1, 1, 1, ByteBufferUtil.bytes('a'),
ByteBufferUtil.bytes('b'));
+ assertInvalidMessage("Unknown identifier value",
+ "INSERT INTO %s (a, b, value, column1) VALUES (?,
?, ?, ?)",
+ 1, 1, 1, ByteBufferUtil.bytes('a'),
ByteBufferUtil.bytes('b'));
+
+ // pass incorrect types to the hidden columns
+ assertInvalidMessage("Unknown identifier value",
+ "INSERT INTO %s (a, b, value) VALUES (?, ?, ?)",
+ 1, 1, 1, 1);
+ assertInvalidMessage("Unknown identifier column1",
+ "INSERT INTO %s (a, b, column1) VALUES (?, ?, ?)",
+ 1, 1, 1, 1);
+ assertEmpty(execute("SELECT * FROM %s"));
+
+ // pass null to the hidden columns
+ assertInvalidMessage("Unknown identifier value",
+ "INSERT INTO %s (a, b, value) VALUES (?, ?, ?)",
+ 1, 1, null);
+ assertInvalidMessage("Unknown identifier column1",
+ "INSERT INTO %s (a, b, column1) VALUES (?, ?, ?)",
+ 1, 1, null);
+ }
+
@Test
public void testInsertWithCompactStorageAndTwoClusteringColumns() throws
Throwable
{
diff --git
a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java
b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java
index 90b47b7..6182f11 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java
@@ -3022,4 +3022,80 @@ public class SelectTest extends CQLTester
i++;
}
}
+
+ /**
+ * Test for CASSANDRA-13917
+ */
+ @Test
+ public void testWithCompactStaticFormat() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int) WITH
COMPACT STORAGE");
+ execute("INSERT INTO %s (a, b, c) VALUES (1, 1, 1)");
+ execute("INSERT INTO %s (a, b, c) VALUES (2, 1, 1)");
+ assertRows(execute("SELECT a, b, c FROM %s"),
+ row(1, 1, 1),
+ row(2, 1, 1));
+ testWithCompactFormat();
+
+ // if column column1 is present, hidden column is called column2
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int, column1
int) WITH COMPACT STORAGE");
+ execute("INSERT INTO %s (a, b, c, column1) VALUES (1, 1, 1, 1)");
+ execute("INSERT INTO %s (a, b, c, column1) VALUES (2, 1, 1, 2)");
+ assertRows(execute("SELECT a, b, c, column1 FROM %s"),
+ row(1, 1, 1, 1),
+ row(2, 1, 1, 2));
+ assertInvalidMessage("Undefined name column2 in selection clause",
+ "SELECT a, column2, value FROM %s");
+
+ // if column value is present, hidden column is called value1
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int, value
int) WITH COMPACT STORAGE");
+ execute("INSERT INTO %s (a, b, c, value) VALUES (1, 1, 1, 1)");
+ execute("INSERT INTO %s (a, b, c, value) VALUES (2, 1, 1, 2)");
+ assertRows(execute("SELECT a, b, c, value FROM %s"),
+ row(1, 1, 1, 1),
+ row(2, 1, 1, 2));
+ assertInvalidMessage("Undefined name value1 in selection clause",
+ "SELECT a, value1, value FROM %s");
+ }
+
+ /**
+ * Test for CASSANDRA-13917
+ */
+ @Test
+ public void testWithCompactNonStaticFormat() throws Throwable
+ {
+ createTable("CREATE TABLE %s (a int, b int, PRIMARY KEY (a, b)) WITH
COMPACT STORAGE");
+ execute("INSERT INTO %s (a, b) VALUES (1, 1)");
+ execute("INSERT INTO %s (a, b) VALUES (2, 1)");
+ assertRows(execute("SELECT a, b FROM %s"),
+ row(1, 1),
+ row(2, 1));
+ testWithCompactFormat();
+
+ createTable("CREATE TABLE %s (a int, b int, v int, PRIMARY KEY (a, b))
WITH COMPACT STORAGE");
+ execute("INSERT INTO %s (a, b, v) VALUES (1, 1, 3)");
+ execute("INSERT INTO %s (a, b, v) VALUES (2, 1, 4)");
+ assertRows(execute("SELECT a, b, v FROM %s"),
+ row(1, 1, 3),
+ row(2, 1, 4));
+ testWithCompactFormat();
+ }
+
+ private void testWithCompactFormat() throws Throwable
+ {
+ assertInvalidMessage("Undefined name column1 in selection clause",
+ "SELECT column1 FROM %s");
+ assertInvalidMessage("Undefined name value in selection clause",
+ "SELECT value FROM %s");
+ assertInvalidMessage("Undefined name value in selection clause",
+ "SELECT value, column1 FROM %s");
+ assertInvalid("Undefined name column1 in where clause ('column1 =
NULL')",
+ "SELECT * FROM %s WHERE column1 = null ALLOW FILTERING");
+ assertInvalid("Undefined name value in where clause ('value = NULL')",
+ "SELECT * FROM %s WHERE value = null ALLOW FILTERING");
+ assertInvalidMessage("Undefined name column1 in selection clause",
+ "SELECT WRITETIME(column1) FROM %s");
+ assertInvalidMessage("Undefined name value in selection clause",
+ "SELECT WRITETIME(value) FROM %s");
+ }
}
diff --git
a/test/unit/org/apache/cassandra/cql3/validation/operations/UpdateTest.java
b/test/unit/org/apache/cassandra/cql3/validation/operations/UpdateTest.java
index a49f828..8a9be19 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/UpdateTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/UpdateTest.java
@@ -29,6 +29,7 @@ import static org.junit.Assert.assertTrue;
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.Keyspace;
+import org.apache.cassandra.utils.ByteBufferUtil;
public class UpdateTest extends CQLTester
{
@@ -608,4 +609,60 @@ public class UpdateTest extends CQLTester
ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(currentTable());
return cfs.metric.allMemtablesLiveDataSize.getValue() == 0;
}
+
+ /**
+ * Test for CASSANDRA-13917
+ */
+ @Test
+ public void testUpdateWithCompactStaticFormat() throws Throwable
+ {
+ testWithCompactFormat("CREATE TABLE %s (a int PRIMARY KEY, b int, c
int) WITH COMPACT STORAGE");
+
+ assertInvalidMessage("Undefined name column1 in where clause ('column1
= ?')",
+ "UPDATE %s SET b = 1 WHERE column1 = ?",
+ ByteBufferUtil.bytes('a'));
+ assertInvalidMessage("Undefined name value in where clause ('value =
?')",
+ "UPDATE %s SET b = 1 WHERE value = ?",
+ ByteBufferUtil.bytes('a'));
+
+ // if column1 is present, hidden column is called column2
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int, column1
int) WITH COMPACT STORAGE");
+ execute("INSERT INTO %s (a, b, c, column1) VALUES (1, 1, 1, 1)");
+ execute("UPDATE %s SET column1 = 6 WHERE a = 1");
+ assertInvalidMessage("Unknown identifier column2", "UPDATE %s SET
column2 = 6 WHERE a = 0");
+ assertInvalidMessage("Unknown identifier value", "UPDATE %s SET value
= 6 WHERE a = 0");
+
+ // if value is present, hidden column is called value1
+ createTable("CREATE TABLE %s (a int PRIMARY KEY, b int, c int, value
int) WITH COMPACT STORAGE");
+ execute("INSERT INTO %s (a, b, c, value) VALUES (1, 1, 1, 1)");
+ execute("UPDATE %s SET value = 6 WHERE a = 1");
+ assertInvalidMessage("Unknown identifier column1", "UPDATE %s SET
column1 = 6 WHERE a = 1");
+ assertInvalidMessage("Unknown identifier value1", "UPDATE %s SET
value1 = 6 WHERE a = 1");
+ }
+
+ /**
+ * Test for CASSANDRA-13917
+ */
+ @Test
+ public void testUpdateWithCompactNonStaticFormat() throws Throwable
+ {
+ testWithCompactFormat("CREATE TABLE %s (a int, b int, PRIMARY KEY (a,
b)) WITH COMPACT STORAGE");
+ testWithCompactFormat("CREATE TABLE %s (a int, b int, v int, PRIMARY
KEY (a, b)) WITH COMPACT STORAGE");
+ }
+
+ private void testWithCompactFormat(String tableQuery) throws Throwable
+ {
+ createTable(tableQuery);
+ // pass correct types to hidden columns
+ assertInvalidMessage("Unknown identifier column1",
+ "UPDATE %s SET column1 = ? WHERE a = 0",
+ ByteBufferUtil.bytes('a'));
+ assertInvalidMessage("Unknown identifier value",
+ "UPDATE %s SET value = ? WHERE a = 0",
+ ByteBufferUtil.bytes('a'));
+
+ // pass incorrect types to hidden columns
+ assertInvalidMessage("Unknown identifier column1", "UPDATE %s SET
column1 = 6 WHERE a = 0");
+ assertInvalidMessage("Unknown identifier value", "UPDATE %s SET value
= 6 WHERE a = 0");
+ }
}
diff --git a/test/unit/org/apache/cassandra/db/PartitionRangeReadTest.java
b/test/unit/org/apache/cassandra/db/PartitionRangeReadTest.java
index c6968da..1368705 100644
--- a/test/unit/org/apache/cassandra/db/PartitionRangeReadTest.java
+++ b/test/unit/org/apache/cassandra/db/PartitionRangeReadTest.java
@@ -127,12 +127,6 @@ public class PartitionRangeReadTest
.add("val", "abcd")
.build()
.applyUnsafe();
-
- new RowUpdateBuilder(cfs.metadata, 0, Integer.toString(i))
- .clustering("column1")
- .add("value", "")
- .build()
- .applyUnsafe();
}
assertEquals(10, Util.getAll(Util.cmd(cfs).build()).size());
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]