Fix inserting empty maps patch by slebresne; reviewed by jbellis for CASSANDRA-5141
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/18913163 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/18913163 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/18913163 Branch: refs/heads/trunk Commit: 189131631bc11d851965856b7926cc1574d9d597 Parents: b664c55 Author: Sylvain Lebresne <sylv...@datastax.com> Authored: Fri Jan 11 17:59:40 2013 +0100 Committer: Sylvain Lebresne <sylv...@datastax.com> Committed: Fri Jan 11 17:59:40 2013 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cassandra/cql3/operations/SetOperation.java | 20 +++++++++++++++ .../cassandra/cql3/statements/UpdateStatement.java | 15 +++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/18913163/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index eae8dbb..b3d5dd7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -31,6 +31,7 @@ * Pick the correct value validator in sstable2json for cql3 tables (CASSANDRA-5134) * Validate login for describe_keyspace, describe_keyspaces and set_keyspace (CASSANDRA-5144) + * Fix inserting empty maps (CASSANDRA-5141) Merged from 1.1: * Simplify CompressedRandomAccessReader to work around JDK FD bug (CASSANDRA-5088) * Improve handling a changing target throttle rate mid-compaction (CASSANDRA-5087) http://git-wip-us.apache.org/repos/asf/cassandra/blob/18913163/src/java/org/apache/cassandra/cql3/operations/SetOperation.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/operations/SetOperation.java b/src/java/org/apache/cassandra/cql3/operations/SetOperation.java index e7f01c6..bec0e1a 100644 --- a/src/java/org/apache/cassandra/cql3/operations/SetOperation.java +++ b/src/java/org/apache/cassandra/cql3/operations/SetOperation.java @@ -18,6 +18,7 @@ package org.apache.cassandra.cql3.operations; import java.nio.ByteBuffer; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -73,6 +74,25 @@ public class SetOperation implements Operation } } + public Operation maybeConvertToEmptyMapOperation() + { + // If it's not empty or a DISCARD, it's a proper invalid query, not + // just the parser that hasn't been able to distinguish empty set from + // empty map. However, we just this as it will be rejected later and + // there is no point in duplicating validation + if (!values.isEmpty()) + return this; + + switch (kind) + { + case SET: + return MapOperation.Set(Collections.<Term, Term>emptyMap()); + case ADD: + return MapOperation.Put(Collections.<Term, Term>emptyMap()); + } + return this; + } + public static void doSetFromPrepared(ColumnFamily cf, ColumnNameBuilder builder, SetType validator, Term values, UpdateParameters params) throws InvalidRequestException { if (!values.isBindMarker()) http://git-wip-us.apache.org/repos/asf/cassandra/blob/18913163/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java b/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java index 46b1b18..7db2bdb 100644 --- a/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java @@ -26,6 +26,7 @@ import org.apache.cassandra.cql3.*; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.cql3.operations.ColumnOperation; import org.apache.cassandra.cql3.operations.Operation; +import org.apache.cassandra.cql3.operations.SetOperation; import org.apache.cassandra.cql3.operations.PreparedOperation; import org.apache.cassandra.db.*; import org.apache.cassandra.db.marshal.*; @@ -302,7 +303,7 @@ public class UpdateStatement extends ModificationStatement case COLUMN_METADATA: if (processedColumns.containsKey(name)) throw new InvalidRequestException(String.format("Multiple definitions found for column %s", name)); - processedColumns.put(name, operation); + addNewOperation(name, operation); break; } } @@ -352,7 +353,7 @@ public class UpdateStatement extends ModificationStatement throw new InvalidRequestException(String.format("Multiple definitions found for column %s", name)); operation.addBoundNames(name, boundNames); - processedColumns.put(name, operation); + addNewOperation(name, operation); break; } } @@ -362,6 +363,16 @@ public class UpdateStatement extends ModificationStatement return new ParsedStatement.Prepared(this, Arrays.<ColumnSpecification>asList(boundNames)); } + private void addNewOperation(CFDefinition.Name name, Operation operation) + { + // On the parser side, we're unable to differentiate an empty map from an empty set for add and set operations. + // Fix it now that we have the actual type. + if (operation.getType() == Operation.Type.SET && (name.type instanceof MapType)) + operation = ((SetOperation)operation).maybeConvertToEmptyMapOperation(); + + processedColumns.put(name, operation); + } + public ParsedStatement.Prepared prepare() throws InvalidRequestException { ColumnSpecification[] names = new ColumnSpecification[getBoundsTerms()];