Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id D73D0200BFC for ; Fri, 9 Dec 2016 11:49:06 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id D611F160B2A; Fri, 9 Dec 2016 10:49:06 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 18375160B1C for ; Fri, 9 Dec 2016 11:49:05 +0100 (CET) Received: (qmail 82430 invoked by uid 500); 9 Dec 2016 10:49:03 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 81750 invoked by uid 99); 9 Dec 2016 10:49:03 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 09 Dec 2016 10:49:03 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id CA148F1712; Fri, 9 Dec 2016 10:49:02 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: snazy@apache.org To: commits@cassandra.apache.org Date: Fri, 09 Dec 2016 10:49:11 -0000 Message-Id: <193a3b03cab24973965ea1e8ca2af1ef@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [10/17] cassandra git commit: Make distinction between unset row and non-existing partition for LWTs archived-at: Fri, 09 Dec 2016 10:49:07 -0000 Make distinction between unset row and non-existing partition for LWTs Patch by Alex Petrov; reviewed by Sylvain Lebresne for CASSANDRA-12964. Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/1cbaceaa Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/1cbaceaa Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/1cbaceaa Branch: refs/heads/cassandra-3.X Commit: 1cbaceaaa6e4cbd16149ef3ab9852050c041c7cc Parents: 1e06774 Author: Alex Petrov Authored: Wed Dec 7 16:04:51 2016 +0100 Committer: Sylvain Lebresne Committed: Fri Dec 9 11:28:26 2016 +0100 ---------------------------------------------------------------------- .../cql3/statements/CQL3CasRequest.java | 10 +++--- .../cassandra/db/filter/ColumnFilter.java | 9 ++++++ .../operations/InsertUpdateIfConditionTest.java | 32 +++++++++++++++++++- 3 files changed, 46 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/1cbaceaa/src/java/org/apache/cassandra/cql3/statements/CQL3CasRequest.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/CQL3CasRequest.java b/src/java/org/apache/cassandra/cql3/statements/CQL3CasRequest.java index ae2a4e5..c203ace 100644 --- a/src/java/org/apache/cassandra/cql3/statements/CQL3CasRequest.java +++ b/src/java/org/apache/cassandra/cql3/statements/CQL3CasRequest.java @@ -20,8 +20,7 @@ package org.apache.cassandra.cql3.statements; import java.nio.ByteBuffer; import java.util.*; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; +import com.google.common.collect.*; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.cql3.*; @@ -179,19 +178,22 @@ public class CQL3CasRequest implements CASRequest { assert staticConditions != null || !conditions.isEmpty(); + // Fetch all columns, but query only the selected ones + ColumnFilter columnFilter = ColumnFilter.selection(cfm, columnsToRead()); + // With only a static condition, we still want to make the distinction between a non-existing partition and one // that exists (has some live data) but has not static content. So we query the first live row of the partition. if (conditions.isEmpty()) return SinglePartitionReadCommand.create(cfm, nowInSec, - ColumnFilter.selection(columnsToRead()), + columnFilter, RowFilter.NONE, DataLimits.cqlLimits(1), key, new ClusteringIndexSliceFilter(Slices.ALL, false)); ClusteringIndexNamesFilter filter = new ClusteringIndexNamesFilter(conditions.navigableKeySet(), false); - return SinglePartitionReadCommand.create(cfm, nowInSec, key, ColumnFilter.selection(columnsToRead()), filter); + return SinglePartitionReadCommand.create(cfm, nowInSec, key, columnFilter, filter); } /** http://git-wip-us.apache.org/repos/asf/cassandra/blob/1cbaceaa/src/java/org/apache/cassandra/db/filter/ColumnFilter.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/filter/ColumnFilter.java b/src/java/org/apache/cassandra/db/filter/ColumnFilter.java index 0dd0aac..d320fc3 100644 --- a/src/java/org/apache/cassandra/db/filter/ColumnFilter.java +++ b/src/java/org/apache/cassandra/db/filter/ColumnFilter.java @@ -105,6 +105,15 @@ public class ColumnFilter return new ColumnFilter(false, null, columns, null); } + /** + * A filter that fetches all columns for the provided table, but returns + * only the queried ones. + */ + public static ColumnFilter selection(CFMetaData metadata, PartitionColumns queried) + { + return new ColumnFilter(true, metadata, queried, null); + } + /** * The columns that needs to be fetched internally for this filter. * http://git-wip-us.apache.org/repos/asf/cassandra/blob/1cbaceaa/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java index 0f6a918..6407300 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java @@ -186,6 +186,10 @@ public class InsertUpdateIfConditionTest extends CQLTester execute("INSERT INTO %s (k, s, i, v) VALUES ('k', 's', 0, 'v')"); assertRows(execute("DELETE v FROM %s WHERE k='k' AND i=0 IF EXISTS"), row(true)); assertRows(execute("DELETE FROM %s WHERE k='k' AND i=0 IF EXISTS"), row(true)); + assertRows(execute("SELECT * FROM %s"), row("k", null, "s", null)); + assertRows(execute("DELETE v FROM %s WHERE k='k' AND i=0 IF s = 'z'"), row(false, "s")); + assertRows(execute("DELETE v FROM %s WHERE k='k' AND i=0 IF v = 'z'"), row(false)); + assertRows(execute("DELETE v FROM %s WHERE k='k' AND i=0 IF v = 'z' AND s = 'z'"), row(false, null, "s")); assertRows(execute("DELETE v FROM %s WHERE k='k' AND i=0 IF EXISTS"), row(false)); assertRows(execute("DELETE FROM %s WHERE k='k' AND i=0 IF EXISTS"), row(false)); @@ -220,6 +224,28 @@ public class InsertUpdateIfConditionTest extends CQLTester assertRows(execute("DELETE FROM %s WHERE k = 1 AND i = 2 IF s = 1"), row(true)); assertEmpty(execute("SELECT * FROM %s WHERE k = 1 AND i = 2")); assertRows(execute("SELECT * FROM %s WHERE k = 1"), row(1, null, 1, null)); + + createTable("CREATE TABLE %s (k int, i int, v1 int, v2 int, s int static, PRIMARY KEY (k, i))"); + execute("INSERT INTO %s (k, i, v1, v2, s) VALUES (?, ?, ?, ?, ?)", + 1, 1, 1, 1, 1); + assertRows(execute("DELETE v1 FROM %s WHERE k = 1 AND i = 1 IF EXISTS"), + row(true)); + assertRows(execute("DELETE v2 FROM %s WHERE k = 1 AND i = 1 IF EXISTS"), + row(true)); + assertRows(execute("DELETE FROM %s WHERE k = 1 AND i = 1 IF EXISTS"), + row(true)); + assertRows(execute("select * from %s"), + row(1, null, 1, null, null)); + assertRows(execute("DELETE v1 FROM %s WHERE k = 1 AND i = 1 IF EXISTS"), + row(false)); + assertRows(execute("DELETE v1 FROM %s WHERE k = 1 AND i = 1 IF s = 5"), + row(false, 1)); + assertRows(execute("DELETE v1 FROM %s WHERE k = 1 AND i = 1 IF v1 = 1 AND v2 = 1"), + row(false)); + assertRows(execute("DELETE v1 FROM %s WHERE k = 1 AND i = 1 IF v1 = 1 AND v2 = 1 AND s = 1"), + row(false, null, null, 1)); + assertRows(execute("DELETE v1 FROM %s WHERE k = 1 AND i = 5 IF s = 1"), + row(true)); } /** @@ -249,13 +275,17 @@ public class InsertUpdateIfConditionTest extends CQLTester assertRows(execute("UPDATE %s SET v='bar', version=2 WHERE id=0 AND k='k2' IF version = 1"), row(true)); assertRows(execute("SELECT * FROM %s"), row(0, "k1", 2, "foo"), row(0, "k2", 2, "bar")); + // Batch output is slightly different from non-batch CAS, since a full PK is included to disambiguate + // cases when conditions span across multiple rows. + assertRows(execute("UPDATE %1$s SET version=3 WHERE id=0 IF version=1; "), + row(false, 2)); // Testing batches assertRows(execute("BEGIN BATCH " + "UPDATE %1$s SET v='foobar' WHERE id=0 AND k='k1'; " + "UPDATE %1$s SET v='barfoo' WHERE id=0 AND k='k2'; " + "UPDATE %1$s SET version=3 WHERE id=0 IF version=1; " + "APPLY BATCH "), - row(false, 0, null, 2)); + row(false, 0, "k1", 2)); assertRows(execute("BEGIN BATCH " + "UPDATE %1$s SET v = 'foobar' WHERE id = 0 AND k = 'k1'; " +