mirror of https://github.com/apache/cassandra
Merge branch cassandra-3.0 into trunk
This commit is contained in:
commit
d6d5698b8d
6
NEWS.txt
6
NEWS.txt
|
|
@ -118,6 +118,12 @@ Changed Defaults
|
|||
of the total space of the commitlog volume. (Before: always used
|
||||
8192)
|
||||
|
||||
New features
|
||||
------------
|
||||
- Custom QueryHandlers can retrieve the column specifications for the bound
|
||||
variables from QueryOptions by using the hasColumnSpecifications()
|
||||
and getColumnSpecifications() methods.
|
||||
|
||||
|
||||
2.2.1
|
||||
=====
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cassandra.utils.MD5Digest;
|
||||
|
||||
import org.apache.cassandra.db.ConsistencyLevel;
|
||||
import org.apache.cassandra.service.QueryState;
|
||||
|
||||
|
|
@ -50,6 +52,11 @@ public abstract class BatchQueryOptions
|
|||
|
||||
public abstract QueryOptions forStatement(int i);
|
||||
|
||||
public void prepareStatement(int i, List<ColumnSpecification> boundNames)
|
||||
{
|
||||
forStatement(i).prepare(boundNames);
|
||||
}
|
||||
|
||||
public ConsistencyLevel getConsistency()
|
||||
{
|
||||
return wrapped.getConsistency();
|
||||
|
|
@ -107,5 +114,26 @@ public abstract class BatchQueryOptions
|
|||
{
|
||||
return perStatementOptions.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareStatement(int i, List<ColumnSpecification> boundNames)
|
||||
{
|
||||
if (isPreparedStatement(i))
|
||||
{
|
||||
QueryOptions options = perStatementOptions.get(i);
|
||||
options.prepare(boundNames);
|
||||
options = QueryOptions.addColumnSpecifications(options, boundNames);
|
||||
perStatementOptions.set(i, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.prepareStatement(i, boundNames);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPreparedStatement(int i)
|
||||
{
|
||||
return getQueryOrIdList().get(i) instanceof MD5Digest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.cassandra.cql3;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import org.apache.cassandra.db.marshal.AbstractType;
|
||||
import org.apache.cassandra.db.marshal.ReversedType;
|
||||
|
||||
|
|
@ -91,4 +92,13 @@ public class ColumnSpecification
|
|||
{
|
||||
return Objects.hashCode(ksName, cfName, name, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return Objects.toStringHelper(this)
|
||||
.add("name", name)
|
||||
.add("type", type)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,9 @@ import java.util.Collections;
|
|||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.apache.cassandra.db.ConsistencyLevel;
|
||||
import org.apache.cassandra.service.QueryState;
|
||||
import org.apache.cassandra.service.pager.PagingState;
|
||||
|
|
@ -72,10 +73,43 @@ public abstract class QueryOptions
|
|||
return new DefaultQueryOptions(consistency, values, skipMetadata, new SpecificOptions(pageSize, pagingState, serialConsistency, -1L), 0);
|
||||
}
|
||||
|
||||
public static QueryOptions addColumnSpecifications(QueryOptions options, List<ColumnSpecification> columnSpecs)
|
||||
{
|
||||
return new OptionsWithColumnSpecifications(options, columnSpecs);
|
||||
}
|
||||
|
||||
public abstract ConsistencyLevel getConsistency();
|
||||
public abstract List<ByteBuffer> getValues();
|
||||
public abstract boolean skipMetadata();
|
||||
|
||||
/**
|
||||
* Tells whether or not this <code>QueryOptions</code> contains the column specifications for the bound variables.
|
||||
* <p>The column specifications will be present only for prepared statements.</p>
|
||||
* @return <code>true</code> this <code>QueryOptions</code> contains the column specifications for the bound
|
||||
* variables, <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean hasColumnSpecifications()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the column specifications for the bound variables (<i>optional operation</i>).
|
||||
*
|
||||
* <p>The column specifications will be present only for prepared statements.</p>
|
||||
*
|
||||
* <p>Invoke the {@link hasColumnSpecifications} method before invoking this method in order to ensure that this
|
||||
* <code>QueryOptions</code> contains the column specifications.</p>
|
||||
*
|
||||
* @return the option names
|
||||
* @throws UnsupportedOperationException If this <code>QueryOptions</code> does not contains the column
|
||||
* specifications.
|
||||
*/
|
||||
public ImmutableList<ColumnSpecification> getColumnSpecifications()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/** The pageSize for this query. Will be <= 0 if not relevant for the query. */
|
||||
public int getPageSize()
|
||||
{
|
||||
|
|
@ -159,7 +193,7 @@ public abstract class QueryOptions
|
|||
}
|
||||
}
|
||||
|
||||
static abstract class QueryOptionsWrapper extends QueryOptions
|
||||
static class QueryOptionsWrapper extends QueryOptions
|
||||
{
|
||||
protected final QueryOptions wrapped;
|
||||
|
||||
|
|
@ -168,6 +202,11 @@ public abstract class QueryOptions
|
|||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
public List<ByteBuffer> getValues()
|
||||
{
|
||||
return this.wrapped.getValues();
|
||||
}
|
||||
|
||||
public ConsistencyLevel getConsistency()
|
||||
{
|
||||
return wrapped.getConsistency();
|
||||
|
|
@ -196,6 +235,32 @@ public abstract class QueryOptions
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>QueryOptions</code> decorator that provides access to the column specifications.
|
||||
*/
|
||||
static class OptionsWithColumnSpecifications extends QueryOptionsWrapper
|
||||
{
|
||||
private final ImmutableList<ColumnSpecification> columnSpecs;
|
||||
|
||||
OptionsWithColumnSpecifications(QueryOptions wrapped, List<ColumnSpecification> columnSpecs)
|
||||
{
|
||||
super(wrapped);
|
||||
this.columnSpecs = ImmutableList.copyOf(columnSpecs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasColumnSpecifications()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<ColumnSpecification> getColumnSpecifications()
|
||||
{
|
||||
return columnSpecs;
|
||||
}
|
||||
}
|
||||
|
||||
static class OptionsWithNames extends QueryOptionsWrapper
|
||||
{
|
||||
private final List<String> names;
|
||||
|
|
@ -228,6 +293,7 @@ public abstract class QueryOptions
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ByteBuffer> getValues()
|
||||
{
|
||||
assert orderedValues != null; // We should have called prepare first!
|
||||
|
|
|
|||
|
|
@ -519,7 +519,7 @@ public class BatchStatement implements CQLStatement
|
|||
|
||||
// Use the CFMetadata of the first statement for partition key bind indexes. If the statements affect
|
||||
// multiple tables, we won't send partition key bind indexes.
|
||||
Short[] partitionKeyBindIndexes = haveMultipleCFs ? null
|
||||
Short[] partitionKeyBindIndexes = (haveMultipleCFs || batchStatement.statements.isEmpty())? null
|
||||
: boundNames.getPartitionKeyBindIndexes(batchStatement.statements.get(0).cfm);
|
||||
|
||||
return new ParsedStatement.Prepared(batchStatement, boundNames, partitionKeyBindIndexes);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public class DropTableStatement extends SchemaAlteringStatement
|
|||
try
|
||||
{
|
||||
KeyspaceMetadata ksm = Schema.instance.getKSMetaData(keyspace());
|
||||
CFMetaData cfm = ksm.tables.getNullable(columnFamily());
|
||||
CFMetaData cfm = ksm.getTableOrViewNullable(columnFamily());
|
||||
if (cfm != null)
|
||||
{
|
||||
if (cfm.isView())
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ public class BatchMessage extends Message.Request
|
|||
for (int i = 0; i < prepared.size(); i++)
|
||||
{
|
||||
ParsedStatement.Prepared p = prepared.get(i);
|
||||
batchOptions.forStatement(i).prepare(p.boundNames);
|
||||
batchOptions.prepareStatement(i, p.boundNames);
|
||||
|
||||
if (!(p.statement instanceof ModificationStatement))
|
||||
throw new InvalidRequestException("Invalid statement in batch: only UPDATE, INSERT and DELETE statements are allowed.");
|
||||
|
|
|
|||
|
|
@ -124,7 +124,10 @@ public class ExecuteMessage extends Message.Request
|
|||
Tracing.instance.begin("Execute CQL3 prepared query", state.getClientAddress(), builder.build());
|
||||
}
|
||||
|
||||
Message.Response response = handler.processPrepared(statement, state, options, getCustomPayload());
|
||||
// Some custom QueryHandlers are interested by the bound names. We provide them this information
|
||||
// by wrapping the QueryOptions.
|
||||
QueryOptions queryOptions = QueryOptions.addColumnSpecifications(options, prepared.boundNames);
|
||||
Message.Response response = handler.processPrepared(statement, state, queryOptions, getCustomPayload());
|
||||
if (options.skipMetadata() && response instanceof ResultMessage.Rows)
|
||||
((ResultMessage.Rows)response).result.metadata.setSkipMetadata();
|
||||
|
||||
|
|
|
|||
|
|
@ -22,18 +22,16 @@ import java.math.BigDecimal;
|
|||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.datastax.driver.core.*;
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.exceptions.InvalidQueryException;
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.apache.cassandra.concurrent.SEPExecutor;
|
||||
import org.apache.cassandra.concurrent.Stage;
|
||||
import org.apache.cassandra.concurrent.StageManager;
|
||||
|
|
@ -46,6 +44,14 @@ import org.apache.cassandra.serializers.SimpleDateSerializer;
|
|||
import org.apache.cassandra.serializers.TimeSerializer;
|
||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||
import org.apache.cassandra.utils.FBUtilities;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.Row;
|
||||
import com.datastax.driver.core.exceptions.InvalidQueryException;
|
||||
|
||||
public class ViewTest extends CQLTester
|
||||
{
|
||||
|
|
@ -1352,4 +1358,30 @@ public class ViewTest extends CQLTester
|
|||
row(2),
|
||||
row(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDropTableWithMV() throws Throwable
|
||||
{
|
||||
createTable("CREATE TABLE %s (" +
|
||||
"a int," +
|
||||
"b int," +
|
||||
"c int," +
|
||||
"d int," +
|
||||
"PRIMARY KEY (a, b, c))");
|
||||
|
||||
executeNet(protocolVersion, "USE " + keyspace());
|
||||
|
||||
createView(keyspace() + ".mv1",
|
||||
"CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (a, b, c)");
|
||||
|
||||
try
|
||||
{
|
||||
executeNet(protocolVersion, "DROP TABLE " + keyspace() + ".mv1");
|
||||
Assert.fail();
|
||||
}
|
||||
catch (InvalidQueryException e)
|
||||
{
|
||||
Assert.assertEquals("Cannot use DROP TABLE on Materialized View", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,12 +18,8 @@
|
|||
|
||||
package org.apache.cassandra.cql3.validation.operations;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isEmpty;
|
||||
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
|
||||
public class BatchTest extends CQLTester
|
||||
|
|
@ -172,4 +168,10 @@ public class BatchTest extends CQLTester
|
|||
row(0, 5, 20),
|
||||
row(0, 6, 20));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatchEmpty() throws Throwable
|
||||
{
|
||||
assertEmpty(execute("BEGIN BATCH APPLY BATCH;"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue