blob: 8a9be19ad5e0cd53d03461c14d0d059bb675fda3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql3.validation.operations;
import java.util.Arrays;
import org.junit.Assert;
import org.junit.Test;
import static org.apache.commons.lang3.StringUtils.isEmpty;
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
{
@Test
public void testTypeCasts() throws Throwable
{
createTable("CREATE TABLE %s (k int PRIMARY KEY, t text, a ascii, d double, i int)");
// The followings is fine
execute("UPDATE %s SET t = 'foo' WHERE k = ?", 0);
execute("UPDATE %s SET t = (ascii)'foo' WHERE k = ?", 0);
execute("UPDATE %s SET t = (text)(ascii)'foo' WHERE k = ?", 0);
execute("UPDATE %s SET a = 'foo' WHERE k = ?", 0);
execute("UPDATE %s SET a = (ascii)'foo' WHERE k = ?", 0);
// But trying to put some explicitely type-casted text into an ascii
// column should be rejected (even though the text is actually ascci)
assertInvalid("UPDATE %s SET a = (text)'foo' WHERE k = ?", 0);
// This is also fine because integer constants works for both integer and float types
execute("UPDATE %s SET i = 3 WHERE k = ?", 0);
execute("UPDATE %s SET i = (int)3 WHERE k = ?", 0);
execute("UPDATE %s SET d = 3 WHERE k = ?", 0);
execute("UPDATE %s SET d = (double)3 WHERE k = ?", 0);
// But values for ints and doubles are not truly compatible (their binary representation differs)
assertInvalid("UPDATE %s SET d = (int)3 WHERE k = ?", 0);
assertInvalid("UPDATE %s SET i = (double)3 WHERE k = ?", 0);
}
@Test
public void testUpdate() throws Throwable
{
testUpdate(false);
testUpdate(true);
}
private void testUpdate(boolean forceFlush) throws Throwable
{
for (String compactOption : new String[] {"", " WITH COMPACT STORAGE" })
{
createTable("CREATE TABLE %s (partitionKey int," +
"clustering_1 int," +
"value int," +
" PRIMARY KEY (partitionKey, clustering_1))" + compactOption);
execute("INSERT INTO %s (partitionKey, clustering_1, value) VALUES (0, 0, 0)");
execute("INSERT INTO %s (partitionKey, clustering_1, value) VALUES (0, 1, 1)");
execute("INSERT INTO %s (partitionKey, clustering_1, value) VALUES (0, 2, 2)");
execute("INSERT INTO %s (partitionKey, clustering_1, value) VALUES (0, 3, 3)");
execute("INSERT INTO %s (partitionKey, clustering_1, value) VALUES (1, 0, 4)");
flush(forceFlush);
execute("UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 = ?", 7, 0, 1);
flush(forceFlush);
assertRows(execute("SELECT value FROM %s WHERE partitionKey = ? AND clustering_1 = ?",
0, 1),
row(7));
execute("UPDATE %s SET value = ? WHERE partitionKey = ? AND (clustering_1) = (?)", 8, 0, 2);
flush(forceFlush);
assertRows(execute("SELECT value FROM %s WHERE partitionKey = ? AND clustering_1 = ?",
0, 2),
row(8));
execute("UPDATE %s SET value = ? WHERE partitionKey IN (?, ?) AND clustering_1 = ?", 9, 0, 1, 0);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s WHERE partitionKey IN (?, ?) AND clustering_1 = ?",
0, 1, 0),
row(0, 0, 9),
row(1, 0, 9));
execute("UPDATE %s SET value = ? WHERE partitionKey IN ? AND clustering_1 = ?", 19, Arrays.asList(0, 1), 0);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s WHERE partitionKey IN ? AND clustering_1 = ?",
Arrays.asList(0, 1), 0),
row(0, 0, 19),
row(1, 0, 19));
execute("UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 IN (?, ?)", 10, 0, 1, 0);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s WHERE partitionKey = ? AND clustering_1 IN (?, ?)",
0, 1, 0),
row(0, 0, 10),
row(0, 1, 10));
execute("UPDATE %s SET value = ? WHERE partitionKey = ? AND (clustering_1) IN ((?), (?))", 20, 0, 0, 1);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s WHERE partitionKey = ? AND (clustering_1) IN ((?), (?))",
0, 0, 1),
row(0, 0, 20),
row(0, 1, 20));
execute("UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 = ?", null, 0, 0);
flush(forceFlush);
if (isEmpty(compactOption))
{
assertRows(execute("SELECT * FROM %s WHERE partitionKey = ? AND (clustering_1) IN ((?), (?))",
0, 0, 1),
row(0, 0, null),
row(0, 1, 20));
}
else
{
assertRows(execute("SELECT * FROM %s WHERE partitionKey = ? AND (clustering_1) IN ((?), (?))",
0, 0, 1),
row(0, 1, 20));
}
// test invalid queries
// missing primary key element
assertInvalidMessage("Some partition key parts are missing: partitionkey",
"UPDATE %s SET value = ? WHERE clustering_1 = ? ", 7, 1);
assertInvalidMessage("Some clustering keys are missing: clustering_1",
"UPDATE %s SET value = ? WHERE partitionKey = ?", 7, 0);
assertInvalidMessage("Some clustering keys are missing: clustering_1",
"UPDATE %s SET value = ? WHERE partitionKey = ?", 7, 0);
// token function
assertInvalidMessage("The token function cannot be used in WHERE clauses for UPDATE statements",
"UPDATE %s SET value = ? WHERE token(partitionKey) = token(?) AND clustering_1 = ?",
7, 0, 1);
// multiple time the same value
assertInvalidSyntax("UPDATE %s SET value = ?, value = ? WHERE partitionKey = ? AND clustering_1 = ?", 7, 0, 1);
// multiple time same primary key element in WHERE clause
assertInvalidMessage("clustering_1 cannot be restricted by more than one relation if it includes an Equal",
"UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 = ? AND clustering_1 = ?", 7, 0, 1, 1);
// unknown identifiers
assertInvalidMessage("Unknown identifier value1",
"UPDATE %s SET value1 = ? WHERE partitionKey = ? AND clustering_1 = ?", 7, 0, 1);
assertInvalidMessage("Undefined name partitionkey1 in where clause ('partitionkey1 = ?')",
"UPDATE %s SET value = ? WHERE partitionKey1 = ? AND clustering_1 = ?", 7, 0, 1);
assertInvalidMessage("Undefined name clustering_3 in where clause ('clustering_3 = ?')",
"UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_3 = ?", 7, 0, 1);
// Invalid operator in the where clause
assertInvalidMessage("Only EQ and IN relation are supported on the partition key (unless you use the token() function)",
"UPDATE %s SET value = ? WHERE partitionKey > ? AND clustering_1 = ?", 7, 0, 1);
assertInvalidMessage("Cannot use CONTAINS on non-collection column partitionkey",
"UPDATE %s SET value = ? WHERE partitionKey CONTAINS ? AND clustering_1 = ?", 7, 0, 1);
assertInvalidMessage("Non PRIMARY KEY columns found in where clause: value",
"UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 = ? AND value = ?", 7, 0, 1, 3);
assertInvalidMessage("Slice restrictions are not supported on the clustering columns in UPDATE statements",
"UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 > ?", 7, 0, 1);
}
}
@Test
public void testUpdateWithSecondaryIndices() throws Throwable
{
testUpdateWithSecondaryIndices(false);
testUpdateWithSecondaryIndices(true);
}
private void testUpdateWithSecondaryIndices(boolean forceFlush) throws Throwable
{
createTable("CREATE TABLE %s (partitionKey int," +
"clustering_1 int," +
"value int," +
"values set<int>," +
" PRIMARY KEY (partitionKey, clustering_1))");
createIndex("CREATE INDEX ON %s (value)");
createIndex("CREATE INDEX ON %s (clustering_1)");
createIndex("CREATE INDEX ON %s (values)");
execute("INSERT INTO %s (partitionKey, clustering_1, value, values) VALUES (0, 0, 0, {0})");
execute("INSERT INTO %s (partitionKey, clustering_1, value, values) VALUES (0, 1, 1, {0, 1})");
execute("INSERT INTO %s (partitionKey, clustering_1, value, values) VALUES (0, 2, 2, {0, 1, 2})");
execute("INSERT INTO %s (partitionKey, clustering_1, value, values) VALUES (0, 3, 3, {0, 1, 2, 3})");
execute("INSERT INTO %s (partitionKey, clustering_1, value, values) VALUES (1, 0, 4, {0, 1, 2, 3, 4})");
flush(forceFlush);
assertInvalidMessage("Non PRIMARY KEY columns found in where clause: value",
"UPDATE %s SET values= {6} WHERE partitionKey = ? AND clustering_1 = ? AND value = ?", 3, 3, 3);
assertInvalidMessage("Non PRIMARY KEY columns found in where clause: values",
"UPDATE %s SET value= ? WHERE partitionKey = ? AND clustering_1 = ? AND values CONTAINS ?", 6, 3, 3, 3);
assertInvalidMessage("Some clustering keys are missing: clustering_1",
"UPDATE %s SET values= {6} WHERE partitionKey = ? AND value = ?", 3, 3);
assertInvalidMessage("Some clustering keys are missing: clustering_1",
"UPDATE %s SET value= ? WHERE partitionKey = ? AND values CONTAINS ?", 6, 3, 3);
assertInvalidMessage("Some partition key parts are missing: partitionkey",
"UPDATE %s SET values= {6} WHERE clustering_1 = ?", 3);
assertInvalidMessage("Some partition key parts are missing: partitionkey",
"UPDATE %s SET values= {6} WHERE value = ?", 3);
assertInvalidMessage("Some partition key parts are missing: partitionkey",
"UPDATE %s SET value= ? WHERE values CONTAINS ?", 6, 3);
}
@Test
public void testUpdateWithTwoClusteringColumns() throws Throwable
{
testUpdateWithTwoClusteringColumns(false);
testUpdateWithTwoClusteringColumns(true);
}
private void testUpdateWithTwoClusteringColumns(boolean forceFlush) throws Throwable
{
for (String compactOption : new String[] { "", " WITH COMPACT STORAGE" })
{
createTable("CREATE TABLE %s (partitionKey int," +
"clustering_1 int," +
"clustering_2 int," +
"value int," +
" PRIMARY KEY (partitionKey, clustering_1, clustering_2))" + compactOption);
execute("INSERT INTO %s (partitionKey, clustering_1, clustering_2, value) VALUES (0, 0, 0, 0)");
execute("INSERT INTO %s (partitionKey, clustering_1, clustering_2, value) VALUES (0, 0, 1, 1)");
execute("INSERT INTO %s (partitionKey, clustering_1, clustering_2, value) VALUES (0, 0, 2, 2)");
execute("INSERT INTO %s (partitionKey, clustering_1, clustering_2, value) VALUES (0, 0, 3, 3)");
execute("INSERT INTO %s (partitionKey, clustering_1, clustering_2, value) VALUES (0, 1, 1, 4)");
execute("INSERT INTO %s (partitionKey, clustering_1, clustering_2, value) VALUES (0, 1, 2, 5)");
execute("INSERT INTO %s (partitionKey, clustering_1, clustering_2, value) VALUES (1, 0, 0, 6)");
flush(forceFlush);
execute("UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 = ?", 7, 0, 1, 1);
flush(forceFlush);
assertRows(execute("SELECT value FROM %s WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 = ?",
0, 1, 1),
row(7));
execute("UPDATE %s SET value = ? WHERE partitionKey = ? AND (clustering_1, clustering_2) = (?, ?)", 8, 0, 1, 2);
flush(forceFlush);
assertRows(execute("SELECT value FROM %s WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 = ?",
0, 1, 2),
row(8));
execute("UPDATE %s SET value = ? WHERE partitionKey IN (?, ?) AND clustering_1 = ? AND clustering_2 = ?", 9, 0, 1, 0, 0);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s WHERE partitionKey IN (?, ?) AND clustering_1 = ? AND clustering_2 = ?",
0, 1, 0, 0),
row(0, 0, 0, 9),
row(1, 0, 0, 9));
execute("UPDATE %s SET value = ? WHERE partitionKey IN ? AND clustering_1 = ? AND clustering_2 = ?", 9, Arrays.asList(0, 1), 0, 0);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s WHERE partitionKey IN ? AND clustering_1 = ? AND clustering_2 = ?",
Arrays.asList(0, 1), 0, 0),
row(0, 0, 0, 9),
row(1, 0, 0, 9));
execute("UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 IN (?, ?)", 12, 0, 1, 1, 2);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 IN (?, ?)",
0, 1, 1, 2),
row(0, 1, 1, 12),
row(0, 1, 2, 12));
execute("UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 IN (?, ?) AND clustering_2 IN (?, ?)", 10, 0, 1, 0, 1, 2);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s WHERE partitionKey = ? AND clustering_1 IN (?, ?) AND clustering_2 IN (?, ?)",
0, 1, 0, 1, 2),
row(0, 0, 1, 10),
row(0, 0, 2, 10),
row(0, 1, 1, 10),
row(0, 1, 2, 10));
execute("UPDATE %s SET value = ? WHERE partitionKey = ? AND (clustering_1, clustering_2) IN ((?, ?), (?, ?))", 20, 0, 0, 2, 1, 2);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s WHERE partitionKey = ? AND (clustering_1, clustering_2) IN ((?, ?), (?, ?))",
0, 0, 2, 1, 2),
row(0, 0, 2, 20),
row(0, 1, 2, 20));
execute("UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 = ?", null, 0, 0, 2);
flush(forceFlush);
if (isEmpty(compactOption))
{
assertRows(execute("SELECT * FROM %s WHERE partitionKey = ? AND (clustering_1, clustering_2) IN ((?, ?), (?, ?))",
0, 0, 2, 1, 2),
row(0, 0, 2, null),
row(0, 1, 2, 20));
}
else
{
assertRows(execute("SELECT * FROM %s WHERE partitionKey = ? AND (clustering_1, clustering_2) IN ((?, ?), (?, ?))",
0, 0, 2, 1, 2),
row(0, 1, 2, 20));
}
// test invalid queries
// missing primary key element
assertInvalidMessage("Some partition key parts are missing: partitionkey",
"UPDATE %s SET value = ? WHERE clustering_1 = ? AND clustering_2 = ?", 7, 1, 1);
String errorMsg = isEmpty(compactOption) ? "Some clustering keys are missing: clustering_1"
: "PRIMARY KEY column \"clustering_2\" cannot be restricted as preceding column \"clustering_1\" is not restricted";
assertInvalidMessage(errorMsg,
"UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_2 = ?", 7, 0, 1);
assertInvalidMessage("Some clustering keys are missing: clustering_1, clustering_2",
"UPDATE %s SET value = ? WHERE partitionKey = ?", 7, 0);
// token function
assertInvalidMessage("The token function cannot be used in WHERE clauses for UPDATE statements",
"UPDATE %s SET value = ? WHERE token(partitionKey) = token(?) AND clustering_1 = ? AND clustering_2 = ?",
7, 0, 1, 1);
// multiple time the same value
assertInvalidSyntax("UPDATE %s SET value = ?, value = ? WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 = ?", 7, 0, 1, 1);
// multiple time same primary key element in WHERE clause
assertInvalidMessage("clustering_1 cannot be restricted by more than one relation if it includes an Equal",
"UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 = ? AND clustering_1 = ?", 7, 0, 1, 1, 1);
// unknown identifiers
assertInvalidMessage("Unknown identifier value1",
"UPDATE %s SET value1 = ? WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 = ?", 7, 0, 1, 1);
assertInvalidMessage("Undefined name partitionkey1 in where clause ('partitionkey1 = ?')",
"UPDATE %s SET value = ? WHERE partitionKey1 = ? AND clustering_1 = ? AND clustering_2 = ?", 7, 0, 1, 1);
assertInvalidMessage("Undefined name clustering_3 in where clause ('clustering_3 = ?')",
"UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 = ? AND clustering_3 = ?", 7, 0, 1, 1);
// Invalid operator in the where clause
assertInvalidMessage("Only EQ and IN relation are supported on the partition key (unless you use the token() function)",
"UPDATE %s SET value = ? WHERE partitionKey > ? AND clustering_1 = ? AND clustering_2 = ?", 7, 0, 1, 1);
assertInvalidMessage("Cannot use CONTAINS on non-collection column partitionkey",
"UPDATE %s SET value = ? WHERE partitionKey CONTAINS ? AND clustering_1 = ? AND clustering_2 = ?", 7, 0, 1, 1);
assertInvalidMessage("Non PRIMARY KEY columns found in where clause: value",
"UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 = ? AND value = ?", 7, 0, 1, 1, 3);
assertInvalidMessage("Slice restrictions are not supported on the clustering columns in UPDATE statements",
"UPDATE %s SET value = ? WHERE partitionKey = ? AND clustering_1 > ?", 7, 0, 1);
assertInvalidMessage("Slice restrictions are not supported on the clustering columns in UPDATE statements",
"UPDATE %s SET value = ? WHERE partitionKey = ? AND (clustering_1, clustering_2) > (?, ?)", 7, 0, 1, 1);
}
}
@Test
public void testUpdateWithMultiplePartitionKeyComponents() throws Throwable
{
testUpdateWithMultiplePartitionKeyComponents(false);
testUpdateWithMultiplePartitionKeyComponents(true);
}
public void testUpdateWithMultiplePartitionKeyComponents(boolean forceFlush) throws Throwable
{
for (String compactOption : new String[] { "", " WITH COMPACT STORAGE" })
{
createTable("CREATE TABLE %s (partitionKey_1 int," +
"partitionKey_2 int," +
"clustering_1 int," +
"clustering_2 int," +
"value int," +
" PRIMARY KEY ((partitionKey_1, partitionKey_2), clustering_1, clustering_2))" + compactOption);
execute("INSERT INTO %s (partitionKey_1, partitionKey_2, clustering_1, clustering_2, value) VALUES (0, 0, 0, 0, 0)");
execute("INSERT INTO %s (partitionKey_1, partitionKey_2, clustering_1, clustering_2, value) VALUES (0, 1, 0, 1, 1)");
execute("INSERT INTO %s (partitionKey_1, partitionKey_2, clustering_1, clustering_2, value) VALUES (0, 1, 1, 1, 2)");
execute("INSERT INTO %s (partitionKey_1, partitionKey_2, clustering_1, clustering_2, value) VALUES (1, 0, 0, 1, 3)");
execute("INSERT INTO %s (partitionKey_1, partitionKey_2, clustering_1, clustering_2, value) VALUES (1, 1, 0, 1, 3)");
flush(forceFlush);
execute("UPDATE %s SET value = ? WHERE partitionKey_1 = ? AND partitionKey_2 = ? AND clustering_1 = ? AND clustering_2 = ?", 7, 0, 0, 0, 0);
flush(forceFlush);
assertRows(execute("SELECT value FROM %s WHERE partitionKey_1 = ? AND partitionKey_2 = ? AND clustering_1 = ? AND clustering_2 = ?",
0, 0, 0, 0),
row(7));
execute("UPDATE %s SET value = ? WHERE partitionKey_1 IN (?, ?) AND partitionKey_2 = ? AND clustering_1 = ? AND clustering_2 = ?", 9, 0, 1, 1, 0, 1);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s WHERE partitionKey_1 IN (?, ?) AND partitionKey_2 = ? AND clustering_1 = ? AND clustering_2 = ?",
0, 1, 1, 0, 1),
row(0, 1, 0, 1, 9),
row(1, 1, 0, 1, 9));
execute("UPDATE %s SET value = ? WHERE partitionKey_1 IN (?, ?) AND partitionKey_2 IN (?, ?) AND clustering_1 = ? AND clustering_2 = ?", 10, 0, 1, 0, 1, 0, 1);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s"),
row(0, 0, 0, 0, 7),
row(0, 0, 0, 1, 10),
row(0, 1, 0, 1, 10),
row(0, 1, 1, 1, 2),
row(1, 0, 0, 1, 10),
row(1, 1, 0, 1, 10));
// missing primary key element
assertInvalidMessage("Some partition key parts are missing: partitionkey_2",
"UPDATE %s SET value = ? WHERE partitionKey_1 = ? AND clustering_1 = ? AND clustering_2 = ?", 7, 1, 1);
}
}
@Test
public void testUpdateWithAStaticColumn() throws Throwable
{
testUpdateWithAStaticColumn(false);
testUpdateWithAStaticColumn(true);
}
private void testUpdateWithAStaticColumn(boolean forceFlush) throws Throwable
{
createTable("CREATE TABLE %s (partitionKey int," +
"clustering_1 int," +
"clustering_2 int," +
"value int," +
"staticValue text static," +
" PRIMARY KEY (partitionKey, clustering_1, clustering_2))");
execute("INSERT INTO %s (partitionKey, clustering_1, clustering_2, value, staticValue) VALUES (0, 0, 0, 0, 'A')");
execute("INSERT INTO %s (partitionKey, clustering_1, clustering_2, value) VALUES (0, 0, 1, 1)");
execute("INSERT INTO %s (partitionKey, clustering_1, clustering_2, value, staticValue) VALUES (1, 0, 0, 6, 'B')");
flush(forceFlush);
execute("UPDATE %s SET staticValue = ? WHERE partitionKey = ?", "A2", 0);
flush(forceFlush);
assertRows(execute("SELECT DISTINCT staticValue FROM %s WHERE partitionKey = ?", 0),
row("A2"));
assertInvalidMessage("Some clustering keys are missing: clustering_1, clustering_2",
"UPDATE %s SET staticValue = ?, value = ? WHERE partitionKey = ?", "A2", 7, 0);
execute("UPDATE %s SET staticValue = ?, value = ? WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 = ?",
"A3", 7, 0, 0, 1);
flush(forceFlush);
assertRows(execute("SELECT * FROM %s WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 = ?",
0, 0, 1),
row(0, 0, 1, "A3", 7));
assertInvalidMessage("Invalid restrictions on clustering columns since the UPDATE statement modifies only static columns",
"UPDATE %s SET staticValue = ? WHERE partitionKey = ? AND clustering_1 = ? AND clustering_2 = ?",
"A3", 0, 0, 1);
}
@Test
public void testUpdateWithStaticList() throws Throwable
{
createTable("CREATE TABLE %s (k int," +
"clustering int," +
"value int," +
"l list<text> static," +
" PRIMARY KEY (k, clustering))");
execute("INSERT INTO %s(k, clustering, value, l) VALUES (?, ?, ?, ?)", 0, 0, 0 ,list("v1", "v2", "v3"));
assertRows(execute("SELECT l FROM %s WHERE k = 0"), row(list("v1", "v2", "v3")));
execute("UPDATE %s SET l[?] = ? WHERE k = ?", 1, "v4", 0);
assertRows(execute("SELECT l FROM %s WHERE k = 0"), row(list("v1", "v4", "v3")));
}
/**
* Test for CASSANDRA-12829
*/
@Test
public void testUpdateWithEmptyInRestriction() throws Throwable
{
createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a,b))");
execute("INSERT INTO %s (a,b,c) VALUES (?,?,?)",1,1,1);
execute("INSERT INTO %s (a,b,c) VALUES (?,?,?)",1,2,2);
execute("INSERT INTO %s (a,b,c) VALUES (?,?,?)",1,3,3);
assertInvalidMessage("Some clustering keys are missing: b",
"UPDATE %s SET c = 100 WHERE a IN ();");
execute("UPDATE %s SET c = 100 WHERE a IN () AND b IN ();");
execute("UPDATE %s SET c = 100 WHERE a IN () AND b = 1;");
execute("UPDATE %s SET c = 100 WHERE a = 1 AND b IN ();");
assertRows(execute("SELECT * FROM %s"),
row(1,1,1),
row(1,2,2),
row(1,3,3));
createTable("CREATE TABLE %s (a int, b int, c int, d int, s int static, PRIMARY KEY ((a,b), c))");
execute("INSERT INTO %s (a,b,c,d,s) VALUES (?,?,?,?,?)",1,1,1,1,1);
execute("INSERT INTO %s (a,b,c,d,s) VALUES (?,?,?,?,?)",1,1,2,2,1);
execute("INSERT INTO %s (a,b,c,d,s) VALUES (?,?,?,?,?)",1,1,3,3,1);
execute("UPDATE %s SET d = 100 WHERE a = 1 AND b = 1 AND c IN ();");
execute("UPDATE %s SET d = 100 WHERE a = 1 AND b IN () AND c IN ();");
execute("UPDATE %s SET d = 100 WHERE a IN () AND b IN () AND c IN ();");
execute("UPDATE %s SET d = 100 WHERE a IN () AND b IN () AND c = 1;");
execute("UPDATE %s SET d = 100 WHERE a IN () AND b = 1 AND c IN ();");
assertRows(execute("SELECT * FROM %s"),
row(1,1,1,1,1),
row(1,1,2,1,2),
row(1,1,3,1,3));
// No clustering keys restricted, update whole partition
execute("UPDATE %s set s = 100 where a = 1 AND b = 1;");
assertRows(execute("SELECT * FROM %s"),
row(1,1,1,100,1),
row(1,1,2,100,2),
row(1,1,3,100,3));
execute("UPDATE %s set s = 200 where a = 1 AND b IN ();");
assertRows(execute("SELECT * FROM %s"),
row(1,1,1,100,1),
row(1,1,2,100,2),
row(1,1,3,100,3));
createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, PRIMARY KEY ((a,b), c, d))");
execute("INSERT INTO %s (a,b,c,d,e) VALUES (?,?,?,?,?)",1,1,1,1,1);
execute("INSERT INTO %s (a,b,c,d,e) VALUES (?,?,?,?,?)",1,1,1,2,2);
execute("INSERT INTO %s (a,b,c,d,e) VALUES (?,?,?,?,?)",1,1,1,3,3);
execute("INSERT INTO %s (a,b,c,d,e) VALUES (?,?,?,?,?)",1,1,1,4,4);
execute("UPDATE %s SET e = 100 WHERE a = 1 AND b = 1 AND c = 1 AND d IN ();");
execute("UPDATE %s SET e = 100 WHERE a = 1 AND b = 1 AND c IN () AND d IN ();");
execute("UPDATE %s SET e = 100 WHERE a = 1 AND b IN () AND c IN () AND d IN ();");
execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c IN () AND d IN ();");
execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c IN () AND d = 1;");
execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c = 1 AND d = 1;");
execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c = 1 AND d IN ();");
assertRows(execute("SELECT * FROM %s"),
row(1,1,1,1,1),
row(1,1,1,2,2),
row(1,1,1,3,3),
row(1,1,1,4,4));
}
/**
* Test for CASSANDRA-13152
*/
@Test
public void testThatUpdatesWithEmptyInRestrictionDoNotCreateMutations() throws Throwable
{
createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a,b))");
execute("UPDATE %s SET c = 100 WHERE a IN () AND b = 1;");
execute("UPDATE %s SET c = 100 WHERE a = 1 AND b IN ();");
assertTrue("The memtable should be empty but is not", isMemtableEmpty());
createTable("CREATE TABLE %s (a int, b int, c int, d int, s int static, PRIMARY KEY ((a,b), c))");
execute("UPDATE %s SET d = 100 WHERE a = 1 AND b = 1 AND c IN ();");
execute("UPDATE %s SET d = 100 WHERE a = 1 AND b IN () AND c IN ();");
execute("UPDATE %s SET d = 100 WHERE a IN () AND b IN () AND c IN ();");
execute("UPDATE %s SET d = 100 WHERE a IN () AND b IN () AND c = 1;");
execute("UPDATE %s SET d = 100 WHERE a IN () AND b = 1 AND c IN ();");
assertTrue("The memtable should be empty but is not", isMemtableEmpty());
createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, PRIMARY KEY ((a,b), c, d))");
execute("UPDATE %s SET e = 100 WHERE a = 1 AND b = 1 AND c = 1 AND d IN ();");
execute("UPDATE %s SET e = 100 WHERE a = 1 AND b = 1 AND c IN () AND d IN ();");
execute("UPDATE %s SET e = 100 WHERE a = 1 AND b IN () AND c IN () AND d IN ();");
execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c IN () AND d IN ();");
execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c IN () AND d = 1;");
execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c = 1 AND d = 1;");
execute("UPDATE %s SET e = 100 WHERE a IN () AND b IN () AND c = 1 AND d IN ();");
assertTrue("The memtable should be empty but is not", isMemtableEmpty());
}
/**
* Checks if the memtable is empty or not
* @return {@code true} if the memtable is empty, {@code false} otherwise.
*/
private boolean isMemtableEmpty()
{
Keyspace keyspace = Keyspace.open(KEYSPACE);
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");
}
}