You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2013/04/04 19:09:39 UTC
git commit: Add support for nulls in CQL3
Updated Branches:
refs/heads/cassandra-1.2 128177c41 -> cf84ea718
Add support for nulls in CQL3
patch by michalm & slebresne; reviewed by iamaleksey for CASSANDRA-3783
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/cf84ea71
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/cf84ea71
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/cf84ea71
Branch: refs/heads/cassandra-1.2
Commit: cf84ea718f84da3071cce0e66d6a9dc753ea4952
Parents: 128177c
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Thu Apr 4 19:07:32 2013 +0200
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Thu Apr 4 19:07:32 2013 +0200
----------------------------------------------------------------------
CHANGES.txt | 1 +
src/java/org/apache/cassandra/cql3/Constants.java | 32 ++++++++++++++
src/java/org/apache/cassandra/cql3/Cql.g | 3 +
src/java/org/apache/cassandra/cql3/Lists.java | 36 ++++++++++-----
src/java/org/apache/cassandra/cql3/Maps.java | 19 ++++----
src/java/org/apache/cassandra/cql3/Sets.java | 5 ++-
src/java/org/apache/cassandra/cql3/Term.java | 3 +-
7 files changed, 76 insertions(+), 23 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/cf84ea71/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 58ba39a..05a1188 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -19,6 +19,7 @@
* Fix NPE during cql3 select with token() (CASSANDRA-5404)
* IndexHelper.skipBloomFilters won't skip non-SHA filters (CASSANDRA-5385)
* cqlsh: Print maps ordered by key, sort sets (CASSANDRA-5413)
+ * Add null syntax support in CQL3 for inserts (CASSANDRA-3783)
Merged from 1.1:
* cli: Quote ks and cf names in schema output when needed (CASSANDRA-5052)
* Fix bad default for min/max timestamp in SSTableMetadata (CASSANDRA-5372)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/cf84ea71/src/java/org/apache/cassandra/cql3/Constants.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Constants.java b/src/java/org/apache/cassandra/cql3/Constants.java
index f630869..9366e7d 100644
--- a/src/java/org/apache/cassandra/cql3/Constants.java
+++ b/src/java/org/apache/cassandra/cql3/Constants.java
@@ -49,6 +49,38 @@ public abstract class Constants
STRING, INTEGER, UUID, FLOAT, BOOLEAN, HEX;
}
+ public static final Term.Raw NULL_LITERAL = new Term.Raw()
+ {
+ private final Term.Terminal NULL_VALUE = new Value(null)
+ {
+ @Override
+ public Terminal bind(List<ByteBuffer> values)
+ {
+ // We return null because that makes life easier for collections
+ return null;
+ }
+ };
+
+ public Term prepare(ColumnSpecification receiver) throws InvalidRequestException
+ {
+ if (!isAssignableTo(receiver))
+ throw new InvalidRequestException("Invalid null value for counter increment/decrement");
+
+ return NULL_VALUE;
+ }
+
+ public boolean isAssignableTo(ColumnSpecification receiver)
+ {
+ return !(receiver.type instanceof CounterColumnType);
+ }
+
+ @Override
+ public String toString()
+ {
+ return null;
+ }
+ };
+
public static class Literal implements Term.Raw
{
private final Type type;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/cf84ea71/src/java/org/apache/cassandra/cql3/Cql.g
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Cql.g b/src/java/org/apache/cassandra/cql3/Cql.g
index fb38fff..0c2113f 100644
--- a/src/java/org/apache/cassandra/cql3/Cql.g
+++ b/src/java/org/apache/cassandra/cql3/Cql.g
@@ -704,6 +704,7 @@ collection_literal returns [Term.Raw value]
value returns [Term.Raw value]
: c=constant { $value = c; }
| l=collection_literal { $value = l; }
+ | K_NULL { $value = Constants.NULL_LITERAL; }
| QMARK { $value = new AbstractMarker.Raw(++currentBindMarkerIdx); }
;
@@ -961,6 +962,8 @@ K_TIMEUUID: T I M E U U I D;
K_TOKEN: T O K E N;
K_WRITETIME: W R I T E T I M E;
+K_NULL: N U L L;
+
K_MAP: M A P;
K_LIST: L I S T;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/cf84ea71/src/java/org/apache/cassandra/cql3/Lists.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Lists.java b/src/java/org/apache/cassandra/cql3/Lists.java
index 78db936..36694e5 100644
--- a/src/java/org/apache/cassandra/cql3/Lists.java
+++ b/src/java/org/apache/cassandra/cql3/Lists.java
@@ -81,6 +81,9 @@ public abstract class Lists
// We don't allow prepared marker in collections, nor nested collections
assert t instanceof Constants.Value;
ByteBuffer bytes = ((Constants.Value)t).bytes;
+ if (bytes == null)
+ throw new InvalidRequestException("null is not supported inside collections");
+
// We don't support value > 64K because the serialization format encode the length as an unsigned short.
if (bytes.remaining() > FBUtilities.MAX_UNSIGNED_SHORT)
throw new InvalidRequestException(String.format("List value is too long. List values are limited to %d bytes but %d bytes value provided",
@@ -255,24 +258,33 @@ public abstract class Lists
public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
{
- Term.Terminal index = idx.bind(params.variables);
- Term.Terminal value = t.bind(params.variables);
- assert index instanceof Constants.Value && value instanceof Constants.Value;
+ ByteBuffer index = idx.bindAndGet(params.variables);
+ ByteBuffer value = t.bindAndGet(params.variables);
+
+ if (index == null)
+ throw new InvalidRequestException("Invalid null value for list index");
List<Pair<ByteBuffer, IColumn>> existingList = params.getPrefetchedList(rowKey, columnName.key);
- int idx = ByteBufferUtil.toInt(((Constants.Value)index).bytes);
+ int idx = ByteBufferUtil.toInt(index);
if (idx < 0 || idx >= existingList.size())
throw new InvalidRequestException(String.format("List index %d out of bound, list has size %d", idx, existingList.size()));
- ByteBuffer bytes = ((Constants.Value)value).bytes;
- // We don't support value > 64K because the serialization format encode the length as an unsigned short.
- if (bytes.remaining() > FBUtilities.MAX_UNSIGNED_SHORT)
- throw new InvalidRequestException(String.format("List value is too long. List values are limited to %d bytes but %d bytes value provided",
- FBUtilities.MAX_UNSIGNED_SHORT,
- bytes.remaining()));
-
ByteBuffer elementName = existingList.get(idx).right.name();
- cf.addColumn(params.makeColumn(elementName, bytes));
+
+ if (value == null)
+ {
+ cf.addColumn(params.makeTombstone(elementName));
+ }
+ else
+ {
+ // We don't support value > 64K because the serialization format encode the length as an unsigned short.
+ if (value.remaining() > FBUtilities.MAX_UNSIGNED_SHORT)
+ throw new InvalidRequestException(String.format("List value is too long. List values are limited to %d bytes but %d bytes value provided",
+ FBUtilities.MAX_UNSIGNED_SHORT,
+ value.remaining()));
+
+ cf.addColumn(params.makeColumn(elementName, value));
+ }
}
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/cf84ea71/src/java/org/apache/cassandra/cql3/Maps.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Maps.java b/src/java/org/apache/cassandra/cql3/Maps.java
index a2eb761..875dc47 100644
--- a/src/java/org/apache/cassandra/cql3/Maps.java
+++ b/src/java/org/apache/cassandra/cql3/Maps.java
@@ -81,12 +81,16 @@ public abstract class Maps
// We don't support values > 64K because the serialization format encode the length as an unsigned short.
ByteBuffer keyBytes = ((Constants.Value)k).bytes;
+ if (keyBytes == null)
+ throw new InvalidRequestException("null is not supported inside collections");
if (keyBytes.remaining() > FBUtilities.MAX_UNSIGNED_SHORT)
throw new InvalidRequestException(String.format("Map key is too long. Map keys are limited to %d bytes but %d bytes keys provided",
FBUtilities.MAX_UNSIGNED_SHORT,
keyBytes.remaining()));
ByteBuffer valueBytes = ((Constants.Value)v).bytes;
+ if (valueBytes == null)
+ throw new InvalidRequestException("null is not supported inside collections");
if (valueBytes.remaining() > FBUtilities.MAX_UNSIGNED_SHORT)
throw new InvalidRequestException(String.format("Map value is too long. Map values are limited to %d bytes but %d bytes value provided",
FBUtilities.MAX_UNSIGNED_SHORT,
@@ -231,14 +235,12 @@ public abstract class Maps
public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
{
- Term.Terminal key = k.bind(params.variables);
- Term.Terminal value = t.bind(params.variables);
+ ByteBuffer key = k.bindAndGet(params.variables);
+ ByteBuffer value = t.bindAndGet(params.variables);
if (key == null)
throw new InvalidRequestException("Invalid null map key");
- assert key instanceof Constants.Value;
- assert value == null || value instanceof Constants.Value;
- ByteBuffer cellName = prefix.add(columnName.key).add(((Constants.Value)key).bytes).build();
+ ByteBuffer cellName = prefix.add(columnName.key).add(key).build();
if (value == null)
{
@@ -246,14 +248,13 @@ public abstract class Maps
}
else
{
- ByteBuffer bytes = ((Constants.Value)value).bytes;
// We don't support value > 64K because the serialization format encode the length as an unsigned short.
- if (bytes.remaining() > FBUtilities.MAX_UNSIGNED_SHORT)
+ if (value.remaining() > FBUtilities.MAX_UNSIGNED_SHORT)
throw new InvalidRequestException(String.format("Map value is too long. Map values are limited to %d bytes but %d bytes value provided",
FBUtilities.MAX_UNSIGNED_SHORT,
- bytes.remaining()));
+ value.remaining()));
- cf.addColumn(params.makeColumn(cellName, bytes));
+ cf.addColumn(params.makeColumn(cellName, value));
}
}
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/cf84ea71/src/java/org/apache/cassandra/cql3/Sets.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Sets.java b/src/java/org/apache/cassandra/cql3/Sets.java
index fb57542..8d67761 100644
--- a/src/java/org/apache/cassandra/cql3/Sets.java
+++ b/src/java/org/apache/cassandra/cql3/Sets.java
@@ -81,6 +81,9 @@ public abstract class Sets
}
ByteBuffer bytes = ((Constants.Value)t).bytes;
+ if (bytes == null)
+ throw new InvalidRequestException("null is not supported inside collections");
+
// We don't support value > 64K because the serialization format encode the length as an unsigned short.
if (bytes.remaining() > FBUtilities.MAX_UNSIGNED_SHORT)
throw new InvalidRequestException(String.format("Set value is too long. Set values are limited to %d bytes but %d bytes value provided",
@@ -215,7 +218,7 @@ public abstract class Sets
if (value == null)
return;
- assert value instanceof Sets.Value;
+ assert value instanceof Sets.Value : value;
Set<ByteBuffer> toAdd = ((Sets.Value)value).elements;
for (ByteBuffer bb : toAdd)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/cf84ea71/src/java/org/apache/cassandra/cql3/Term.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Term.java b/src/java/org/apache/cassandra/cql3/Term.java
index 3cdb70f..d2d7975 100644
--- a/src/java/org/apache/cassandra/cql3/Term.java
+++ b/src/java/org/apache/cassandra/cql3/Term.java
@@ -125,7 +125,8 @@ public interface Term
{
public ByteBuffer bindAndGet(List<ByteBuffer> values) throws InvalidRequestException
{
- return bind(values).get();
+ Terminal t = bind(values);
+ return t == null ? null : t.get();
}
}
}