Merge branch cassandra-3.0 into cassandra-3.11

Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/b5df3b4c
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/b5df3b4c
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/b5df3b4c

Branch: refs/heads/cassandra-3.11
Commit: b5df3b4c367c2927f309ca16a540b7be83636556
Parents: 7afb97c e51c85f
Author: Benjamin Lerer <b.le...@gmail.com>
Authored: Fri Jul 7 13:36:52 2017 +0200
Committer: Benjamin Lerer <b.le...@gmail.com>
Committed: Fri Jul 7 13:38:22 2017 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |  3 +-
 .../org/apache/cassandra/cql3/UserTypes.java    | 12 +---
 .../apache/cassandra/db/marshal/TupleType.java  | 45 ++++---------
 .../apache/cassandra/db/marshal/UserType.java   | 51 +++++----------
 .../cassandra/serializers/TupleSerializer.java  | 64 +++++++++++++++++++
 .../serializers/UserTypeSerializer.java         | 67 ++++++++++++++++++++
 .../validation/entities/CollectionsTest.java    | 36 +++++++++++
 .../cql3/validation/entities/TupleTypeTest.java | 10 ++-
 .../cql3/validation/entities/UserTypesTest.java | 15 ++++-
 9 files changed, 223 insertions(+), 80 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/b5df3b4c/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 096dfa4,c98ffd9..679d55b
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,51 -1,12 +1,52 @@@
 -3.0.15
 +3.11.1
 + * Properly evict pstmts from prepared statements cache (CASSANDRA-13641)
 +Merged from 3.0:
   * Allow different NUMACTL_ARGS to be passed in (CASSANDRA-13557)
 - * Allow native function calls in CQLSSTableWriter (CASSANDRA-12606)
   * Fix secondary index queries on COMPACT tables (CASSANDRA-13627)
   * Nodetool listsnapshots output is missing a newline, if there are no 
snapshots (CASSANDRA-13568)
- 
 - Merged from 2.2:
 -* Fix nested Tuples/UDTs validation (CASSANDRA-13646)
++Merged from 2.2:
++ * Fix nested Tuples/UDTs validation (CASSANDRA-13646)
  
 -3.0.14
 +3.11.0
 + * Allow native function calls in CQLSSTableWriter (CASSANDRA-12606)
 + * Replace string comparison with regex/number checks in MessagingService 
test (CASSANDRA-13216)
 + * Fix formatting of duration columns in CQLSH (CASSANDRA-13549)
 + * Fix the problem with duplicated rows when using paging with SASI 
(CASSANDRA-13302)
 + * Allow CONTAINS statements filtering on the partition key and it’s parts 
(CASSANDRA-13275)
 + * Fall back to even ranges calculation in clusters with vnodes when tokens 
are distributed unevenly (CASSANDRA-13229)
 + * Fix duration type validation to prevent overflow (CASSANDRA-13218)
 + * Forbid unsupported creation of SASI indexes over partition key columns 
(CASSANDRA-13228)
 + * Reject multiple values for a key in CQL grammar. (CASSANDRA-13369)
 + * UDA fails without input rows (CASSANDRA-13399)
 + * Fix compaction-stress by using daemonInitialization (CASSANDRA-13188)
 + * V5 protocol flags decoding broken (CASSANDRA-13443)
 + * Use write lock not read lock for removing sstables from compaction 
strategies. (CASSANDRA-13422)
 + * Use corePoolSize equal to maxPoolSize in JMXEnabledThreadPoolExecutors 
(CASSANDRA-13329)
 + * Avoid rebuilding SASI indexes containing no values (CASSANDRA-12962)
 + * Add charset to Analyser input stream (CASSANDRA-13151)
 + * Fix testLimitSSTables flake caused by concurrent flush (CASSANDRA-12820)
 + * cdc column addition strikes again (CASSANDRA-13382)
 + * Fix static column indexes (CASSANDRA-13277)
 + * DataOutputBuffer.asNewBuffer broken (CASSANDRA-13298)
 + * unittest CipherFactoryTest failed on MacOS (CASSANDRA-13370)
 + * Forbid SELECT restrictions and CREATE INDEX over non-frozen UDT columns 
(CASSANDRA-13247)
 + * Default logging we ship will incorrectly print "?:?" for "%F:%L" pattern 
(CASSANDRA-13317)
 + * Possible AssertionError in UnfilteredRowIteratorWithLowerBound 
(CASSANDRA-13366)
 + * Support unaligned memory access for AArch64 (CASSANDRA-13326)
 + * Improve SASI range iterator efficiency on intersection with an empty range 
(CASSANDRA-12915).
 + * Fix equality comparisons of columns using the duration type 
(CASSANDRA-13174)
 + * Obfuscate password in stress-graphs (CASSANDRA-12233)
 + * Move to FastThreadLocalThread and FastThreadLocal (CASSANDRA-13034)
 + * nodetool stopdaemon errors out (CASSANDRA-13030)
 + * Tables in system_distributed should not use gcgs of 0 (CASSANDRA-12954)
 + * Fix primary index calculation for SASI (CASSANDRA-12910)
 + * More fixes to the TokenAllocator (CASSANDRA-12990)
 + * NoReplicationTokenAllocator should work with zero replication factor 
(CASSANDRA-12983)
 + * Address message coalescing regression (CASSANDRA-12676)
 + * Delete illegal character from StandardTokenizerImpl.jflex (CASSANDRA-13417)
 + * Fix cqlsh automatic protocol downgrade regression (CASSANDRA-13307)
 + * Tracing payload not passed from QueryMessage to tracing session 
(CASSANDRA-12835)
 +Merged from 3.0:
   * Ensure int overflow doesn't occur when calculating large partition warning 
size (CASSANDRA-13172)
   * Ensure consistent view of partition columns between coordinator and 
replica in ColumnFilter (CASSANDRA-13004)
   * Failed unregistering mbean during drop keyspace (CASSANDRA-13346)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b5df3b4c/src/java/org/apache/cassandra/cql3/UserTypes.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/UserTypes.java
index e867179,68a0513..4edd27f
--- a/src/java/org/apache/cassandra/cql3/UserTypes.java
+++ b/src/java/org/apache/cassandra/cql3/UserTypes.java
@@@ -95,8 -88,8 +95,8 @@@ public abstract class UserType
  
          private void validateAssignableTo(String keyspace, 
ColumnSpecification receiver) throws InvalidRequestException
          {
 -            if (!(receiver.type instanceof UserType))
 +            if (!receiver.type.isUDT())
-                 throw new InvalidRequestException(String.format("Invalid user 
type literal for %s of type %s", receiver, receiver.type.asCQL3Type()));
+                 throw new InvalidRequestException(String.format("Invalid user 
type literal for %s of type %s", receiver.name, receiver.type.asCQL3Type()));
  
              UserType ut = (UserType)receiver.type;
              for (int i = 0; i < ut.size(); i++)
@@@ -108,10 -101,7 +108,10 @@@
  
                  ColumnSpecification fieldSpec = fieldSpecOf(receiver, i);
                  if (!value.testAssignment(keyspace, fieldSpec).isAssignable())
 -                    throw new InvalidRequestException(String.format("Invalid 
user type literal for %s: field %s is not of type %s", receiver.name, field, 
fieldSpec.type.asCQL3Type()));
 +                {
 +                    throw new InvalidRequestException(String.format("Invalid 
user type literal for %s: field %s is not of type %s",
-                             receiver, field, fieldSpec.type.asCQL3Type()));
++                            receiver.name, field, 
fieldSpec.type.asCQL3Type()));
 +                }
              }
          }
  
@@@ -150,52 -135,7 +150,46 @@@
          }
      }
  
 -    // Same purpose than Lists.DelayedValue, except we do handle bind marker 
in that case
 +    public static class Value extends Term.MultiItemTerminal
 +    {
 +        private final UserType type;
 +        public final ByteBuffer[] elements;
 +
 +        public Value(UserType type, ByteBuffer[] elements)
 +        {
 +            this.type = type;
 +            this.elements = elements;
 +        }
 +
 +        public static Value fromSerialized(ByteBuffer bytes, UserType type)
 +        {
-             ByteBuffer[] values = type.split(bytes);
-             if (values.length > type.size())
-             {
-                 throw new InvalidRequestException(String.format(
-                         "UDT value contained too many fields (expected %s, 
got %s)", type.size(), values.length));
-             }
- 
++            type.validate(bytes);
 +            return new Value(type, type.split(bytes));
 +        }
 +
 +        public ByteBuffer get(ProtocolVersion protocolVersion)
 +        {
 +            return TupleType.buildValue(elements);
 +        }
 +
 +        public boolean equals(UserType userType, Value v)
 +        {
 +            if (elements.length != v.elements.length)
 +                return false;
 +
 +            for (int i = 0; i < elements.length; i++)
 +                if (userType.fieldType(i).compare(elements[i], v.elements[i]) 
!= 0)
 +                    return false;
 +
 +            return true;
 +        }
 +
 +        public List<ByteBuffer> getElements()
 +        {
 +            return Arrays.asList(elements);
 +        }
 +    }
 +
      public static class DelayedValue extends Term.NonTerminal
      {
          private final UserType type;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b5df3b4c/src/java/org/apache/cassandra/db/marshal/TupleType.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/marshal/TupleType.java
index 5a90ae9,3af1054..034ad53
--- a/src/java/org/apache/cassandra/db/marshal/TupleType.java
+++ b/src/java/org/apache/cassandra/db/marshal/TupleType.java
@@@ -41,29 -37,26 +41,41 @@@ import org.apache.cassandra.utils.ByteB
   */
  public class TupleType extends AbstractType<ByteBuffer>
  {
 +    private static final String COLON = ":";
 +    private static final Pattern COLON_PAT = Pattern.compile(COLON);
 +    private static final String ESCAPED_COLON = "\\\\:";
 +    private static final Pattern ESCAPED_COLON_PAT = 
Pattern.compile(ESCAPED_COLON);
 +    private static final String AT = "@";
 +    private static final Pattern AT_PAT = Pattern.compile(AT);
 +    private static final String ESCAPED_AT = "\\\\@";
 +    private static final Pattern ESCAPED_AT_PAT = Pattern.compile(ESCAPED_AT);
 +    
      protected final List<AbstractType<?>> types;
  
+     private final TupleSerializer serializer;
+ 
      public TupleType(List<AbstractType<?>> types)
      {
 +        this(types, true);
 +    }
 +
 +    protected TupleType(List<AbstractType<?>> types, boolean freezeInner)
 +    {
          super(ComparisonType.CUSTOM);
 -        for (int i = 0; i < types.size(); i++)
 -            types.set(i, types.get(i).freeze());
 -        this.types = types;
 +        if (freezeInner)
 +            this.types = 
types.stream().map(AbstractType::freeze).collect(Collectors.toList());
 +        else
 +            this.types = types;
+         this.serializer = new TupleSerializer(fieldSerializers(types));
+     }
+ 
+     private static List<TypeSerializer<?>> 
fieldSerializers(List<AbstractType<?>> types)
+     {
+         int size = types.size();
+         List<TypeSerializer<?>> serializers = new ArrayList<>(size);
+         for (int i = 0; i < size; i++)
+             serializers.add(types.get(i).getSerializer());
+         return serializers;
      }
  
      public static TupleType getInstance(TypeParser parser) throws 
ConfigurationException, SyntaxException
@@@ -133,55 -120,13 +145,24 @@@
                  return cmp;
          }
  
 -        if (bb1.remaining() == 0)
 -            return bb2.remaining() == 0 ? 0 : -1;
 +        // handle trailing nulls
 +        while (bb1.remaining() > 0)
 +        {
 +            int size = bb1.getInt();
 +            if (size > 0) // non-null
 +                return 1;
 +        }
 +
 +        while (bb2.remaining() > 0)
 +        {
 +            int size = bb2.getInt();
 +            if (size > 0) // non-null
 +                return -1;
 +        }
  
 -        // bb1.remaining() > 0 && bb2.remaining() == 0
 -        return 1;
 +        return 0;
      }
  
-     @Override
-     public void validate(ByteBuffer bytes) throws MarshalException
-     {
-         ByteBuffer input = bytes.duplicate();
-         for (int i = 0; i < size(); i++)
-         {
-             // we allow the input to have less fields than declared so as to 
support field addition.
-             if (!input.hasRemaining())
-                 return;
- 
-             if (input.remaining() < Integer.BYTES)
-                 throw new MarshalException(String.format("Not enough bytes to 
read size of %dth component", i));
- 
-             int size = input.getInt();
- 
-             // size < 0 means null value
-             if (size < 0)
-                 continue;
- 
-             if (input.remaining() < size)
-                 throw new MarshalException(String.format("Not enough bytes to 
read %dth component", i));
- 
-             ByteBuffer field = ByteBufferUtil.readBytes(input, size);
-             types.get(i).validate(field);
-         }
- 
-         // We're allowed to get less fields than declared, but not more
-         if (input.hasRemaining())
-             throw new MarshalException("Invalid remaining data after end of 
tuple value");
-     }
- 
      /**
       * Split a tuple value into its component values.
       */

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b5df3b4c/src/java/org/apache/cassandra/db/marshal/UserType.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/marshal/UserType.java
index a59000a,b91dbf8..febd91c
--- a/src/java/org/apache/cassandra/db/marshal/UserType.java
+++ b/src/java/org/apache/cassandra/db/marshal/UserType.java
@@@ -29,11 -28,10 +29,13 @@@ import org.apache.cassandra.db.rows.Cel
  import org.apache.cassandra.exceptions.ConfigurationException;
  import org.apache.cassandra.exceptions.SyntaxException;
  import org.apache.cassandra.serializers.MarshalException;
 +import org.apache.cassandra.transport.ProtocolVersion;
+ import org.apache.cassandra.serializers.TypeSerializer;
+ import org.apache.cassandra.serializers.UserTypeSerializer;
  import org.apache.cassandra.utils.ByteBufferUtil;
  import org.apache.cassandra.utils.Pair;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
  
  /**
   * A user defined type.
@@@ -42,26 -40,36 +44,33 @@@
   */
  public class UserType extends TupleType
  {
 +    private static final Logger logger = 
LoggerFactory.getLogger(UserType.class);
 +
      public final String keyspace;
      public final ByteBuffer name;
 -    private final List<ByteBuffer> fieldNames;
 +    private final List<FieldIdentifier> fieldNames;
      private final List<String> stringFieldNames;
 +    private final boolean isMultiCell;
+     private final UserTypeSerializer serializer;
  
 -    public UserType(String keyspace, ByteBuffer name, List<ByteBuffer> 
fieldNames, List<AbstractType<?>> fieldTypes)
 +    public UserType(String keyspace, ByteBuffer name, List<FieldIdentifier> 
fieldNames, List<AbstractType<?>> fieldTypes, boolean isMultiCell)
      {
 -        super(fieldTypes);
 +        super(fieldTypes, false);
          assert fieldNames.size() == fieldTypes.size();
          this.keyspace = keyspace;
          this.name = name;
          this.fieldNames = fieldNames;
          this.stringFieldNames = new ArrayList<>(fieldNames.size());
 +        this.isMultiCell = isMultiCell;
 +
-         for (FieldIdentifier fieldName : fieldNames)
-             stringFieldNames.add(fieldName.toString());
+         LinkedHashMap<String , TypeSerializer<?>> fieldSerializers = new 
LinkedHashMap<>(fieldTypes.size());
+         for (int i = 0, m = fieldNames.size(); i < m; i++)
+         {
 -            ByteBuffer fieldName = fieldNames.get(i);
 -            try
 -            {
 -                String stringFieldName = ByteBufferUtil.string(fieldName, 
StandardCharsets.UTF_8);
 -                stringFieldNames.add(stringFieldName);
 -                fieldSerializers.put(stringFieldName, 
fieldTypes.get(i).getSerializer());
 -            }
 -            catch (CharacterCodingException ex)
 -            {
 -                throw new AssertionError("Got non-UTF8 field name for 
user-defined type: " + ByteBufferUtil.bytesToHex(fieldName), ex);
 -            }
++            String stringFieldName = fieldNames.get(i).toString();
++            stringFieldNames.add(stringFieldName);
++            fieldSerializers.put(stringFieldName, 
fieldTypes.get(i).getSerializer());
+         }
+         this.serializer = new UserTypeSerializer(fieldSerializers);
      }
  
      public static UserType getInstance(TypeParser parser) throws 
ConfigurationException, SyntaxException
@@@ -128,94 -117,6 +137,62 @@@
          return UTF8Type.instance.compose(name);
      }
  
 +    public int fieldPosition(FieldIdentifier fieldName)
 +    {
 +        return fieldNames.indexOf(fieldName);
 +    }
 +
 +    public CellPath cellPathForField(FieldIdentifier fieldName)
 +    {
 +        // we use the field position instead of the field name to allow for 
field renaming in ALTER TYPE statements
 +        return 
CellPath.create(ByteBufferUtil.bytes((short)fieldPosition(fieldName)));
 +    }
 +
 +    public ShortType nameComparator()
 +    {
 +        return ShortType.instance;
 +    }
 +
 +    public ByteBuffer serializeForNativeProtocol(Iterator<Cell> cells, 
ProtocolVersion protocolVersion)
 +    {
 +        assert isMultiCell;
 +
 +        ByteBuffer[] components = new ByteBuffer[size()];
 +        short fieldPosition = 0;
 +        while (cells.hasNext())
 +        {
 +            Cell cell = cells.next();
 +
 +            // handle null fields that aren't at the end
 +            short fieldPositionOfCell = 
ByteBufferUtil.toShort(cell.path().get(0));
 +            while (fieldPosition < fieldPositionOfCell)
 +                components[fieldPosition++] = null;
 +
 +            components[fieldPosition++] = cell.value();
 +        }
 +
 +        // append trailing nulls for missing cells
 +        while (fieldPosition < size())
 +            components[fieldPosition++] = null;
 +
 +        return TupleType.buildValue(components);
 +    }
 +
 +    public void validateCell(Cell cell) throws MarshalException
 +    {
 +        if (isMultiCell)
 +        {
 +            ByteBuffer path = cell.path().get(0);
 +            nameComparator().validate(path);
 +            Short fieldPosition = 
nameComparator().getSerializer().deserialize(path);
 +            fieldType(fieldPosition).validate(cell.value());
 +        }
 +        else
 +        {
 +            validate(cell.value());
 +        }
 +    }
 +
-     // Note: the only reason we override this is to provide nicer error 
message, but since that's not that much code...
-     @Override
-     public void validate(ByteBuffer bytes) throws MarshalException
-     {
-         ByteBuffer input = bytes.duplicate();
-         for (int i = 0; i < size(); i++)
-         {
-             // we allow the input to have less fields than declared so as to 
support field addition.
-             if (!input.hasRemaining())
-                 return;
- 
-             if (input.remaining() < 4)
-                 throw new MarshalException(String.format("Not enough bytes to 
read size of %dth field %s", i, fieldNameAsString(i)));
- 
-             int size = input.getInt();
- 
-             // size < 0 means null value
-             if (size < 0)
-                 continue;
- 
-             if (input.remaining() < size)
-                 throw new MarshalException(String.format("Not enough bytes to 
read %dth field %s", i, fieldNameAsString(i)));
- 
-             ByteBuffer field = ByteBufferUtil.readBytes(input, size);
-             types.get(i).validate(field);
-         }
- 
-         // We're allowed to get less fields than declared, but not more
-         if (input.hasRemaining())
-             throw new MarshalException("Invalid remaining data after end of 
UDT value");
-     }
- 
      @Override
      public Term fromJSONObject(Object parsed) throws MarshalException
      {
@@@ -395,35 -222,14 +372,41 @@@
      }
  
      @Override
 +    public boolean referencesDuration()
 +    {
 +        return fieldTypes().stream().anyMatch(f -> f.referencesDuration());
 +    }
 +
 +    @Override
      public String toString()
      {
 -        return getClass().getName() + 
TypeParser.stringifyUserTypeParameters(keyspace, name, fieldNames, types);
 +        return this.toString(false);
 +    }
 +
 +    @Override
 +    public boolean isTuple()
 +    {
 +        return false;
 +    }
 +
 +    @Override
 +    public String toString(boolean ignoreFreezing)
 +    {
 +        boolean includeFrozenType = !ignoreFreezing && !isMultiCell();
 +
 +        StringBuilder sb = new StringBuilder();
 +        if (includeFrozenType)
 +            sb.append(FrozenType.class.getName()).append("(");
 +        sb.append(getClass().getName());
 +        sb.append(TypeParser.stringifyUserTypeParameters(keyspace, name, 
fieldNames, types, ignoreFreezing || !isMultiCell));
 +        if (includeFrozenType)
 +            sb.append(")");
 +        return sb.toString();
      }
+ 
+     @Override
+     public TypeSerializer<ByteBuffer> getSerializer()
+     {
+         return serializer;
+     }
  }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b5df3b4c/src/java/org/apache/cassandra/serializers/TupleSerializer.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/serializers/TupleSerializer.java
index 0000000,7cf71c6..65e6654
mode 000000,100644..100644
--- a/src/java/org/apache/cassandra/serializers/TupleSerializer.java
+++ b/src/java/org/apache/cassandra/serializers/TupleSerializer.java
@@@ -1,0 -1,66 +1,64 @@@
+ /*
+  * 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.serializers;
+ 
+ import java.nio.ByteBuffer;
 -import java.util.HashMap;
+ import java.util.List;
 -import java.util.Map;
+ 
+ import org.apache.cassandra.utils.ByteBufferUtil;
+ 
+ public class TupleSerializer extends BytesSerializer
+ {
+     public final List<TypeSerializer<?>> fields;
+ 
+     public TupleSerializer(List<TypeSerializer<?>> fields)
+     {
+         this.fields = fields;
+     }
+ 
+     @Override
+     public void validate(ByteBuffer bytes) throws MarshalException
+     {
+         ByteBuffer input = bytes.duplicate();
+         for (int i = 0; i < fields.size(); i++)
+         {
+             // we allow the input to have less fields than declared so as to 
support field addition.
+             if (!input.hasRemaining())
+                 return;
+ 
 -            if (input.remaining() < 4)
++            if (input.remaining() < Integer.BYTES)
+                 throw new MarshalException(String.format("Not enough bytes to 
read size of %dth component", i));
+ 
+             int size = input.getInt();
+ 
+             // size < 0 means null value
+             if (size < 0)
+                 continue;
+ 
+             if (input.remaining() < size)
+                 throw new MarshalException(String.format("Not enough bytes to 
read %dth component", i));
+ 
+             ByteBuffer field = ByteBufferUtil.readBytes(input, size);
+             fields.get(i).validate(field);
+         }
+ 
+         // We're allowed to get less fields than declared, but not more
+         if (input.hasRemaining())
+             throw new MarshalException("Invalid remaining data after end of 
tuple value");
+     }
+ }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b5df3b4c/test/unit/org/apache/cassandra/cql3/validation/entities/CollectionsTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b5df3b4c/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java
----------------------------------------------------------------------
diff --cc 
test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java
index e295d82,c279e00..b78eb3e
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java
@@@ -52,10 -50,19 +52,19 @@@ public class UserTypesTest extends CQLT
      {
          String myType = createType("CREATE TYPE %s (f int)");
          createTable("CREATE TABLE %s(pk int PRIMARY KEY, t frozen<" + myType 
+ ">)");
-         assertInvalidMessage("Not enough bytes to read 0th component",
+         assertInvalidMessage("Not enough bytes to read 0th field f",
                               "INSERT INTO %s (pk, t) VALUES (?, ?)", 1, 
"test");
-         assertInvalidMessage("Not enough bytes to read 0th component",
+         assertInvalidMessage("Not enough bytes to read 0th field f",
                               "INSERT INTO %s (pk, t) VALUES (?, ?)", 1, 
Long.MAX_VALUE);
+ 
+         String type = createType("CREATE TYPE %s (a int, b tuple<int, text, 
double>)");
+         createTable("CREATE TABLE %s (k int PRIMARY KEY, t frozen<" + type + 
">)");
+         assertInvalidMessage("Invalid remaining data after end of tuple 
value",
+                              "INSERT INTO %s (k, t) VALUES (0, ?)",
 -                             userType(1, tuple(1, "1", 1.0, 1)));
++                             userType("a", 1, "b", tuple(1, "1", 1.0, 1)));
+ 
+         assertInvalidMessage("Invalid user type literal for t: field b is not 
of type frozen<tuple<int, text, double>>",
+                              "INSERT INTO %s (k, t) VALUES (0, {a: 1, b: (1, 
'1', 1.0, 1)})");
      }
  
      @Test
@@@ -128,44 -117,8 +137,44 @@@
                               " user types can only be used in the keyspace 
they are defined in",
                               "CREATE TABLE " + KEYSPACE + ".wrong (k int 
PRIMARY KEY, v frozen<otherKeyspace.myType>)");
  
 +        // referencing an unknown UDT
          assertInvalidMessage("Unknown type " + KEYSPACE + ".unknowntype",
                               "CREATE TABLE " + KEYSPACE + ".wrong (k int 
PRIMARY KEY, v frozen<" + KEYSPACE + '.' + "unknownType>)");
 +
 +        // bad deletions on frozen UDTs
 +        createTable("CREATE TABLE %s (a int PRIMARY KEY, b frozen<" + myType 
+ ">, c int)");
 +        assertInvalidMessage("Frozen UDT column b does not support field 
deletion", "DELETE b.a FROM %s WHERE a = 0");
 +        assertInvalidMessage("Invalid field deletion operation for non-UDT 
column c", "DELETE c.a FROM %s WHERE a = 0");
 +
 +        // bad updates on frozen UDTs
 +        assertInvalidMessage("Invalid operation (b.a = 0) for frozen UDT 
column b", "UPDATE %s SET b.a = 0 WHERE a = 0");
 +        assertInvalidMessage("Invalid operation (c.a = 0) for non-UDT column 
c", "UPDATE %s SET c.a = 0 WHERE a = 0");
 +
 +        // bad deletions on non-frozen UDTs
 +        createTable("CREATE TABLE %s (a int PRIMARY KEY, b " + myType + ", c 
int)");
 +        assertInvalidMessage("UDT column b does not have a field named foo", 
"DELETE b.foo FROM %s WHERE a = 0");
 +
 +        // bad updates on non-frozen UDTs
 +        assertInvalidMessage("UDT column b does not have a field named foo", 
"UPDATE %s SET b.foo = 0 WHERE a = 0");
 +
 +        // bad insert on non-frozen UDTs
 +        assertInvalidMessage("Unknown field 'foo' in value of user defined 
type", "INSERT INTO %s (a, b, c) VALUES (0, {a: 0, foo: 0}, 0)");
 +        if (usePrepared())
 +        {
-             assertInvalidMessage("Expected 1 value for " + typename + " 
column, but got more",
++            assertInvalidMessage("Invalid remaining data after end of UDT 
value",
 +                    "INSERT INTO %s (a, b, c) VALUES (0, ?, 0)", 
userType("a", 0, "foo", 0));
 +        }
 +        else
 +        {
 +            assertInvalidMessage("Unknown field 'foo' in value of user 
defined type " + typename,
 +                    "INSERT INTO %s (a, b, c) VALUES (0, ?, 0)", 
userType("a", 0, "foo", 0));
 +        }
 +
 +        // non-frozen UDT with non-frozen nested collection
 +        String typename2 = createType("CREATE TYPE %s (bar int, foo 
list<int>)");
 +        String myType2 = KEYSPACE + '.' + typename2;
 +        assertInvalidMessage("Non-frozen UDTs with nested non-frozen 
collections are not supported",
 +                "CREATE TABLE " + KEYSPACE + ".wrong (k int PRIMARY KEY, v " 
+ myType2 + ")");
      }
  
      @Test


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to