[ 
https://issues.apache.org/jira/browse/CASSANDRA-6892?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Sylvain Lebresne updated CASSANDRA-6892:
----------------------------------------

    Attachment: 6892-2.0-v2.txt

The fact that a default alias could conflict with a column name introduced 
through thrift is definitively not on purpose. And in fact, this is not really 
just limited to default aliases since with a compact table with 1 clustering 
column, you currently cannot add a value for that clustering column if it 
conflicts with any of the CQL column names (which don't have to be "default" 
aliases in particular). Or rather, CQL will let you insert it, but if you scrub 
later, it will tell you the data is invalid which is bogus.

All this to say that this is not really entirely thrift related, and is really 
a bug in getColumnDefinitionFromColumnName (and that's what we should fix). 
This method should never return a definition that is not a REGULAR or STATIC 
one, since that's the only 2 cases where a column definition is "stored" inside 
an internal column/cell name.  That, plus the fact that getValueValidator() 
should always use getColumnDefinitionFromColumnName, since it's really only 
ever used when dealing with cell names. So anyway, attaching a v2 that does 
those modifications: it fixes getColumnDefinitionFromColumnName and fix 
getValueValidator to use it (renaming it to getValueValidatorFromColumnName for 
consistency sake). Also remove Schema.getValueValidator as it is a really 
unecessary (but that's more of a nit). The patch does include the unit tests 
from the first patch and adds a new one for the 'compact table with clustering 
column' case I describe above.


> Cassandra 2.0.x validates Thrift columns incorrectly and causes 
> InvalidRequestException
> ---------------------------------------------------------------------------------------
>
>                 Key: CASSANDRA-6892
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-6892
>             Project: Cassandra
>          Issue Type: Bug
>          Components: API
>            Reporter: Christian Spriegel
>            Assignee: Tyler Hobbs
>            Priority: Minor
>             Fix For: 2.0.7
>
>         Attachments: 6892-2.0-v2.txt, 6892-2.0.txt, CASSANDRA-6892_V1.patch
>
>
> I just upgrade my local dev machine to Cassandra 2.0, which causes one of my 
> automated tests to fail now. With the latest 1.2.x it was working fine.
> The Exception I get on my client (using Hector) is:
> {code}
> me.prettyprint.hector.api.exceptions.HInvalidRequestException: 
> InvalidRequestException(why:(Expected 8 or 0 byte long (21)) 
> [MDS_0][MasterdataIndex][key2] failed validation)
>       at 
> me.prettyprint.cassandra.service.ExceptionsTranslatorImpl.translate(ExceptionsTranslatorImpl.java:52)
>       at 
> me.prettyprint.cassandra.connection.HConnectionManager.operateWithFailover(HConnectionManager.java:265)
>       at 
> me.prettyprint.cassandra.model.ExecutingKeyspace.doExecuteOperation(ExecutingKeyspace.java:113)
>       at 
> me.prettyprint.cassandra.model.MutatorImpl.execute(MutatorImpl.java:243)
>       at 
> me.prettyprint.cassandra.service.template.AbstractColumnFamilyTemplate.executeBatch(AbstractColumnFamilyTemplate.java:115)
>       at 
> me.prettyprint.cassandra.service.template.AbstractColumnFamilyTemplate.executeIfNotBatched(AbstractColumnFamilyTemplate.java:163)
>       at 
> me.prettyprint.cassandra.service.template.ColumnFamilyTemplate.update(ColumnFamilyTemplate.java:69)
>       at 
> com.mycompany.spring3utils.dataaccess.cassandra.AbstractCassandraDAO.doUpdate(AbstractCassandraDAO.java:482)
>       ....
> Caused by: InvalidRequestException(why:(Expected 8 or 0 byte long (21)) 
> [MDS_0][MasterdataIndex][key2] failed validation)
>       at 
> org.apache.cassandra.thrift.Cassandra$batch_mutate_result.read(Cassandra.java:20833)
>       at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:78)
>       at 
> org.apache.cassandra.thrift.Cassandra$Client.recv_batch_mutate(Cassandra.java:964)
>       at 
> org.apache.cassandra.thrift.Cassandra$Client.batch_mutate(Cassandra.java:950)
>       at 
> me.prettyprint.cassandra.model.MutatorImpl$3.execute(MutatorImpl.java:246)
>       at 
> me.prettyprint.cassandra.model.MutatorImpl$3.execute(MutatorImpl.java:1)
>       at 
> me.prettyprint.cassandra.service.Operation.executeAndSetResult(Operation.java:104)
>       at 
> me.prettyprint.cassandra.connection.HConnectionManager.operateWithFailover(HConnectionManager.java:258)
>       ... 46 more
> {code}
> The schema of my column family is:
> {code}
> create column family MasterdataIndex with
>     compression_options = {sstable_compression:SnappyCompressor, 
> chunk_length_kb:64} and
>     comparator = UTF8Type and
>     key_validation_class = 'CompositeType(UTF8Type,LongType)' and
>     default_validation_class = BytesType;
> {code}
> From the error message it looks like Cassandra is trying to validate the 
> value with the key-validator! (My value in this case it 21 bytes long)
> I studied the Cassandra 2.0 code and found something wrong. It seems in 
> CFMetaData.addDefaultKeyAliases it passes the KeyValidator into 
> ColumnDefinition.partitionKeyDef. Inside ColumnDefinition the validator is 
> expected to be the value validator!
> In CFMetaData:
> {code}
>     private List<ColumnDefinition> 
> addDefaultKeyAliases(List<ColumnDefinition> pkCols)
>     {
>         for (int i = 0; i < pkCols.size(); i++)
>         {
>             if (pkCols.get(i) == null)
>             {
>                 Integer idx = null;
>                 AbstractType<?> type = keyValidator;
>                 if (keyValidator instanceof CompositeType)
>                 {
>                     idx = i;
>                     type = ((CompositeType)keyValidator).types.get(i);
>                 }
>                 // For compatibility sake, we call the first alias 'key' 
> rather than 'key1'. This
>                 // is inconsistent with column alias, but it's probably not 
> worth risking breaking compatibility now.
>                 ByteBuffer name = ByteBufferUtil.bytes(i == 0 ? 
> DEFAULT_KEY_ALIAS : DEFAULT_KEY_ALIAS + (i + 1));
>                 ColumnDefinition newDef = 
> ColumnDefinition.partitionKeyDef(name, type, idx); // type is LongType in my 
> case, as it uses keyValidator !!!
>                 column_metadata.put(newDef.name, newDef);
>                 pkCols.set(i, newDef);
>             }
>         }
>         return pkCols;
>     }
> ...
>     public AbstractType<?> getValidator() // in ThriftValidation this is 
> expected to be the value validator!
>     {
>         return validator;
>     }
> {code}



--
This message was sent by Atlassian JIRA
(v6.2#6252)

Reply via email to