mirror of https://github.com/apache/cassandra
Accord: Deterministic time integration
- now() functions must be deterministic (and derived from Accord timestamp) - tombstone GC and TTL evaluation must be deterministic and based on both Accord timestamp and Accord GC mechanisms (that guarantee completeness of execution) patch by Benedict; reviewed by Alex Petrov and Ariel Weisberg for CASSANDRA-21376
This commit is contained in:
parent
a0dc6f857b
commit
7623a59b31
|
|
@ -82,12 +82,12 @@ public class Attributes
|
||||||
return timeToLive != null;
|
return timeToLive != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTimestamp(long now, QueryOptions options) throws InvalidRequestException
|
public long getTimestamp(long now, FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
if (timestamp == null)
|
if (timestamp == null)
|
||||||
return now;
|
return now;
|
||||||
|
|
||||||
ByteBuffer tval = timestamp.bindAndGet(options);
|
ByteBuffer tval = timestamp.bindAndGet(context);
|
||||||
if (tval == null)
|
if (tval == null)
|
||||||
throw new InvalidRequestException("Invalid null value of timestamp");
|
throw new InvalidRequestException("Invalid null value of timestamp");
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ public class Attributes
|
||||||
return LongType.instance.compose(tval);
|
return LongType.instance.compose(tval);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTimeToLive(QueryOptions options, TableMetadata metadata) throws InvalidRequestException
|
public int getTimeToLive(FunctionContext context, TableMetadata metadata) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
if (timeToLive == null)
|
if (timeToLive == null)
|
||||||
{
|
{
|
||||||
|
|
@ -114,7 +114,7 @@ public class Attributes
|
||||||
return metadata.params.defaultTimeToLive;
|
return metadata.params.defaultTimeToLive;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer tval = timeToLive.bindAndGet(options);
|
ByteBuffer tval = timeToLive.bindAndGet(context);
|
||||||
if (tval == null)
|
if (tval == null)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -356,9 +356,9 @@ public final class ColumnsExpression
|
||||||
* Returns the key, index or fieldname specifying the selected element.
|
* Returns the key, index or fieldname specifying the selected element.
|
||||||
* @return the key, index or fieldname specifying the selected element.
|
* @return the key, index or fieldname specifying the selected element.
|
||||||
*/
|
*/
|
||||||
public ByteBuffer element(QueryOptions options)
|
public ByteBuffer element(FunctionContext context)
|
||||||
{
|
{
|
||||||
return element.bindAndGet(options);
|
return element.bindAndGet(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -158,12 +158,12 @@ public final class ElementExpression
|
||||||
/**
|
/**
|
||||||
* Returns the ByteBuffer representation of the key or index.
|
* Returns the ByteBuffer representation of the key or index.
|
||||||
*
|
*
|
||||||
* @param options the query options
|
* @param context the query options
|
||||||
* @return the ByteBuffer representation of the key or index.
|
* @return the ByteBuffer representation of the key or index.
|
||||||
*/
|
*/
|
||||||
public ByteBuffer bindAndGet(QueryOptions options)
|
public ByteBuffer bindAndGet(FunctionContext context)
|
||||||
{
|
{
|
||||||
return keyOrIndex.bindAndGet(options);
|
return keyOrIndex.bindAndGet(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toCQLString()
|
public String toCQLString()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* 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.cql3;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.functions.Arguments;
|
||||||
|
import org.apache.cassandra.cql3.functions.FunctionArguments;
|
||||||
|
import org.apache.cassandra.db.marshal.TimeUUIDType;
|
||||||
|
import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
|
import org.apache.cassandra.utils.Clock.Global;
|
||||||
|
import org.apache.cassandra.utils.TimeUUID;
|
||||||
|
|
||||||
|
public interface FunctionContext
|
||||||
|
{
|
||||||
|
NoTimeOrQueryFunctionContext NONE = new NoTimeOrQueryFunctionContext() {};
|
||||||
|
|
||||||
|
interface RealTimeFunctionContext extends FunctionContext
|
||||||
|
{
|
||||||
|
@Override default byte[] nextTimeUUIDAsBytes() { return TimeUUID.Generator.nextTimeUUIDAsBytes(); }
|
||||||
|
@Override default Instant now() { return Global.currentTime(); }
|
||||||
|
@Override default long nowMicros() { return Global.currentTimeMicros(); }
|
||||||
|
@Override default long nowMillis() { return Global.currentTimeMillis(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NoTimeFunctionContext extends FunctionContext
|
||||||
|
{
|
||||||
|
@Override default byte[] nextTimeUUIDAsBytes() { throw new UnsupportedOperationException(); }
|
||||||
|
@Override default Instant now() { throw new UnsupportedOperationException(); }
|
||||||
|
@Override default long nowMicros() { throw new UnsupportedOperationException(); }
|
||||||
|
@Override default long nowMillis() { throw new UnsupportedOperationException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NoTimeOrQueryFunctionContext extends NoTimeFunctionContext
|
||||||
|
{
|
||||||
|
@Override default QueryOptions options() { throw new UnsupportedOperationException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PartialFunctionContext extends FunctionContext
|
||||||
|
{
|
||||||
|
default long nowMillis() { return nowMicros() / 1000; }
|
||||||
|
default Instant now()
|
||||||
|
{
|
||||||
|
long nowMicros = nowMicros();
|
||||||
|
return Instant.ofEpochSecond(nowMicros / 1000_000, (nowMicros % 1000_000) * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class MicrosFunctionContext implements PartialFunctionContext
|
||||||
|
{
|
||||||
|
final long atMicros;
|
||||||
|
private long timeUuidNanos;
|
||||||
|
|
||||||
|
public MicrosFunctionContext(long atMicros)
|
||||||
|
{
|
||||||
|
this.atMicros = atMicros;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public long nowMicros() { return atMicros; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] nextTimeUUIDAsBytes()
|
||||||
|
{
|
||||||
|
return TimeUUID.toBytes(TimeUUID.unixMicrosToMsb(atMicros), TimeUUIDType.signedBytesToNativeLong(timeUuidNanos++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryOptions options();
|
||||||
|
Instant now();
|
||||||
|
long nowMillis();
|
||||||
|
long nowMicros();
|
||||||
|
byte[] nextTimeUUIDAsBytes();
|
||||||
|
|
||||||
|
default ProtocolVersion getProtocolVersion() { return options().getProtocolVersion(); }
|
||||||
|
|
||||||
|
default Arguments noArguments()
|
||||||
|
{
|
||||||
|
return new FunctionArguments(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -251,12 +251,12 @@ public final class Json
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminal bind(QueryOptions options) throws InvalidRequestException
|
public Terminal bind(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
Term term = options.getJsonColumnValue(marker.bindIndex, column.name, marker.columns);
|
Term term = context.options().getJsonColumnValue(marker.bindIndex, column.name, marker.columns);
|
||||||
return term == null
|
return term == null
|
||||||
? (defaultUnset ? Constants.UNSET_VALUE : null)
|
? (defaultUnset ? Constants.UNSET_VALUE : null)
|
||||||
: term.bind(options);
|
: term.bind(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -116,9 +116,9 @@ public abstract class Operation
|
||||||
* Execute the operation.
|
* Execute the operation.
|
||||||
*
|
*
|
||||||
* @param partitionKey partition key for the update.
|
* @param partitionKey partition key for the update.
|
||||||
* @param params parameters of the update.
|
* @param builder parameters of the update.
|
||||||
*/
|
*/
|
||||||
public abstract void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException;
|
public abstract void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A parsed raw UPDATE operation.
|
* A parsed raw UPDATE operation.
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
import org.apache.cassandra.config.DataStorageSpec;
|
import org.apache.cassandra.config.DataStorageSpec;
|
||||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext.RealTimeFunctionContext;
|
||||||
import org.apache.cassandra.cql3.terms.Term;
|
import org.apache.cassandra.cql3.terms.Term;
|
||||||
import org.apache.cassandra.db.ConsistencyLevel;
|
import org.apache.cassandra.db.ConsistencyLevel;
|
||||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||||
|
|
@ -53,7 +54,7 @@ import static org.apache.cassandra.utils.ByteArrayUtil.convertToByteBufferValue;
|
||||||
/**
|
/**
|
||||||
* Options for a query.
|
* Options for a query.
|
||||||
*/
|
*/
|
||||||
public abstract class QueryOptions
|
public abstract class QueryOptions implements RealTimeFunctionContext
|
||||||
{
|
{
|
||||||
public static final QueryOptions DEFAULT = new DefaultQueryOptions(ConsistencyLevel.ONE,
|
public static final QueryOptions DEFAULT = new DefaultQueryOptions(ConsistencyLevel.ONE,
|
||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
|
|
@ -378,6 +379,12 @@ public abstract class QueryOptions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryOptions options()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
static class DefaultQueryOptions extends QueryOptions
|
static class DefaultQueryOptions extends QueryOptions
|
||||||
{
|
{
|
||||||
private final ConsistencyLevel consistency;
|
private final ConsistencyLevel consistency;
|
||||||
|
|
|
||||||
|
|
@ -555,7 +555,7 @@ public class QueryProcessor implements QueryHandler
|
||||||
.map(m -> MessagingService.instance().<ReadCommand, ReadResponse>sendWithResult(m, address))
|
.map(m -> MessagingService.instance().<ReadCommand, ReadResponse>sendWithResult(m, address))
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
ResultSetBuilder result = new ResultSetBuilder(select.getResultMetadata(), select.getSelection().newSelectors(options), false);
|
ResultSetBuilder result = new ResultSetBuilder(select.getResultMetadata(), options, select.getSelection().newSelectors(options), false);
|
||||||
return future.map(list -> {
|
return future.map(list -> {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Message<ReadResponse> m : list)
|
for (Message<ReadResponse> m : list)
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.cassandra.cql3;
|
package org.apache.cassandra.cql3;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
@ -43,20 +44,32 @@ import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.schema.ColumnMetadata;
|
import org.apache.cassandra.schema.ColumnMetadata;
|
||||||
import org.apache.cassandra.schema.TableMetadata;
|
import org.apache.cassandra.schema.TableMetadata;
|
||||||
import org.apache.cassandra.service.ClientState;
|
import org.apache.cassandra.service.ClientState;
|
||||||
import org.apache.cassandra.utils.TimeUUID;
|
|
||||||
|
|
||||||
/**
|
public abstract class RowUpdateBuilder implements FunctionContext
|
||||||
* Groups the parameters of an update query, and make building updates easier.
|
|
||||||
*/
|
|
||||||
public class UpdateParameters
|
|
||||||
{
|
{
|
||||||
public final TableMetadata metadata;
|
public static class RegularRowUpdateBuilder extends RowUpdateBuilder implements RealTimeFunctionContext
|
||||||
public final ClientState clientState;
|
{
|
||||||
public final QueryOptions options;
|
public RegularRowUpdateBuilder(TableMetadata metadata, ClientState clientState, QueryOptions options, long timestamp, long nowInSec, int ttl, Map<DecoratedKey, Partition> prefetchedRows) throws InvalidRequestException
|
||||||
|
{
|
||||||
|
super(metadata, clientState, options, timestamp, nowInSec, ttl, prefetchedRows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final long nowInSec;
|
public static class NoTimeRowUpdateBuilder extends RowUpdateBuilder implements NoTimeFunctionContext
|
||||||
protected final long timestamp;
|
{
|
||||||
private final int ttl;
|
public NoTimeRowUpdateBuilder(TableMetadata metadata, ClientState clientState, QueryOptions options, long timestamp, long nowInSec, int ttl, Map<DecoratedKey, Partition> prefetchedRows) throws InvalidRequestException
|
||||||
|
{
|
||||||
|
super(metadata, clientState, options, timestamp, nowInSec, ttl, prefetchedRows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final TableMetadata metadata;
|
||||||
|
private final QueryOptions options;
|
||||||
|
public final ClientState clientState;
|
||||||
|
|
||||||
|
public final long nowInSec;
|
||||||
|
public final long timestamp;
|
||||||
|
public final int ttl;
|
||||||
|
|
||||||
private DeletionTime deletionTime;
|
private DeletionTime deletionTime;
|
||||||
|
|
||||||
|
|
@ -66,7 +79,7 @@ public class UpdateParameters
|
||||||
// The builder currently in use. Will alias either staticBuilder or regularBuilder, which are themselves built lazily.
|
// The builder currently in use. Will alias either staticBuilder or regularBuilder, which are themselves built lazily.
|
||||||
private Row.Builder builder;
|
private Row.Builder builder;
|
||||||
|
|
||||||
public UpdateParameters(TableMetadata metadata,
|
protected RowUpdateBuilder(TableMetadata metadata,
|
||||||
ClientState clientState,
|
ClientState clientState,
|
||||||
QueryOptions options,
|
QueryOptions options,
|
||||||
long timestamp,
|
long timestamp,
|
||||||
|
|
@ -75,21 +88,26 @@ public class UpdateParameters
|
||||||
Map<DecoratedKey, Partition> prefetchedRows) throws InvalidRequestException
|
Map<DecoratedKey, Partition> prefetchedRows) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
this.clientState = clientState;
|
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
this.clientState = clientState;
|
||||||
this.nowInSec = nowInSec;
|
this.nowInSec = nowInSec;
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
this.ttl = ttl;
|
this.ttl = ttl;
|
||||||
|
|
||||||
|
this.deletionTime = DeletionTime.build(timestamp, nowInSec);
|
||||||
this.prefetchedRows = prefetchedRows;
|
this.prefetchedRows = prefetchedRows;
|
||||||
|
|
||||||
// We use MIN_VALUE internally to mean the absence of of timestamp (in Selection, in sstable stats, ...), so exclude
|
// We use MIN_VALUE internally to mean the absence of of timestamp (in Selection, in sstable stats, ...), so exclude
|
||||||
// it to avoid potential confusion.
|
// it to avoid potential confusion.
|
||||||
if (timestamp == Long.MIN_VALUE)
|
if (timestamp == Long.MIN_VALUE)
|
||||||
throw new InvalidRequestException(String.format("Out of bound timestamp, must be in [%d, %d]", Long.MIN_VALUE + 1, Long.MAX_VALUE));
|
throw new InvalidRequestException(String.format("Out of bound timestamp, must be in [%d, %d]", Long.MIN_VALUE + 1, Long.MAX_VALUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryOptions options()
|
||||||
|
{
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
public <V> void newRow(Clustering<V> clustering) throws InvalidRequestException
|
public <V> void newRow(Clustering<V> clustering) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
if (metadata.isCompactTable())
|
if (metadata.isCompactTable())
|
||||||
|
|
@ -208,7 +226,7 @@ public class UpdateParameters
|
||||||
newRow(row.clustering());
|
newRow(row.clustering());
|
||||||
addRowDeletion(row.deletion());
|
addRowDeletion(row.deletion());
|
||||||
addPrimaryKeyLivenessInfo(row.primaryKeyLivenessInfo());
|
addPrimaryKeyLivenessInfo(row.primaryKeyLivenessInfo());
|
||||||
row.iterator().forEachRemaining(cd -> {
|
row.forEach(cd -> {
|
||||||
if (cd instanceof Cell<?>)
|
if (cd instanceof Cell<?>)
|
||||||
{
|
{
|
||||||
builder.addCell((Cell<?>) cd);
|
builder.addCell((Cell<?>) cd);
|
||||||
|
|
@ -297,11 +315,6 @@ public class UpdateParameters
|
||||||
return new RangeTombstone(slice, deletionTime());
|
return new RangeTombstone(slice, deletionTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] nextTimeUUIDAsBytes()
|
|
||||||
{
|
|
||||||
return TimeUUID.Generator.nextTimeUUIDAsBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the prefetched row with the already performed modifications.
|
* Returns the prefetched row with the already performed modifications.
|
||||||
* <p>If no modification have yet been performed this method will return the fetched row or {@code null} if
|
* <p>If no modification have yet been performed this method will return the fetched row or {@code null} if
|
||||||
|
|
@ -332,4 +345,5 @@ public class UpdateParameters
|
||||||
return Rows.merge(prefetchedRow, pendingMutations)
|
return Rows.merge(prefetchedRow, pendingMutations)
|
||||||
.purge(DeletionPurger.PURGE_ALL, nowInSec, metadata.enforceStrictLiveness());
|
.purge(DeletionPurger.PURGE_ALL, nowInSec, metadata.enforceStrictLiveness());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -29,8 +29,8 @@ import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.ColumnsExpression;
|
import org.apache.cassandra.cql3.ColumnsExpression;
|
||||||
import org.apache.cassandra.cql3.FieldIdentifier;
|
import org.apache.cassandra.cql3.FieldIdentifier;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.Operator;
|
import org.apache.cassandra.cql3.Operator;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.cql3.terms.Term;
|
import org.apache.cassandra.cql3.terms.Term;
|
||||||
|
|
@ -110,39 +110,39 @@ public final class ColumnCondition
|
||||||
values.collectMarkerSpecification(boundNames, owner);
|
values.collectMarkerSpecification(boundNames, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ColumnCondition.Bound bind(QueryOptions options)
|
public ColumnCondition.Bound bind(FunctionContext context)
|
||||||
{
|
{
|
||||||
switch (columnsExpression.kind())
|
switch (columnsExpression.kind())
|
||||||
{
|
{
|
||||||
case SINGLE_COLUMN:
|
case SINGLE_COLUMN:
|
||||||
return bindSingleColumn(options);
|
return bindSingleColumn(context);
|
||||||
case ELEMENT:
|
case ELEMENT:
|
||||||
return bindElement(options);
|
return bindElement(context);
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bound bindSingleColumn(QueryOptions options)
|
private Bound bindSingleColumn(FunctionContext context)
|
||||||
{
|
{
|
||||||
ColumnMetadata column = columnsExpression.firstColumn();
|
ColumnMetadata column = columnsExpression.firstColumn();
|
||||||
TableMetadata table = columnsExpression.table();
|
TableMetadata table = columnsExpression.table();
|
||||||
if (column.type.isMultiCell())
|
if (column.type.isMultiCell())
|
||||||
return new MultiCellBound(column, table, operator, toValue(column.type, bindAndGetTerms(options)));
|
return new MultiCellBound(column, table, operator, toValue(column.type, bindAndGetTerms(context)));
|
||||||
|
|
||||||
return new SimpleBound(column, table, operator, toValue(column.type, bindAndGetTerms(options)));
|
return new SimpleBound(column, table, operator, toValue(column.type, bindAndGetTerms(context)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ColumnCondition.Bound bindElement(QueryOptions options)
|
private ColumnCondition.Bound bindElement(FunctionContext context)
|
||||||
{
|
{
|
||||||
ColumnMetadata column = columnsExpression.firstColumn();
|
ColumnMetadata column = columnsExpression.firstColumn();
|
||||||
TableMetadata table = columnsExpression.table();
|
TableMetadata table = columnsExpression.table();
|
||||||
ByteBuffer keyOrIndex = columnsExpression.element(options);
|
ByteBuffer keyOrIndex = columnsExpression.element(context);
|
||||||
if (column.type.isCollection())
|
if (column.type.isCollection())
|
||||||
{
|
{
|
||||||
checkNotNull(keyOrIndex, "Invalid null value for %s element access", column.type instanceof MapType ? "map" : "list");
|
checkNotNull(keyOrIndex, "Invalid null value for %s element access", column.type instanceof MapType ? "map" : "list");
|
||||||
}
|
}
|
||||||
return new ElementOrFieldAccessBound(column, table, keyOrIndex, operator, toValue(columnsExpression.type(), bindAndGetTerms(options)));
|
return new ElementOrFieldAccessBound(column, table, keyOrIndex, operator, toValue(columnsExpression.type(), bindAndGetTerms(context)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ByteBuffer toValue(AbstractType<?> type, List<ByteBuffer> values)
|
private ByteBuffer toValue(AbstractType<?> type, List<ByteBuffer> values)
|
||||||
|
|
@ -157,9 +157,9 @@ public final class ColumnCondition
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ByteBuffer> bindAndGetTerms(QueryOptions options)
|
private List<ByteBuffer> bindAndGetTerms(FunctionContext context)
|
||||||
{
|
{
|
||||||
List<ByteBuffer> buffers = values.bindAndGet(options);
|
List<ByteBuffer> buffers = values.bindAndGet(context);
|
||||||
checkFalse(buffers == null && operator.isIN(), "Invalid null list in IN condition");
|
checkFalse(buffers == null && operator.isIN(), "Invalid null list in IN condition");
|
||||||
checkFalse(buffers == Term.UNSET_LIST, "Invalid 'unset' value in condition");
|
checkFalse(buffers == Term.UNSET_LIST, "Invalid 'unset' value in condition");
|
||||||
return filterUnsetValuesIfNeeded(buffers, ByteBufferUtil.UNSET_BYTE_BUFFER);
|
return filterUnsetValuesIfNeeded(buffers, ByteBufferUtil.UNSET_BYTE_BUFFER);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import java.math.RoundingMode;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.ByteType;
|
import org.apache.cassandra.db.marshal.ByteType;
|
||||||
import org.apache.cassandra.db.marshal.BytesType;
|
import org.apache.cassandra.db.marshal.BytesType;
|
||||||
|
|
@ -35,7 +36,6 @@ import org.apache.cassandra.db.marshal.IntegerType;
|
||||||
import org.apache.cassandra.db.marshal.LongType;
|
import org.apache.cassandra.db.marshal.LongType;
|
||||||
import org.apache.cassandra.db.marshal.ShortType;
|
import org.apache.cassandra.db.marshal.ShortType;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory methods for aggregate functions.
|
* Factory methods for aggregate functions.
|
||||||
|
|
@ -119,7 +119,7 @@ public abstract class AggregateFcts
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return LongType.instance.decompose(count);
|
return LongType.instance.decompose(count);
|
||||||
}
|
}
|
||||||
|
|
@ -163,7 +163,7 @@ public abstract class AggregateFcts
|
||||||
sum = BigDecimal.ZERO;
|
sum = BigDecimal.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return ((DecimalType) returnType()).decompose(sum);
|
return ((DecimalType) returnType()).decompose(sum);
|
||||||
}
|
}
|
||||||
|
|
@ -204,7 +204,7 @@ public abstract class AggregateFcts
|
||||||
avg = BigDecimal.ZERO;
|
avg = BigDecimal.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return DecimalType.instance.decompose(avg);
|
return DecimalType.instance.decompose(avg);
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +244,7 @@ public abstract class AggregateFcts
|
||||||
sum = BigInteger.ZERO;
|
sum = BigInteger.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return ((IntegerType) returnType()).decompose(sum);
|
return ((IntegerType) returnType()).decompose(sum);
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +286,7 @@ public abstract class AggregateFcts
|
||||||
sum = BigInteger.ZERO;
|
sum = BigInteger.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return IntegerType.instance.decompose(BigInteger.ZERO);
|
return IntegerType.instance.decompose(BigInteger.ZERO);
|
||||||
|
|
@ -329,7 +329,7 @@ public abstract class AggregateFcts
|
||||||
sum = 0;
|
sum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return ((ByteType) returnType()).decompose(sum);
|
return ((ByteType) returnType()).decompose(sum);
|
||||||
}
|
}
|
||||||
|
|
@ -361,7 +361,7 @@ public abstract class AggregateFcts
|
||||||
{
|
{
|
||||||
return new AvgAggregate()
|
return new AvgAggregate()
|
||||||
{
|
{
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion) throws InvalidRequestException
|
public ByteBuffer compute(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return ByteType.instance.decompose((byte) computeInternal());
|
return ByteType.instance.decompose((byte) computeInternal());
|
||||||
}
|
}
|
||||||
|
|
@ -389,7 +389,7 @@ public abstract class AggregateFcts
|
||||||
sum = 0;
|
sum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return ((ShortType) returnType()).decompose(sum);
|
return ((ShortType) returnType()).decompose(sum);
|
||||||
}
|
}
|
||||||
|
|
@ -421,7 +421,7 @@ public abstract class AggregateFcts
|
||||||
{
|
{
|
||||||
return new AvgAggregate()
|
return new AvgAggregate()
|
||||||
{
|
{
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return ShortType.instance.decompose((short) computeInternal());
|
return ShortType.instance.decompose((short) computeInternal());
|
||||||
}
|
}
|
||||||
|
|
@ -449,7 +449,7 @@ public abstract class AggregateFcts
|
||||||
sum = 0;
|
sum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return ((Int32Type) returnType()).decompose(sum);
|
return ((Int32Type) returnType()).decompose(sum);
|
||||||
}
|
}
|
||||||
|
|
@ -481,7 +481,7 @@ public abstract class AggregateFcts
|
||||||
{
|
{
|
||||||
return new AvgAggregate()
|
return new AvgAggregate()
|
||||||
{
|
{
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return Int32Type.instance.decompose((int) computeInternal());
|
return Int32Type.instance.decompose((int) computeInternal());
|
||||||
}
|
}
|
||||||
|
|
@ -517,7 +517,7 @@ public abstract class AggregateFcts
|
||||||
{
|
{
|
||||||
return new AvgAggregate()
|
return new AvgAggregate()
|
||||||
{
|
{
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return LongType.instance.decompose(computeInternal());
|
return LongType.instance.decompose(computeInternal());
|
||||||
}
|
}
|
||||||
|
|
@ -538,7 +538,7 @@ public abstract class AggregateFcts
|
||||||
{
|
{
|
||||||
return new FloatSumAggregate()
|
return new FloatSumAggregate()
|
||||||
{
|
{
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion) throws InvalidRequestException
|
public ByteBuffer compute(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return FloatType.instance.decompose((float) computeInternal());
|
return FloatType.instance.decompose((float) computeInternal());
|
||||||
}
|
}
|
||||||
|
|
@ -558,7 +558,7 @@ public abstract class AggregateFcts
|
||||||
{
|
{
|
||||||
return new FloatAvgAggregate()
|
return new FloatAvgAggregate()
|
||||||
{
|
{
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion) throws InvalidRequestException
|
public ByteBuffer compute(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return FloatType.instance.decompose((float) computeInternal());
|
return FloatType.instance.decompose((float) computeInternal());
|
||||||
}
|
}
|
||||||
|
|
@ -579,7 +579,7 @@ public abstract class AggregateFcts
|
||||||
{
|
{
|
||||||
return new FloatSumAggregate()
|
return new FloatSumAggregate()
|
||||||
{
|
{
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion) throws InvalidRequestException
|
public ByteBuffer compute(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return DoubleType.instance.decompose(computeInternal());
|
return DoubleType.instance.decompose(computeInternal());
|
||||||
}
|
}
|
||||||
|
|
@ -730,7 +730,7 @@ public abstract class AggregateFcts
|
||||||
{
|
{
|
||||||
return new FloatAvgAggregate()
|
return new FloatAvgAggregate()
|
||||||
{
|
{
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion) throws InvalidRequestException
|
public ByteBuffer compute(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return DoubleType.instance.decompose(computeInternal());
|
return DoubleType.instance.decompose(computeInternal());
|
||||||
}
|
}
|
||||||
|
|
@ -760,7 +760,7 @@ public abstract class AggregateFcts
|
||||||
{
|
{
|
||||||
return new AvgAggregate()
|
return new AvgAggregate()
|
||||||
{
|
{
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion) throws InvalidRequestException
|
public ByteBuffer compute(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return CounterColumnType.instance.decompose(computeInternal());
|
return CounterColumnType.instance.decompose(computeInternal());
|
||||||
}
|
}
|
||||||
|
|
@ -785,7 +785,7 @@ public abstract class AggregateFcts
|
||||||
min = null;
|
min = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return min != null ? LongType.instance.decompose(min) : null;
|
return min != null ? LongType.instance.decompose(min) : null;
|
||||||
}
|
}
|
||||||
|
|
@ -824,7 +824,7 @@ public abstract class AggregateFcts
|
||||||
max = null;
|
max = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return max != null ? LongType.instance.decompose(max) : null;
|
return max != null ? LongType.instance.decompose(max) : null;
|
||||||
}
|
}
|
||||||
|
|
@ -857,9 +857,9 @@ public abstract class AggregateFcts
|
||||||
return new NativeAggregateFunction("max", inputType, inputType)
|
return new NativeAggregateFunction("max", inputType, inputType)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newNoopInstance(version, 1);
|
return FunctionArguments.newNoopInstance(context, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -874,7 +874,7 @@ public abstract class AggregateFcts
|
||||||
max = null;
|
max = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
@ -906,9 +906,9 @@ public abstract class AggregateFcts
|
||||||
return new NativeAggregateFunction("min", inputType, inputType)
|
return new NativeAggregateFunction("min", inputType, inputType)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newNoopInstance(version, 1);
|
return FunctionArguments.newNoopInstance(context, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -923,7 +923,7 @@ public abstract class AggregateFcts
|
||||||
min = null;
|
min = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
@ -955,9 +955,9 @@ public abstract class AggregateFcts
|
||||||
return new NativeAggregateFunction("count", LongType.instance, inputType)
|
return new NativeAggregateFunction("count", LongType.instance, inputType)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newNoopInstance(version, 1);
|
return FunctionArguments.newNoopInstance(context, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -972,7 +972,7 @@ public abstract class AggregateFcts
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return ((LongType) returnType()).decompose(count);
|
return ((LongType) returnType()).decompose(count);
|
||||||
}
|
}
|
||||||
|
|
@ -999,7 +999,7 @@ public abstract class AggregateFcts
|
||||||
sum = 0;
|
sum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion)
|
public ByteBuffer compute(FunctionContext context)
|
||||||
{
|
{
|
||||||
return LongType.instance.decompose(sum);
|
return LongType.instance.decompose(sum);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ package org.apache.cassandra.cql3.functions;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a calculation on a set of values and return a single value.
|
* Performs a calculation on a set of values and return a single value.
|
||||||
|
|
@ -49,10 +49,10 @@ public interface AggregateFunction extends Function
|
||||||
/**
|
/**
|
||||||
* Computes and returns the aggregate current value.
|
* Computes and returns the aggregate current value.
|
||||||
*
|
*
|
||||||
* @param protocolVersion native protocol version
|
* @param context
|
||||||
* @return the aggregate current value.
|
* @return the aggregate current value.
|
||||||
*/
|
*/
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion) throws InvalidRequestException;
|
public ByteBuffer compute(FunctionContext context) throws InvalidRequestException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset this aggregate.
|
* Reset this aggregate.
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ package org.apache.cassandra.cql3.functions;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -29,6 +30,8 @@ import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
*/
|
*/
|
||||||
public interface Arguments
|
public interface Arguments
|
||||||
{
|
{
|
||||||
|
FunctionContext context();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the specified value to the arguments
|
* Sets the specified value to the arguments
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,11 @@ package org.apache.cassandra.cql3.functions;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.BytesType;
|
import org.apache.cassandra.db.marshal.BytesType;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.serializers.MarshalException;
|
import org.apache.cassandra.serializers.MarshalException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||||
|
|
||||||
public abstract class BytesConversionFcts
|
public abstract class BytesConversionFcts
|
||||||
|
|
@ -49,9 +49,9 @@ public abstract class BytesConversionFcts
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newNoopInstance(version, 1);
|
return FunctionArguments.newNoopInstance(context, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import java.util.List;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.AsciiType;
|
import org.apache.cassandra.db.marshal.AsciiType;
|
||||||
import org.apache.cassandra.db.marshal.BooleanType;
|
import org.apache.cassandra.db.marshal.BooleanType;
|
||||||
|
|
@ -44,7 +45,6 @@ import org.apache.cassandra.db.marshal.TimeUUIDType;
|
||||||
import org.apache.cassandra.db.marshal.TimestampType;
|
import org.apache.cassandra.db.marshal.TimestampType;
|
||||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||||
import org.apache.cassandra.db.marshal.UUIDType;
|
import org.apache.cassandra.db.marshal.UUIDType;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
import static org.apache.cassandra.cql3.functions.TimeFcts.toDate;
|
import static org.apache.cassandra.cql3.functions.TimeFcts.toDate;
|
||||||
import static org.apache.cassandra.cql3.functions.TimeFcts.toTimestamp;
|
import static org.apache.cassandra.cql3.functions.TimeFcts.toTimestamp;
|
||||||
|
|
@ -388,9 +388,9 @@ public final class CastFcts
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return new FunctionArguments(version, (protocolVersion, buffer) -> {
|
return new FunctionArguments(context, (protocolVersion, buffer) -> {
|
||||||
AbstractType<?> argType = argTypes.get(0);
|
AbstractType<?> argType = argTypes.get(0);
|
||||||
if (buffer == null || (!buffer.hasRemaining() && argType.isEmptyValueMeaningless()))
|
if (buffer == null || (!buffer.hasRemaining() && argType.isEmptyValueMeaningless()))
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,13 @@ import java.util.Set;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.CollectionType;
|
import org.apache.cassandra.db.marshal.CollectionType;
|
||||||
import org.apache.cassandra.db.marshal.Int32Type;
|
import org.apache.cassandra.db.marshal.Int32Type;
|
||||||
import org.apache.cassandra.db.marshal.ListType;
|
import org.apache.cassandra.db.marshal.ListType;
|
||||||
import org.apache.cassandra.db.marshal.MapType;
|
import org.apache.cassandra.db.marshal.MapType;
|
||||||
import org.apache.cassandra.db.marshal.SetType;
|
import org.apache.cassandra.db.marshal.SetType;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Native CQL functions for collections (sets, list and maps).
|
* Native CQL functions for collections (sets, list and maps).
|
||||||
|
|
@ -179,9 +179,9 @@ public class CollectionFcts
|
||||||
return new NativeScalarFunction(name, Int32Type.instance, inputType)
|
return new NativeScalarFunction(name, Int32Type.instance, inputType)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newNoopInstance(version, 1);
|
return FunctionArguments.newNoopInstance(context, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -359,9 +359,9 @@ public class CollectionFcts
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newNoopInstance(version, 1);
|
return FunctionArguments.newNoopInstance(context, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -370,7 +370,7 @@ public class CollectionFcts
|
||||||
if (arguments.containsNulls())
|
if (arguments.containsNulls())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Arguments args = aggregateFunction.newArguments(arguments.getProtocolVersion());
|
Arguments args = aggregateFunction.newArguments(arguments.context());
|
||||||
AggregateFunction.Aggregate aggregate = aggregateFunction.newAggregate();
|
AggregateFunction.Aggregate aggregate = aggregateFunction.newAggregate();
|
||||||
|
|
||||||
inputType.forEach(arguments.get(0), element -> {
|
inputType.forEach(arguments.get(0), element -> {
|
||||||
|
|
@ -378,7 +378,7 @@ public class CollectionFcts
|
||||||
aggregate.addInput(args);
|
aggregate.addInput(args);
|
||||||
});
|
});
|
||||||
|
|
||||||
return aggregate.compute(arguments.getProtocolVersion());
|
return aggregate.compute(arguments.context());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ import java.util.Optional;
|
||||||
import org.github.jamm.Unmetered;
|
import org.github.jamm.Unmetered;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.AssignmentTestable;
|
import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.schema.Difference;
|
import org.apache.cassandra.schema.Difference;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
@Unmetered
|
@Unmetered
|
||||||
public interface Function extends AssignmentTestable
|
public interface Function extends AssignmentTestable
|
||||||
|
|
@ -77,10 +77,10 @@ public interface Function extends AssignmentTestable
|
||||||
/**
|
/**
|
||||||
* Creates some new input arguments for this function.
|
* Creates some new input arguments for this function.
|
||||||
*
|
*
|
||||||
* @param version the protocol version
|
* @param context
|
||||||
* @return some new input arguments for this function
|
* @return some new input arguments for this function
|
||||||
*/
|
*/
|
||||||
Arguments newArguments(ProtocolVersion version);
|
Arguments newArguments(FunctionContext context);
|
||||||
|
|
||||||
public default Optional<Difference> compare(Function other)
|
public default Optional<Difference> compare(Function other)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
|
|
||||||
|
|
@ -30,20 +31,14 @@ import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
*/
|
*/
|
||||||
public final class FunctionArguments implements Arguments
|
public final class FunctionArguments implements Arguments
|
||||||
{
|
{
|
||||||
/**
|
public static final ArgumentDeserializer[] NO_DESERIALIZERS = new ArgumentDeserializer[0];
|
||||||
* An empty {@link FunctionArguments} for the current protocol.
|
|
||||||
*/
|
|
||||||
private static final FunctionArguments EMPTY = new FunctionArguments(ProtocolVersion.CURRENT);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The deserializer used to deserialize the columns.
|
* The deserializer used to deserialize the columns.
|
||||||
*/
|
*/
|
||||||
private final ArgumentDeserializer[] deserializers;
|
private final ArgumentDeserializer[] deserializers;
|
||||||
|
|
||||||
/**
|
private final FunctionContext context;
|
||||||
* The protocol version.
|
|
||||||
*/
|
|
||||||
private final ProtocolVersion version;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The deserialized arguments.
|
* The deserialized arguments.
|
||||||
|
|
@ -53,93 +48,82 @@ public final class FunctionArguments implements Arguments
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link FunctionArguments} for the specified types.
|
* Creates a new {@link FunctionArguments} for the specified types.
|
||||||
*
|
*
|
||||||
* @param version the protocol version
|
|
||||||
* @param argTypes the argument types
|
* @param argTypes the argument types
|
||||||
* @return a new {@link FunctionArguments} for the specified types.
|
* @return a new {@link FunctionArguments} for the specified types.
|
||||||
*/
|
*/
|
||||||
public static FunctionArguments newInstanceForUdf(ProtocolVersion version, List<UDFDataType> argTypes)
|
public static Arguments newInstanceForUdf(FunctionContext context, List<UDFDataType> argTypes)
|
||||||
{
|
{
|
||||||
int size = argTypes.size();
|
int size = argTypes.size();
|
||||||
|
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return emptyInstance(version);
|
return context.noArguments();
|
||||||
|
|
||||||
ArgumentDeserializer[] deserializers = new ArgumentDeserializer[size];
|
ArgumentDeserializer[] deserializers = new ArgumentDeserializer[size];
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
deserializers[i] = argTypes.get(i).getArgumentDeserializer();
|
deserializers[i] = argTypes.get(i).getArgumentDeserializer();
|
||||||
|
|
||||||
return new FunctionArguments(version, deserializers);
|
return new FunctionArguments(context, deserializers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProtocolVersion getProtocolVersion()
|
public ProtocolVersion getProtocolVersion()
|
||||||
{
|
{
|
||||||
return version;
|
return context.getProtocolVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FunctionContext context()
|
||||||
|
{
|
||||||
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link FunctionArguments} that does not deserialize the arguments.
|
* Creates a new {@link FunctionArguments} that does not deserialize the arguments.
|
||||||
*
|
*
|
||||||
* @param version the protocol version
|
|
||||||
* @param numberOfArguments the number of argument
|
* @param numberOfArguments the number of argument
|
||||||
* @return a new {@link FunctionArguments} for the specified types.
|
* @return a new {@link FunctionArguments} for the specified types.
|
||||||
*/
|
*/
|
||||||
public static FunctionArguments newNoopInstance(ProtocolVersion version, int numberOfArguments)
|
public static FunctionArguments newNoopInstance(FunctionContext context, int numberOfArguments)
|
||||||
{
|
{
|
||||||
ArgumentDeserializer[] deserializers = new ArgumentDeserializer[numberOfArguments];
|
ArgumentDeserializer[] deserializers = new ArgumentDeserializer[numberOfArguments];
|
||||||
Arrays.fill(deserializers, ArgumentDeserializer.NOOP_DESERIALIZER);
|
Arrays.fill(deserializers, ArgumentDeserializer.NOOP_DESERIALIZER);
|
||||||
|
|
||||||
return new FunctionArguments(version, deserializers);
|
return new FunctionArguments(context, deserializers);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an empty {@link FunctionArguments}.
|
|
||||||
*
|
|
||||||
* @param version the protocol version
|
|
||||||
* @return an empty {@link FunctionArguments}
|
|
||||||
*/
|
|
||||||
public static FunctionArguments emptyInstance(ProtocolVersion version)
|
|
||||||
{
|
|
||||||
if (version == ProtocolVersion.CURRENT)
|
|
||||||
return EMPTY;
|
|
||||||
|
|
||||||
return new FunctionArguments(version);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link FunctionArguments} for a native function.
|
* Creates a new {@link FunctionArguments} for a native function.
|
||||||
* <p>Native functions can use different {@link ArgumentDeserializer} to avoid instanciating primitive wrappers.</p>
|
* <p>Native functions can use different {@link ArgumentDeserializer} to avoid instanciating primitive wrappers.</p>
|
||||||
*
|
*
|
||||||
* @param version the protocol version
|
|
||||||
* @param argTypes the argument types
|
* @param argTypes the argument types
|
||||||
* @return a new {@link FunctionArguments} for the specified types.
|
* @return a new {@link FunctionArguments} for the specified types.
|
||||||
*/
|
*/
|
||||||
public static FunctionArguments newInstanceForNativeFunction(ProtocolVersion version, List<AbstractType<?>> argTypes)
|
public static Arguments newInstanceForNativeFunction(FunctionContext context, List<AbstractType<?>> argTypes)
|
||||||
{
|
{
|
||||||
int size = argTypes.size();
|
int size = argTypes.size();
|
||||||
|
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return emptyInstance(version);
|
return context.noArguments();
|
||||||
|
|
||||||
ArgumentDeserializer[] deserializers = new ArgumentDeserializer[size];
|
ArgumentDeserializer[] deserializers = new ArgumentDeserializer[size];
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
deserializers[i] = argTypes.get(i).getArgumentDeserializer();
|
deserializers[i] = argTypes.get(i).getArgumentDeserializer();
|
||||||
|
|
||||||
return new FunctionArguments(version, deserializers);
|
return new FunctionArguments(context, deserializers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FunctionArguments(ProtocolVersion version, ArgumentDeserializer... deserializers)
|
public FunctionArguments(FunctionContext context, ArgumentDeserializer... deserializers)
|
||||||
{
|
{
|
||||||
this.version = version;
|
this.context = context;
|
||||||
this.deserializers = deserializers;
|
this.deserializers = deserializers;
|
||||||
this.arguments = new Object[deserializers.length];
|
this.arguments = new Object[deserializers.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(int i, ByteBuffer buffer)
|
public void set(int i, ByteBuffer buffer)
|
||||||
{
|
{
|
||||||
arguments[i] = deserializers[i].deserialize(version, buffer);
|
arguments[i] = deserializers[i].deserialize(context.getProtocolVersion(), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.CqlBuilder;
|
import org.apache.cassandra.cql3.CqlBuilder;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.statements.RequestValidations;
|
import org.apache.cassandra.cql3.statements.RequestValidations;
|
||||||
import org.apache.cassandra.cql3.terms.Constants;
|
import org.apache.cassandra.cql3.terms.Constants;
|
||||||
|
|
@ -68,19 +68,19 @@ public class FunctionCall extends Term.NonTerminal
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Term.Terminal bind(QueryOptions options) throws InvalidRequestException
|
public Term.Terminal bind(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return makeTerminal(fun, bindAndGet(options));
|
return makeTerminal(fun, bindAndGet(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer bindAndGet(QueryOptions options) throws InvalidRequestException
|
public ByteBuffer bindAndGet(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
Arguments arguments = fun.newArguments(options.getProtocolVersion());
|
Arguments arguments = fun.newArguments(context);
|
||||||
for (int i = 0, m = terms.size(); i < m; i++)
|
for (int i = 0, m = terms.size(); i < m; i++)
|
||||||
{
|
{
|
||||||
Term t = terms.get(i);
|
Term t = terms.get(i);
|
||||||
ByteBuffer argument = t.bindAndGet(options);
|
ByteBuffer argument = t.bindAndGet(context);
|
||||||
RequestValidations.checkBindValueSet(argument, "Invalid unset value for argument in call to function %s", fun.name().name);
|
RequestValidations.checkBindValueSet(argument, "Invalid unset value for argument in call to function %s", fun.name().name);
|
||||||
arguments.set(i, argument);
|
arguments.set(i, argument);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,11 @@ import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.Int32Type;
|
import org.apache.cassandra.db.marshal.Int32Type;
|
||||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -60,9 +60,9 @@ public class LengthFcts
|
||||||
{
|
{
|
||||||
// Do not deserialize
|
// Do not deserialize
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newNoopInstance(version, 1);
|
return FunctionArguments.newNoopInstance(context, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ import java.util.Arrays;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for our native/hardcoded functions.
|
* Base class for our native/hardcoded functions.
|
||||||
|
|
@ -62,9 +62,8 @@ public abstract class NativeFunction extends AbstractFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newInstanceForNativeFunction(version, argTypes);
|
return FunctionArguments.newInstanceForNativeFunction(context, argTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
/**
|
/**
|
||||||
* A partial application of a function.
|
* A partial application of a function.
|
||||||
*
|
*
|
||||||
* @see ScalarFunction#partialApplication(ProtocolVersion, List)
|
* @see ScalarFunction#partialApplication(ProtocolVersion, org.apache.cassandra.cql3.FunctionContext, List)
|
||||||
*/
|
*/
|
||||||
public interface PartialScalarFunction extends ScalarFunction
|
public interface PartialScalarFunction extends ScalarFunction
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.CqlBuilder;
|
import org.apache.cassandra.cql3.CqlBuilder;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
|
|
@ -28,7 +29,7 @@ import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
/**
|
/**
|
||||||
* An internal function used to hold the partial application of another function to only some of its parameters.
|
* An internal function used to hold the partial application of another function to only some of its parameters.
|
||||||
*
|
*
|
||||||
* @see ScalarFunction#partialApplication(ProtocolVersion, List)
|
* @see ScalarFunction#partialApplication(FunctionContext, List)
|
||||||
*/
|
*/
|
||||||
final class PartiallyAppliedScalarFunction extends NativeScalarFunction implements PartialScalarFunction
|
final class PartiallyAppliedScalarFunction extends NativeScalarFunction implements PartialScalarFunction
|
||||||
{
|
{
|
||||||
|
|
@ -63,9 +64,9 @@ final class PartiallyAppliedScalarFunction extends NativeScalarFunction implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return new PartialFunctionArguments(version, function, partialParameters, argTypes.size());
|
return new PartialFunctionArguments(context, function, partialParameters, argTypes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -126,9 +127,9 @@ final class PartiallyAppliedScalarFunction extends NativeScalarFunction implemen
|
||||||
*/
|
*/
|
||||||
private final int[] mapping;
|
private final int[] mapping;
|
||||||
|
|
||||||
public PartialFunctionArguments(ProtocolVersion version, ScalarFunction function, List<ByteBuffer> partialArguments, int unresolvedCount)
|
public PartialFunctionArguments(FunctionContext context, ScalarFunction function, List<ByteBuffer> partialArguments, int unresolvedCount)
|
||||||
{
|
{
|
||||||
arguments = function.newArguments(version);
|
arguments = function.newArguments(context);
|
||||||
mapping = new int[unresolvedCount];
|
mapping = new int[unresolvedCount];
|
||||||
int mappingIndex = 0;
|
int mappingIndex = 0;
|
||||||
for (int i = 0, m = partialArguments.size(); i < m; i++)
|
for (int i = 0, m = partialArguments.size(); i < m; i++)
|
||||||
|
|
@ -151,6 +152,12 @@ final class PartiallyAppliedScalarFunction extends NativeScalarFunction implemen
|
||||||
return arguments.getProtocolVersion();
|
return arguments.getProtocolVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FunctionContext context()
|
||||||
|
{
|
||||||
|
return arguments.context();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void set(int i, ByteBuffer buffer)
|
public void set(int i, ByteBuffer buffer)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ package org.apache.cassandra.cql3.functions;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
|
|
@ -27,7 +28,7 @@ import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
/**
|
/**
|
||||||
* Function used internally to hold the pre-computed result of another function.
|
* Function used internally to hold the pre-computed result of another function.
|
||||||
* <p>
|
* <p>
|
||||||
* See {@link ScalarFunction#partialApplication(ProtocolVersion, List)} for why this is used.
|
* See {@link ScalarFunction#partialApplication(ProtocolVersion, FunctionContext, List)} for why this is used.
|
||||||
* <p>
|
* <p>
|
||||||
* Note : the function is cautious in keeping the protocol version used for the pre-computed value and to
|
* Note : the function is cautious in keeping the protocol version used for the pre-computed value and to
|
||||||
* fallback to recomputation if the version we get when {@link #execute} is called. I don't think it's truly necessary
|
* fallback to recomputation if the version we get when {@link #execute} is called. I don't think it's truly necessary
|
||||||
|
|
@ -74,7 +75,7 @@ class PreComputedScalarFunction extends NativeScalarFunction implements PartialS
|
||||||
if (nothing.getProtocolVersion() == valueVersion)
|
if (nothing.getProtocolVersion() == valueVersion)
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
Arguments args = function.newArguments(nothing.getProtocolVersion());
|
Arguments args = function.newArguments(nothing.context());
|
||||||
for (int i = 0, m = arguments.size() ; i < m; i++)
|
for (int i = 0, m = arguments.size() ; i < m; i++)
|
||||||
{
|
{
|
||||||
args.set(i, arguments.get(i));;
|
args.set(i, arguments.get(i));;
|
||||||
|
|
@ -83,7 +84,7 @@ class PreComputedScalarFunction extends NativeScalarFunction implements PartialS
|
||||||
return function.execute(args);
|
return function.execute(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScalarFunction partialApplication(ProtocolVersion protocolVersion, List<ByteBuffer> nothing) throws InvalidRequestException
|
public ScalarFunction partialApplication(ProtocolVersion protocolVersion, FunctionContext context, List<ByteBuffer> nothing) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ public interface ScalarFunction extends Function
|
||||||
* </pre>
|
* </pre>
|
||||||
* and such that for any value of {@code b} and {@code d}, {@code bar(b, d) == foo(3, b, 'bar', d)}.
|
* and such that for any value of {@code b} and {@code d}, {@code bar(b, d) == foo(3, b, 'bar', d)}.
|
||||||
*
|
*
|
||||||
* @param protocolVersion protocol version used for arguments
|
* @param protocolVersion protocol version used for arguments
|
||||||
* @param partialArguments a list of input arguments for the function where some arguments can be {@link #UNRESOLVED}.
|
* @param partialArguments a list of input arguments for the function where some arguments can be {@link #UNRESOLVED}.
|
||||||
* The input <b>must</b> be of size {@code this.argsType().size()}. For convenience, it is
|
* The input <b>must</b> be of size {@code this.argsType().size()}. For convenience, it is
|
||||||
* allowed both to pass a list with all arguments being {@link #UNRESOLVED} (the function is
|
* allowed both to pass a list with all arguments being {@link #UNRESOLVED} (the function is
|
||||||
|
|
@ -88,6 +88,7 @@ public interface ScalarFunction extends Function
|
||||||
|
|
||||||
if (isPure() && unresolvedCount == 0)
|
if (isPure() && unresolvedCount == 0)
|
||||||
{
|
{
|
||||||
|
// if isPure(), requires no FunctionContext
|
||||||
Arguments arguments = newArguments(protocolVersion);
|
Arguments arguments = newArguments(protocolVersion);
|
||||||
for (int i = 0, m = partialArguments.size(); i < m; i++)
|
for (int i = 0, m = partialArguments.size(); i < m; i++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ public abstract class TimeFcts
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer execute(Arguments arguments)
|
public ByteBuffer execute(Arguments arguments)
|
||||||
{
|
{
|
||||||
return type.now();
|
return type.now(arguments.context());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,10 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||||
|
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
|
|
@ -55,9 +55,9 @@ public class ToJsonFct extends NativeScalarFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return new FunctionArguments(version, (protocolVersion, buffer) -> {
|
return new FunctionArguments(context, (protocolVersion, buffer) -> {
|
||||||
AbstractType<?> argType = argTypes.get(0);
|
AbstractType<?> argType = argTypes.get(0);
|
||||||
|
|
||||||
if (buffer == null || (!buffer.hasRemaining() && argType.isEmptyValueMeaningless()))
|
if (buffer == null || (!buffer.hasRemaining() && argType.isEmptyValueMeaningless()))
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,13 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.AssignmentTestable;
|
import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.CBuilder;
|
import org.apache.cassandra.db.CBuilder;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.schema.ColumnMetadata;
|
import org.apache.cassandra.schema.ColumnMetadata;
|
||||||
import org.apache.cassandra.schema.Schema;
|
import org.apache.cassandra.schema.Schema;
|
||||||
import org.apache.cassandra.schema.TableMetadata;
|
import org.apache.cassandra.schema.TableMetadata;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
public class TokenFct extends NativeScalarFunction
|
public class TokenFct extends NativeScalarFunction
|
||||||
{
|
{
|
||||||
|
|
@ -41,11 +41,11 @@ public class TokenFct extends NativeScalarFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
ArgumentDeserializer[] deserializers = new ArgumentDeserializer[argTypes.size()];
|
ArgumentDeserializer[] deserializers = new ArgumentDeserializer[argTypes.size()];
|
||||||
Arrays.fill(deserializers, ArgumentDeserializer.NOOP_DESERIALIZER);
|
Arrays.fill(deserializers, ArgumentDeserializer.NOOP_DESERIALIZER);
|
||||||
return new FunctionArguments(version, deserializers);
|
return new FunctionArguments(context, deserializers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AbstractType<?>[] getKeyTypes(TableMetadata metadata)
|
private static AbstractType<?>[] getKeyTypes(TableMetadata metadata)
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.CqlBuilder;
|
import org.apache.cassandra.cql3.CqlBuilder;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.UserType;
|
import org.apache.cassandra.db.marshal.UserType;
|
||||||
import org.apache.cassandra.exceptions.ConfigurationException;
|
import org.apache.cassandra.exceptions.ConfigurationException;
|
||||||
|
|
@ -120,9 +121,9 @@ public class UDAggregate extends UserFunction implements AggregateFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newInstanceForUdf(version, argumentTypes);
|
return FunctionArguments.newInstanceForUdf(context, argumentTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasReferenceTo(Function function)
|
public boolean hasReferenceTo(Function function)
|
||||||
|
|
@ -230,8 +231,9 @@ public class UDAggregate extends UserFunction implements AggregateFunction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer compute(ProtocolVersion protocolVersion) throws InvalidRequestException
|
public ByteBuffer compute(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
|
ProtocolVersion protocolVersion = context.getProtocolVersion();
|
||||||
maybeInit(protocolVersion);
|
maybeInit(protocolVersion);
|
||||||
|
|
||||||
// final function is traced in UDFunction
|
// final function is traced in UDFunction
|
||||||
|
|
@ -242,7 +244,7 @@ public class UDAggregate extends UserFunction implements AggregateFunction
|
||||||
if (finalFunction instanceof UDFunction)
|
if (finalFunction instanceof UDFunction)
|
||||||
{
|
{
|
||||||
UDFunction udf = (UDFunction)finalFunction;
|
UDFunction udf = (UDFunction)finalFunction;
|
||||||
Object result = udf.executeForAggregate(state, FunctionArguments.emptyInstance(protocolVersion));
|
Object result = udf.executeForAggregate(state, context.noArguments());
|
||||||
return resultType.decompose(protocolVersion, result);
|
return resultType.decompose(protocolVersion, result);
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException("UDAs only support UDFs");
|
throw new UnsupportedOperationException("UDAs only support UDFs");
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ import org.apache.cassandra.config.Config;
|
||||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.CqlBuilder;
|
import org.apache.cassandra.cql3.CqlBuilder;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.types.TypeCodec;
|
import org.apache.cassandra.cql3.functions.types.TypeCodec;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.UserType;
|
import org.apache.cassandra.db.marshal.UserType;
|
||||||
|
|
@ -232,9 +233,9 @@ public abstract class UDFunction extends UserFunction implements ScalarFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newInstanceForUdf(version, argumentTypes);
|
return FunctionArguments.newInstanceForUdf(context, argumentTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UDFunction tryCreate(FunctionName name,
|
public static UDFunction tryCreate(FunctionName name,
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.FloatType;
|
import org.apache.cassandra.db.marshal.FloatType;
|
||||||
import org.apache.cassandra.db.marshal.VectorType;
|
import org.apache.cassandra.db.marshal.VectorType;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
import io.github.jbellis.jvector.vector.VectorSimilarityFunction;
|
import io.github.jbellis.jvector.vector.VectorSimilarityFunction;
|
||||||
|
|
||||||
|
|
@ -69,9 +69,9 @@ public class VectorFcts
|
||||||
return new NativeScalarFunction(name, FloatType.instance, type, type)
|
return new NativeScalarFunction(name, FloatType.instance, type, type)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return new FunctionArguments(version,
|
return new FunctionArguments(context,
|
||||||
(v, b) -> type.composeAsFloat(b),
|
(v, b) -> type.composeAsFloat(b),
|
||||||
(v, b) -> type.composeAsFloat(b));
|
(v, b) -> type.composeAsFloat(b));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.CqlBuilder;
|
import org.apache.cassandra.cql3.CqlBuilder;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.Arguments;
|
import org.apache.cassandra.cql3.functions.Arguments;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.cql3.functions.FunctionName;
|
import org.apache.cassandra.cql3.functions.FunctionName;
|
||||||
|
|
@ -135,20 +136,28 @@ public class ColumnMask
|
||||||
* @param version the used version of the transport protocol
|
* @param version the used version of the transport protocol
|
||||||
* @return a masker instance that caches the terminal masking function arguments
|
* @return a masker instance that caches the terminal masking function arguments
|
||||||
*/
|
*/
|
||||||
public Masker masker(ProtocolVersion version)
|
public Masker masker(ProtocolVersion version, FunctionContext context)
|
||||||
{
|
{
|
||||||
return new Masker(version, function, partialArgumentValues);
|
return new Masker(version, context, function, partialArgumentValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Masker
|
public static class Masker
|
||||||
{
|
{
|
||||||
|
public static final Masker NOT_A_MASKER = new Masker();
|
||||||
|
|
||||||
private final ScalarFunction function;
|
private final ScalarFunction function;
|
||||||
private final Arguments arguments;
|
private final Arguments arguments;
|
||||||
|
|
||||||
private Masker(ProtocolVersion version, ScalarFunction function, ByteBuffer[] partialArgumentValues)
|
private Masker()
|
||||||
|
{
|
||||||
|
function = null;
|
||||||
|
arguments = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Masker(ProtocolVersion version, FunctionContext context, ScalarFunction function, ByteBuffer[] partialArgumentValues)
|
||||||
{
|
{
|
||||||
this.function = function;
|
this.function = function;
|
||||||
arguments = function.newArguments(version);
|
arguments = function.newArguments(context);
|
||||||
for (int i = 0; i < partialArgumentValues.length; i++)
|
for (int i = 0; i < partialArgumentValues.length; i++)
|
||||||
arguments.set(i + 1, partialArgumentValues[i]);
|
arguments.set(i + 1, partialArgumentValues[i]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ package org.apache.cassandra.cql3.functions.masking;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.Arguments;
|
import org.apache.cassandra.cql3.functions.Arguments;
|
||||||
import org.apache.cassandra.cql3.functions.FunctionArguments;
|
import org.apache.cassandra.cql3.functions.FunctionArguments;
|
||||||
import org.apache.cassandra.cql3.functions.FunctionFactory;
|
import org.apache.cassandra.cql3.functions.FunctionFactory;
|
||||||
|
|
@ -29,7 +30,6 @@ import org.apache.cassandra.cql3.functions.FunctionParameter;
|
||||||
import org.apache.cassandra.cql3.functions.NativeFunction;
|
import org.apache.cassandra.cql3.functions.NativeFunction;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link MaskingFunction} that returns a fixed replacement value for the data type of its single argument.
|
* A {@link MaskingFunction} that returns a fixed replacement value for the data type of its single argument.
|
||||||
|
|
@ -53,9 +53,9 @@ public class DefaultMaskingFunction extends MaskingFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newNoopInstance(version, 1);
|
return FunctionArguments.newNoopInstance(context, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import javax.annotation.Nullable;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.ArgumentDeserializer;
|
import org.apache.cassandra.cql3.functions.ArgumentDeserializer;
|
||||||
import org.apache.cassandra.cql3.functions.Arguments;
|
import org.apache.cassandra.cql3.functions.Arguments;
|
||||||
import org.apache.cassandra.cql3.functions.FunctionArguments;
|
import org.apache.cassandra.cql3.functions.FunctionArguments;
|
||||||
|
|
@ -41,7 +42,6 @@ import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.BytesType;
|
import org.apache.cassandra.db.marshal.BytesType;
|
||||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -71,9 +71,9 @@ public class HashMaskingFunction extends MaskingFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return new FunctionArguments(version,
|
return new FunctionArguments(context,
|
||||||
ArgumentDeserializer.NOOP_DESERIALIZER, // the value to be masked
|
ArgumentDeserializer.NOOP_DESERIALIZER, // the value to be masked
|
||||||
(v, b) -> messageDigest(b)); // the algorithm, if any
|
(v, b) -> messageDigest(b)); // the algorithm, if any
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ package org.apache.cassandra.cql3.functions.masking;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.Arguments;
|
import org.apache.cassandra.cql3.functions.Arguments;
|
||||||
import org.apache.cassandra.cql3.functions.FunctionArguments;
|
import org.apache.cassandra.cql3.functions.FunctionArguments;
|
||||||
import org.apache.cassandra.cql3.functions.FunctionFactory;
|
import org.apache.cassandra.cql3.functions.FunctionFactory;
|
||||||
|
|
@ -29,7 +30,6 @@ import org.apache.cassandra.cql3.functions.FunctionParameter;
|
||||||
import org.apache.cassandra.cql3.functions.NativeFunction;
|
import org.apache.cassandra.cql3.functions.NativeFunction;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link MaskingFunction} that always returns a {@code null} column. The returned value is always an absent column,
|
* A {@link MaskingFunction} that always returns a {@code null} column. The returned value is always an absent column,
|
||||||
|
|
@ -48,9 +48,9 @@ public class NullMaskingFunction extends MaskingFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newNoopInstance(version, 1);
|
return FunctionArguments.newNoopInstance(context, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import com.google.common.annotations.VisibleForTesting;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.ArgumentDeserializer;
|
import org.apache.cassandra.cql3.functions.ArgumentDeserializer;
|
||||||
import org.apache.cassandra.cql3.functions.Arguments;
|
import org.apache.cassandra.cql3.functions.Arguments;
|
||||||
import org.apache.cassandra.cql3.functions.FunctionArguments;
|
import org.apache.cassandra.cql3.functions.FunctionArguments;
|
||||||
|
|
@ -40,7 +41,6 @@ import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.Int32Type;
|
import org.apache.cassandra.db.marshal.Int32Type;
|
||||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
|
|
||||||
|
|
@ -106,9 +106,9 @@ public class PartialMaskingFunction extends MaskingFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return new FunctionArguments(version,
|
return new FunctionArguments(context,
|
||||||
inputType.getArgumentDeserializer(),
|
inputType.getArgumentDeserializer(),
|
||||||
Int32Type.instance.getArgumentDeserializer(),
|
Int32Type.instance.getArgumentDeserializer(),
|
||||||
Int32Type.instance.getArgumentDeserializer(),
|
Int32Type.instance.getArgumentDeserializer(),
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ package org.apache.cassandra.cql3.functions.masking;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.Arguments;
|
import org.apache.cassandra.cql3.functions.Arguments;
|
||||||
import org.apache.cassandra.cql3.functions.FunctionArguments;
|
import org.apache.cassandra.cql3.functions.FunctionArguments;
|
||||||
import org.apache.cassandra.cql3.functions.FunctionFactory;
|
import org.apache.cassandra.cql3.functions.FunctionFactory;
|
||||||
|
|
@ -29,7 +30,6 @@ import org.apache.cassandra.cql3.functions.FunctionParameter;
|
||||||
import org.apache.cassandra.cql3.functions.NativeFunction;
|
import org.apache.cassandra.cql3.functions.NativeFunction;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link MaskingFunction} that replaces the specified column value by a certain replacement value.
|
* A {@link MaskingFunction} that replaces the specified column value by a certain replacement value.
|
||||||
|
|
@ -48,9 +48,9 @@ public class ReplaceMaskingFunction extends MaskingFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Arguments newArguments(ProtocolVersion version)
|
public Arguments newArguments(FunctionContext context)
|
||||||
{
|
{
|
||||||
return FunctionArguments.newNoopInstance(version, 2);
|
return FunctionArguments.newNoopInstance(context, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.RangeSet;
|
import com.google.common.collect.RangeSet;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.db.Clustering;
|
import org.apache.cassandra.db.Clustering;
|
||||||
import org.apache.cassandra.db.ClusteringComparator;
|
import org.apache.cassandra.db.ClusteringComparator;
|
||||||
|
|
@ -199,7 +200,7 @@ final class ClusteringColumnRestrictions extends RestrictionSetWrapper
|
||||||
@Override
|
@Override
|
||||||
public void addToRowFilter(RowFilter filter,
|
public void addToRowFilter(RowFilter filter,
|
||||||
IndexRegistry indexRegistry,
|
IndexRegistry indexRegistry,
|
||||||
QueryOptions options,
|
FunctionContext context,
|
||||||
IndexHints indexHints) throws InvalidRequestException
|
IndexHints indexHints) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
int position = 0;
|
int position = 0;
|
||||||
|
|
@ -209,7 +210,7 @@ final class ClusteringColumnRestrictions extends RestrictionSetWrapper
|
||||||
// We ignore all the clustering columns that can be handled by slices.
|
// We ignore all the clustering columns that can be handled by slices.
|
||||||
if (handleInFilter(restriction, position) || restriction.hasSupportingIndex(indexRegistry, indexHints))
|
if (handleInFilter(restriction, position) || restriction.hasSupportingIndex(indexRegistry, indexHints))
|
||||||
{
|
{
|
||||||
restriction.addToRowFilter(filter, indexRegistry, options, indexHints);
|
restriction.addToRowFilter(filter, indexRegistry, context, indexHints);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ import java.util.Set;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.RangeSet;
|
import com.google.common.collect.RangeSet;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.Operator;
|
import org.apache.cassandra.cql3.Operator;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
|
||||||
import org.apache.cassandra.cql3.Relation;
|
import org.apache.cassandra.cql3.Relation;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.db.filter.IndexHints;
|
import org.apache.cassandra.db.filter.IndexHints;
|
||||||
|
|
@ -332,31 +332,31 @@ public final class MergedRestriction implements SingleRestriction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClusteringElements> values(QueryOptions options)
|
public List<ClusteringElements> values(FunctionContext context)
|
||||||
{
|
{
|
||||||
List<ClusteringElements> values = restrictions.get(0).values(options);
|
List<ClusteringElements> values = restrictions.get(0).values(context);
|
||||||
for (int i = 1, m = restrictions.size(); i < m; i++)
|
for (int i = 1, m = restrictions.size(); i < m; i++)
|
||||||
{
|
{
|
||||||
values.retainAll(restrictions.get(i).values(options));
|
values.retainAll(restrictions.get(i).values(context));
|
||||||
}
|
}
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restrict(RangeSet<ClusteringElements> rangeSet, QueryOptions options, IPartitioner partitioner)
|
public void restrict(RangeSet<ClusteringElements> rangeSet, FunctionContext context, IPartitioner partitioner)
|
||||||
{
|
{
|
||||||
for (int i = 0, m = restrictions.size(); i < m; i++)
|
for (int i = 0, m = restrictions.size(); i < m; i++)
|
||||||
{
|
{
|
||||||
restrictions.get(i).restrict(rangeSet, options, partitioner);
|
restrictions.get(i).restrict(rangeSet, context, partitioner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addToRowFilter(RowFilter filter, IndexRegistry indexRegistry, QueryOptions options, IndexHints indexHints)
|
public void addToRowFilter(RowFilter filter, IndexRegistry indexRegistry, FunctionContext context, IndexHints indexHints)
|
||||||
{
|
{
|
||||||
for (int i = 0, m = restrictions.size(); i < m; i++)
|
for (int i = 0, m = restrictions.size(); i < m; i++)
|
||||||
{
|
{
|
||||||
restrictions.get(i).addToRowFilter(filter, indexRegistry, options, indexHints);
|
restrictions.get(i).addToRowFilter(filter, indexRegistry, context, indexHints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ package org.apache.cassandra.cql3.restrictions;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.db.filter.IndexHints;
|
import org.apache.cassandra.db.filter.IndexHints;
|
||||||
import org.apache.cassandra.db.filter.RowFilter;
|
import org.apache.cassandra.db.filter.RowFilter;
|
||||||
|
|
@ -109,12 +109,12 @@ public interface Restriction
|
||||||
/**
|
/**
|
||||||
* Adds to the specified row filter the expressions corresponding to this <code>Restriction</code>.
|
* Adds to the specified row filter the expressions corresponding to this <code>Restriction</code>.
|
||||||
*
|
*
|
||||||
* @param filter the row filter to add expressions to
|
* @param filter the row filter to add expressions to
|
||||||
* @param indexRegistry the index registry
|
* @param indexRegistry the index registry
|
||||||
* @param options the query options
|
* @param context the query options
|
||||||
*/
|
*/
|
||||||
void addToRowFilter(RowFilter filter,
|
void addToRowFilter(RowFilter filter,
|
||||||
IndexRegistry indexRegistry,
|
IndexRegistry indexRegistry,
|
||||||
QueryOptions options,
|
FunctionContext context,
|
||||||
IndexHints indexHints);
|
IndexHints indexHints);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ import com.google.common.collect.AbstractIterator;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.db.filter.IndexHints;
|
import org.apache.cassandra.db.filter.IndexHints;
|
||||||
import org.apache.cassandra.db.filter.RowFilter;
|
import org.apache.cassandra.db.filter.RowFilter;
|
||||||
|
|
@ -113,10 +113,10 @@ final class RestrictionSet implements Restrictions, Iterable<SingleRestriction>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addToRowFilter(RowFilter filter, IndexRegistry indexRegistry, QueryOptions options, IndexHints indexHints) throws InvalidRequestException
|
public void addToRowFilter(RowFilter filter, IndexRegistry indexRegistry, FunctionContext context, IndexHints indexHints) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
for (Restriction restriction : this)
|
for (Restriction restriction : this)
|
||||||
restriction.addToRowFilter(filter, indexRegistry, options, indexHints);
|
restriction.addToRowFilter(filter, indexRegistry, context, indexHints);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import java.util.List;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.db.filter.IndexHints;
|
import org.apache.cassandra.db.filter.IndexHints;
|
||||||
import org.apache.cassandra.db.filter.RowFilter;
|
import org.apache.cassandra.db.filter.RowFilter;
|
||||||
|
|
@ -48,10 +48,10 @@ class RestrictionSetWrapper implements Restrictions
|
||||||
|
|
||||||
public void addToRowFilter(RowFilter filter,
|
public void addToRowFilter(RowFilter filter,
|
||||||
IndexRegistry indexRegistry,
|
IndexRegistry indexRegistry,
|
||||||
QueryOptions options,
|
FunctionContext context,
|
||||||
IndexHints indexHints)
|
IndexHints indexHints)
|
||||||
{
|
{
|
||||||
restrictions.addToRowFilter(filter, indexRegistry, options, indexHints);
|
restrictions.addToRowFilter(filter, indexRegistry, context, indexHints);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ColumnMetadata> columns()
|
public List<ColumnMetadata> columns()
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ import java.util.stream.Collectors;
|
||||||
import com.google.common.collect.RangeSet;
|
import com.google.common.collect.RangeSet;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.ColumnsExpression;
|
import org.apache.cassandra.cql3.ColumnsExpression;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.Operator;
|
import org.apache.cassandra.cql3.Operator;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
|
||||||
import org.apache.cassandra.cql3.Relation;
|
import org.apache.cassandra.cql3.Relation;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.cql3.terms.Term;
|
import org.apache.cassandra.cql3.terms.Term;
|
||||||
|
|
@ -248,44 +248,44 @@ public final class SimpleRestriction implements SingleRestriction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClusteringElements> values(QueryOptions options)
|
public List<ClusteringElements> values(FunctionContext context)
|
||||||
{
|
{
|
||||||
assert operator == Operator.EQ ||
|
assert operator == Operator.EQ ||
|
||||||
operator == Operator.IN ||
|
operator == Operator.IN ||
|
||||||
operator == Operator.ANN : String.format("Unexpected operator: %s", operator);
|
operator == Operator.ANN : String.format("Unexpected operator: %s", operator);
|
||||||
return bindAndGetClusteringElements(options);
|
return bindAndGetClusteringElements(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restrict(RangeSet<ClusteringElements> rangeSet, QueryOptions options, IPartitioner partitioner)
|
public void restrict(RangeSet<ClusteringElements> rangeSet, FunctionContext context, IPartitioner partitioner)
|
||||||
{
|
{
|
||||||
assert operator.isSlice() || operator == Operator.EQ;
|
assert operator.isSlice() || operator == Operator.EQ;
|
||||||
operator.restrict(rangeSet, bindAndGetClusteringElements(options), partitioner);
|
operator.restrict(rangeSet, bindAndGetClusteringElements(context), partitioner);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ClusteringElements> bindAndGetClusteringElements(QueryOptions options)
|
private List<ClusteringElements> bindAndGetClusteringElements(FunctionContext context)
|
||||||
{
|
{
|
||||||
switch (columnsExpression.kind())
|
switch (columnsExpression.kind())
|
||||||
{
|
{
|
||||||
case SINGLE_COLUMN:
|
case SINGLE_COLUMN:
|
||||||
case TOKEN:
|
case TOKEN:
|
||||||
return bindAndGetSingleTermClusteringElements(options);
|
return bindAndGetSingleTermClusteringElements(context);
|
||||||
case MULTI_COLUMN:
|
case MULTI_COLUMN:
|
||||||
return bindAndGetMultiTermClusteringElements(options);
|
return bindAndGetMultiTermClusteringElements(context);
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ClusteringElements> bindAndGetSingleTermClusteringElements(QueryOptions options)
|
private List<ClusteringElements> bindAndGetSingleTermClusteringElements(FunctionContext context)
|
||||||
{
|
{
|
||||||
if (values.isSingleTerm(options))
|
if (values.isSingleTerm(context))
|
||||||
{
|
{
|
||||||
ByteBuffer value = bindAndGetSingle(options);
|
ByteBuffer value = bindAndGetSingle(context);
|
||||||
return Collections.singletonList(ClusteringElements.of(columnsExpression.columnSpecification(), value, isOnToken()));
|
return Collections.singletonList(ClusteringElements.of(columnsExpression.columnSpecification(), value, isOnToken()));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ByteBuffer> values = bindAndGet(options);
|
List<ByteBuffer> values = bindAndGet(context);
|
||||||
if (values.isEmpty())
|
if (values.isEmpty())
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|
||||||
|
|
@ -301,9 +301,9 @@ public final class SimpleRestriction implements SingleRestriction
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ClusteringElements> bindAndGetMultiTermClusteringElements(QueryOptions options)
|
private List<ClusteringElements> bindAndGetMultiTermClusteringElements(FunctionContext context)
|
||||||
{
|
{
|
||||||
List<List<ByteBuffer>> values = bindAndGetElements(options);
|
List<List<ByteBuffer>> values = bindAndGetElements(context);
|
||||||
if (values.isEmpty())
|
if (values.isEmpty())
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|
||||||
|
|
@ -313,24 +313,24 @@ public final class SimpleRestriction implements SingleRestriction
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ByteBuffer> bindAndGet(QueryOptions options)
|
private List<ByteBuffer> bindAndGet(FunctionContext context)
|
||||||
{
|
{
|
||||||
List<ByteBuffer> buffers = values.bindAndGet(options);
|
List<ByteBuffer> buffers = values.bindAndGet(context);
|
||||||
validate(buffers);
|
validate(buffers);
|
||||||
buffers.forEach(this::validate);
|
buffers.forEach(this::validate);
|
||||||
return buffers;
|
return buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ByteBuffer bindAndGetSingle(QueryOptions options)
|
private ByteBuffer bindAndGetSingle(FunctionContext context)
|
||||||
{
|
{
|
||||||
ByteBuffer buffer = values.bindAndGetSingleTermValue(options);
|
ByteBuffer buffer = values.bindAndGetSingleTermValue(context);
|
||||||
validate(buffer);
|
validate(buffer);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<List<ByteBuffer>> bindAndGetElements(QueryOptions options)
|
private List<List<ByteBuffer>> bindAndGetElements(FunctionContext context)
|
||||||
{
|
{
|
||||||
List<List<ByteBuffer>> elementsList = values.bindAndGetElements(options);
|
List<List<ByteBuffer>> elementsList = values.bindAndGetElements(context);
|
||||||
validate(elementsList);
|
validate(elementsList);
|
||||||
elementsList.forEach(this::validateElements);
|
elementsList.forEach(this::validateElements);
|
||||||
return elementsList;
|
return elementsList;
|
||||||
|
|
@ -371,7 +371,7 @@ public final class SimpleRestriction implements SingleRestriction
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addToRowFilter(RowFilter filter, IndexRegistry indexRegistry, QueryOptions options, IndexHints indexHints)
|
public void addToRowFilter(RowFilter filter, IndexRegistry indexRegistry, FunctionContext context, IndexHints indexHints)
|
||||||
{
|
{
|
||||||
if (isOnToken())
|
if (isOnToken())
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|
@ -380,7 +380,7 @@ public final class SimpleRestriction implements SingleRestriction
|
||||||
switch (columnsExpression.kind())
|
switch (columnsExpression.kind())
|
||||||
{
|
{
|
||||||
case SINGLE_COLUMN:
|
case SINGLE_COLUMN:
|
||||||
List<ByteBuffer> buffers = bindAndGet(options);
|
List<ByteBuffer> buffers = bindAndGet(context);
|
||||||
if (operator.kind() != Operator.Kind.BINARY)
|
if (operator.kind() != Operator.Kind.BINARY)
|
||||||
{
|
{
|
||||||
if (operator == Operator.IN && !column.type.isCounter())
|
if (operator == Operator.IN && !column.type.isCounter())
|
||||||
|
|
@ -406,7 +406,7 @@ public final class SimpleRestriction implements SingleRestriction
|
||||||
|
|
||||||
if (isEQ())
|
if (isEQ())
|
||||||
{
|
{
|
||||||
List<ByteBuffer> elements = bindAndGetElements(options).get(0);
|
List<ByteBuffer> elements = bindAndGetElements(context).get(0);
|
||||||
|
|
||||||
for (int i = 0, m = columns().size(); i < m; i++)
|
for (int i = 0, m = columns().size(); i < m; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -420,7 +420,7 @@ public final class SimpleRestriction implements SingleRestriction
|
||||||
// c IN (x, y, z) and we can perform filtering
|
// c IN (x, y, z) and we can perform filtering
|
||||||
if (columns().size() == 1)
|
if (columns().size() == 1)
|
||||||
{
|
{
|
||||||
List<ByteBuffer> values = bindAndGetElements(options).stream()
|
List<ByteBuffer> values = bindAndGetElements(context).stream()
|
||||||
.map(elements -> elements.get(0))
|
.map(elements -> elements.get(0))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
|
@ -451,12 +451,12 @@ public final class SimpleRestriction implements SingleRestriction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer key = columnsExpression.element(options);
|
ByteBuffer key = columnsExpression.element(context);
|
||||||
if (key == null)
|
if (key == null)
|
||||||
throw invalidRequest("Invalid null map key for column %s", column.name.toCQLString());
|
throw invalidRequest("Invalid null map key for column %s", column.name.toCQLString());
|
||||||
if (key == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
if (key == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
||||||
throw invalidRequest("Invalid unset map key for column %s", column.name.toCQLString());
|
throw invalidRequest("Invalid unset map key for column %s", column.name.toCQLString());
|
||||||
List<ByteBuffer> values = bindAndGet(options);
|
List<ByteBuffer> values = bindAndGet(context);
|
||||||
filter.addMapEquality(column, key, operator, values.get(0));
|
filter.addMapEquality(column, key, operator, values.get(0));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import java.util.List;
|
||||||
|
|
||||||
import com.google.common.collect.RangeSet;
|
import com.google.common.collect.RangeSet;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.dht.IPartitioner;
|
import org.apache.cassandra.dht.IPartitioner;
|
||||||
import org.apache.cassandra.index.Index;
|
import org.apache.cassandra.index.Index;
|
||||||
|
|
||||||
|
|
@ -93,19 +93,19 @@ public interface SingleRestriction extends Restriction
|
||||||
/**
|
/**
|
||||||
* Returns the values selected by this restriction (or by the intersection of merged restrictions) if the operator is an {@code EQ} or an {@code IN}.
|
* Returns the values selected by this restriction (or by the intersection of merged restrictions) if the operator is an {@code EQ} or an {@code IN}.
|
||||||
*
|
*
|
||||||
* @param options the query options
|
* @param context the query options
|
||||||
* @return the values selected by this restriction (or by the intersection of merged restrictions) if the operator is an {@code EQ} or an {@code IN}.
|
* @return the values selected by this restriction (or by the intersection of merged restrictions) if the operator is an {@code EQ} or an {@code IN}.
|
||||||
* @throws UnsupportedOperationException if the operator is not an {@code EQ} or an {@code IN}.
|
* @throws UnsupportedOperationException if the operator is not an {@code EQ} or an {@code IN}.
|
||||||
*/
|
*/
|
||||||
List<ClusteringElements> values(QueryOptions options);
|
List<ClusteringElements> values(FunctionContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the ranges of values not selected by this restriction from the specified {@code RangeSet} if the operator is an operator selecting ranges of data.
|
* Removes the ranges of values not selected by this restriction from the specified {@code RangeSet} if the operator is an operator selecting ranges of data.
|
||||||
*
|
*
|
||||||
* @param rangeSet the range set to add to
|
* @param rangeSet the range set to add to
|
||||||
* @param options the query options
|
* @param context the query options
|
||||||
* @param partitioner the partitioner, used to identify MIN_TOKEN when using token restrictions
|
* @param partitioner the partitioner, used to identify MIN_TOKEN when using token restrictions
|
||||||
* @throws UnsupportedOperationException if the operator is not an operator selecting ranges of data.
|
* @throws UnsupportedOperationException if the operator is not an operator selecting ranges of data.
|
||||||
*/
|
*/
|
||||||
void restrict(RangeSet<ClusteringElements> rangeSet, QueryOptions options, IPartitioner partitioner);
|
void restrict(RangeSet<ClusteringElements> rangeSet, FunctionContext context, IPartitioner partitioner);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import com.google.common.collect.Iterables;
|
||||||
import org.apache.commons.lang3.text.StrBuilder;
|
import org.apache.commons.lang3.text.StrBuilder;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.functions.Arguments;
|
import org.apache.cassandra.cql3.functions.Arguments;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
|
|
@ -133,9 +134,17 @@ abstract class AbstractFunctionSelector<T extends Function> extends Selector
|
||||||
* The list used to pass the function arguments is recycled to avoid the cost of instantiating a new list
|
* The list used to pass the function arguments is recycled to avoid the cost of instantiating a new list
|
||||||
* with each function call.
|
* with each function call.
|
||||||
*/
|
*/
|
||||||
private final Arguments args;
|
private Arguments args;
|
||||||
protected final List<Selector> argSelectors;
|
protected final List<Selector> argSelectors;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
args = fun.newArguments(context);
|
||||||
|
for (Selector selector : argSelectors)
|
||||||
|
selector.prepare(context);
|
||||||
|
}
|
||||||
|
|
||||||
public static Factory newFactory(final Function fun, final SelectorFactories factories) throws InvalidRequestException
|
public static Factory newFactory(final Function fun, final SelectorFactories factories) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
if (fun.isAggregate())
|
if (fun.isAggregate())
|
||||||
|
|
@ -179,7 +188,7 @@ abstract class AbstractFunctionSelector<T extends Function> extends Selector
|
||||||
|
|
||||||
public Selector newInstance(QueryOptions options) throws InvalidRequestException
|
public Selector newInstance(QueryOptions options) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return fun.isAggregate() ? new AggregateFunctionSelector(options.getProtocolVersion(), fun, factories.newInstances(options))
|
return fun.isAggregate() ? new AggregateFunctionSelector(fun, factories.newInstances(options))
|
||||||
: createScalarSelector(options, (ScalarFunction) fun, factories.newInstances(options));
|
: createScalarSelector(options, (ScalarFunction) fun, factories.newInstances(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,7 +213,7 @@ abstract class AbstractFunctionSelector<T extends Function> extends Selector
|
||||||
}
|
}
|
||||||
|
|
||||||
if (terminalCount == 0)
|
if (terminalCount == 0)
|
||||||
return new ScalarFunctionSelector(version, fun, argSelectors);
|
return new ScalarFunctionSelector(fun, argSelectors);
|
||||||
|
|
||||||
// We have some terminal arguments, do a partial application
|
// We have some terminal arguments, do a partial application
|
||||||
ScalarFunction partialFunction = function.partialApplication(version, terminalArgs);
|
ScalarFunction partialFunction = function.partialApplication(version, terminalArgs);
|
||||||
|
|
@ -212,6 +221,7 @@ abstract class AbstractFunctionSelector<T extends Function> extends Selector
|
||||||
// If all the arguments are terminal and the function is pure we can reduce to a simple value.
|
// If all the arguments are terminal and the function is pure we can reduce to a simple value.
|
||||||
if (terminalCount == argSelectors.size() && fun.isPure())
|
if (terminalCount == argSelectors.size() && fun.isPure())
|
||||||
{
|
{
|
||||||
|
// pure functions need no context
|
||||||
Arguments arguments = partialFunction.newArguments(version);
|
Arguments arguments = partialFunction.newArguments(version);
|
||||||
return new TermSelector(partialFunction.execute(arguments), partialFunction.returnType());
|
return new TermSelector(partialFunction.execute(arguments), partialFunction.returnType());
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +232,7 @@ abstract class AbstractFunctionSelector<T extends Function> extends Selector
|
||||||
if (!selector.isTerminal())
|
if (!selector.isTerminal())
|
||||||
remainingSelectors.add(selector);
|
remainingSelectors.add(selector);
|
||||||
}
|
}
|
||||||
return new ScalarFunctionSelector(version, partialFunction, remainingSelectors);
|
return new ScalarFunctionSelector(partialFunction, remainingSelectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWritetimeSelectorFactory()
|
public boolean isWritetimeSelectorFactory()
|
||||||
|
|
@ -255,12 +265,11 @@ abstract class AbstractFunctionSelector<T extends Function> extends Selector
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractFunctionSelector(Kind kind, ProtocolVersion version, T fun, List<Selector> argSelectors)
|
protected AbstractFunctionSelector(Kind kind, T fun, List<Selector> argSelectors)
|
||||||
{
|
{
|
||||||
super(kind);
|
super(kind);
|
||||||
this.fun = fun;
|
this.fun = fun;
|
||||||
this.argSelectors = argSelectors;
|
this.argSelectors = argSelectors;
|
||||||
this.args = fun.newArguments(version);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ package org.apache.cassandra.cql3.selection;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.AggregateFunction;
|
import org.apache.cassandra.cql3.functions.AggregateFunction;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
|
|
@ -32,10 +33,11 @@ final class AggregateFunctionSelector extends AbstractFunctionSelector<Aggregate
|
||||||
@Override
|
@Override
|
||||||
protected Selector newFunctionSelector(ProtocolVersion version, Function function, List<Selector> argSelectors)
|
protected Selector newFunctionSelector(ProtocolVersion version, Function function, List<Selector> argSelectors)
|
||||||
{
|
{
|
||||||
return new AggregateFunctionSelector(version, function, argSelectors);
|
return new AggregateFunctionSelector(function, argSelectors);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private FunctionContext context;
|
||||||
private final AggregateFunction.Aggregate aggregate;
|
private final AggregateFunction.Aggregate aggregate;
|
||||||
|
|
||||||
public boolean isAggregate()
|
public boolean isAggregate()
|
||||||
|
|
@ -43,6 +45,13 @@ final class AggregateFunctionSelector extends AbstractFunctionSelector<Aggregate
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
super.prepare(context);
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
public void addInput(InputRow input)
|
public void addInput(InputRow input)
|
||||||
{
|
{
|
||||||
ProtocolVersion protocolVersion = input.getProtocolVersion();
|
ProtocolVersion protocolVersion = input.getProtocolVersion();
|
||||||
|
|
@ -60,7 +69,7 @@ final class AggregateFunctionSelector extends AbstractFunctionSelector<Aggregate
|
||||||
|
|
||||||
public ByteBuffer getOutput(ProtocolVersion protocolVersion) throws InvalidRequestException
|
public ByteBuffer getOutput(ProtocolVersion protocolVersion) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return aggregate.compute(protocolVersion);
|
return aggregate.compute(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset()
|
public void reset()
|
||||||
|
|
@ -68,9 +77,9 @@ final class AggregateFunctionSelector extends AbstractFunctionSelector<Aggregate
|
||||||
aggregate.reset();
|
aggregate.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
AggregateFunctionSelector(ProtocolVersion version, Function fun, List<Selector> argSelectors) throws InvalidRequestException
|
AggregateFunctionSelector(Function fun, List<Selector> argSelectors) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
super(Kind.AGGREGATE_FUNCTION_SELECTOR, version, (AggregateFunction) fun, argSelectors);
|
super(Kind.AGGREGATE_FUNCTION_SELECTOR, (AggregateFunction) fun, argSelectors);
|
||||||
|
|
||||||
this.aggregate = this.fun.newAggregate();
|
this.aggregate = this.fun.newAggregate();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import com.google.common.base.Objects;
|
||||||
import com.google.common.collect.Range;
|
import com.google.common.collect.Range;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.selection.SimpleSelector.SimpleSelectorFactory;
|
import org.apache.cassandra.cql3.selection.SimpleSelector.SimpleSelectorFactory;
|
||||||
import org.apache.cassandra.cql3.terms.Term;
|
import org.apache.cassandra.cql3.terms.Term;
|
||||||
|
|
@ -63,6 +64,13 @@ abstract class ElementsSelector extends Selector
|
||||||
this.type = getCollectionType(selected);
|
this.type = getCollectionType(selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
super.prepare(context);
|
||||||
|
selected.prepare(context);
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean isUnset(ByteBuffer bb)
|
private static boolean isUnset(ByteBuffer bb)
|
||||||
{
|
{
|
||||||
return bb == ByteBufferUtil.UNSET_BYTE_BUFFER;
|
return bb == ByteBufferUtil.UNSET_BYTE_BUFFER;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.db.TypeSizes;
|
import org.apache.cassandra.db.TypeSizes;
|
||||||
import org.apache.cassandra.db.filter.ColumnFilter;
|
import org.apache.cassandra.db.filter.ColumnFilter;
|
||||||
|
|
@ -159,6 +160,13 @@ final class FieldSelector extends Selector
|
||||||
this.selected = selected;
|
this.selected = selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
super.prepare(context);
|
||||||
|
selected.prepare(context);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.terms.Lists;
|
import org.apache.cassandra.cql3.terms.Lists;
|
||||||
import org.apache.cassandra.db.TypeSizes;
|
import org.apache.cassandra.db.TypeSizes;
|
||||||
|
|
@ -139,6 +140,14 @@ final class ListSelector extends Selector
|
||||||
this.elements = elements;
|
this.elements = elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
super.prepare(context);
|
||||||
|
for (Selector selector : elements)
|
||||||
|
selector.prepare(context);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import java.util.stream.Collectors;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.cql3.terms.Maps;
|
import org.apache.cassandra.cql3.terms.Maps;
|
||||||
|
|
@ -259,7 +260,17 @@ final class MapSelector extends Selector
|
||||||
this.type = (MapType<?, ?>) type;
|
this.type = (MapType<?, ?>) type;
|
||||||
this.elements = elements;
|
this.elements = elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
super.prepare(context);
|
||||||
|
for (Pair<Selector, Selector> selector : elements)
|
||||||
|
{
|
||||||
|
selector.left.prepare(context);
|
||||||
|
selector.right.prepare(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.ResultSet;
|
import org.apache.cassandra.cql3.ResultSet;
|
||||||
import org.apache.cassandra.cql3.ResultSet.ResultMetadata;
|
import org.apache.cassandra.cql3.ResultSet.ResultMetadata;
|
||||||
import org.apache.cassandra.cql3.selection.Selection.Selectors;
|
import org.apache.cassandra.cql3.selection.Selection.Selectors;
|
||||||
|
|
@ -60,17 +61,18 @@ public final class ResultSetBuilder
|
||||||
private long size = 0;
|
private long size = 0;
|
||||||
private boolean sizeWarningEmitted = false;
|
private boolean sizeWarningEmitted = false;
|
||||||
|
|
||||||
public ResultSetBuilder(ResultMetadata metadata, Selectors selectors, boolean unmask)
|
public ResultSetBuilder(ResultMetadata metadata, FunctionContext context, Selectors selectors, boolean unmask)
|
||||||
{
|
{
|
||||||
this(metadata, selectors, unmask, null);
|
this(metadata, context, selectors, unmask, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultSetBuilder(ResultMetadata metadata, Selectors selectors, boolean unmask, GroupMaker groupMaker)
|
public ResultSetBuilder(ResultMetadata metadata, FunctionContext context, Selectors selectors, boolean unmask, GroupMaker groupMaker)
|
||||||
{
|
{
|
||||||
this.resultSet = new ResultSet(metadata.copy(), new ArrayList<>());
|
this.resultSet = new ResultSet(metadata.copy(), new ArrayList<>());
|
||||||
this.selectors = selectors;
|
this.selectors = selectors;
|
||||||
this.groupMaker = groupMaker;
|
this.groupMaker = groupMaker;
|
||||||
this.unmask = unmask;
|
this.unmask = unmask;
|
||||||
|
selectors.prepare(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSize(List<ByteBuffer> row)
|
private void addSize(List<ByteBuffer> row)
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ final class ScalarFunctionSelector extends AbstractFunctionSelector<ScalarFuncti
|
||||||
@Override
|
@Override
|
||||||
protected Selector newFunctionSelector(ProtocolVersion version, Function function, List<Selector> argSelectors)
|
protected Selector newFunctionSelector(ProtocolVersion version, Function function, List<Selector> argSelectors)
|
||||||
{
|
{
|
||||||
return new ScalarFunctionSelector(version, function, argSelectors);
|
return new ScalarFunctionSelector(function, argSelectors);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -69,8 +69,8 @@ final class ScalarFunctionSelector extends AbstractFunctionSelector<ScalarFuncti
|
||||||
argSelectors.get(i).validateForGroupBy();
|
argSelectors.get(i).validateForGroupBy();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScalarFunctionSelector(ProtocolVersion version, Function fun, List<Selector> argSelectors)
|
ScalarFunctionSelector(Function fun, List<Selector> argSelectors)
|
||||||
{
|
{
|
||||||
super(Kind.SCALAR_FUNCTION_SELECTOR, version, (ScalarFunction) fun, argSelectors);
|
super(Kind.SCALAR_FUNCTION_SELECTOR, (ScalarFunction) fun, argSelectors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import com.google.common.collect.Iterators;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.Json;
|
import org.apache.cassandra.cql3.Json;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.ResultSet;
|
import org.apache.cassandra.cql3.ResultSet;
|
||||||
|
|
@ -393,6 +394,8 @@ public abstract class Selection
|
||||||
*/
|
*/
|
||||||
default boolean collectWritetimes() { return false; }
|
default boolean collectWritetimes() { return false; }
|
||||||
|
|
||||||
|
default void prepare(FunctionContext context) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the current row of the specified <code>ResultSetBuilder</code>.
|
* Adds the current row of the specified <code>ResultSetBuilder</code>.
|
||||||
*
|
*
|
||||||
|
|
@ -601,6 +604,13 @@ public abstract class Selection
|
||||||
return isJson ? rowToJson(outputRow, options.getProtocolVersion(), metadata, orderingColumns) : outputRow;
|
return isJson ? rowToJson(outputRow, options.getProtocolVersion(), metadata, orderingColumns) : outputRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
for (Selector selector : selectors)
|
||||||
|
selector.prepare(context);
|
||||||
|
}
|
||||||
|
|
||||||
public void addInputRow(InputRow input)
|
public void addInputRow(InputRow input)
|
||||||
{
|
{
|
||||||
for (Selector selector : selectors)
|
for (Selector selector : selectors)
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.cql3.selection.ColumnTimestamps.TimestampsType;
|
import org.apache.cassandra.cql3.selection.ColumnTimestamps.TimestampsType;
|
||||||
|
|
@ -562,6 +563,8 @@ public abstract class Selector
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void prepare(FunctionContext context) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that this selector is valid for GROUP BY clause.
|
* Checks that this selector is valid for GROUP BY clause.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import java.util.TreeSet;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.terms.Sets;
|
import org.apache.cassandra.cql3.terms.Sets;
|
||||||
import org.apache.cassandra.db.TypeSizes;
|
import org.apache.cassandra.db.TypeSizes;
|
||||||
|
|
@ -141,6 +142,14 @@ final class SetSelector extends Selector
|
||||||
this.elements = elements;
|
this.elements = elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
super.prepare(context);
|
||||||
|
for (Selector selector : elements)
|
||||||
|
selector.prepare(context);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import com.google.common.base.Objects;
|
||||||
|
|
||||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.functions.masking.ColumnMask;
|
import org.apache.cassandra.cql3.functions.masking.ColumnMask;
|
||||||
import org.apache.cassandra.db.TypeSizes;
|
import org.apache.cassandra.db.TypeSizes;
|
||||||
|
|
@ -38,6 +39,8 @@ import org.apache.cassandra.schema.TableMetadata;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||||
|
|
||||||
|
import static org.apache.cassandra.cql3.functions.masking.ColumnMask.Masker.NOT_A_MASKER;
|
||||||
|
|
||||||
public final class SimpleSelector extends Selector
|
public final class SimpleSelector extends Selector
|
||||||
{
|
{
|
||||||
protected static final SelectorDeserializer deserializer = new SelectorDeserializer()
|
protected static final SelectorDeserializer deserializer = new SelectorDeserializer()
|
||||||
|
|
@ -47,7 +50,7 @@ public final class SimpleSelector extends Selector
|
||||||
ByteBuffer columnName = ByteBufferUtil.readWithVIntLength(in);
|
ByteBuffer columnName = ByteBufferUtil.readWithVIntLength(in);
|
||||||
ColumnMetadata column = metadata.getColumn(columnName);
|
ColumnMetadata column = metadata.getColumn(columnName);
|
||||||
int idx = in.readInt();
|
int idx = in.readInt();
|
||||||
return new SimpleSelector(column, idx, false, ProtocolVersion.CURRENT);
|
return new SimpleSelector(column, idx, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -87,7 +90,7 @@ public final class SimpleSelector extends Selector
|
||||||
@Override
|
@Override
|
||||||
public Selector newInstance(QueryOptions options)
|
public Selector newInstance(QueryOptions options)
|
||||||
{
|
{
|
||||||
return new SimpleSelector(column, idx, useForPostOrdering, options.getProtocolVersion());
|
return new SimpleSelector(column, idx, useForPostOrdering);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -120,7 +123,7 @@ public final class SimpleSelector extends Selector
|
||||||
|
|
||||||
public final ColumnMetadata column;
|
public final ColumnMetadata column;
|
||||||
private final int idx;
|
private final int idx;
|
||||||
private final ColumnMask.Masker masker;
|
private ColumnMask.Masker masker;
|
||||||
private ByteBuffer current;
|
private ByteBuffer current;
|
||||||
private ColumnTimestamps writetimes;
|
private ColumnTimestamps writetimes;
|
||||||
private ColumnTimestamps ttls;
|
private ColumnTimestamps ttls;
|
||||||
|
|
@ -197,7 +200,7 @@ public final class SimpleSelector extends Selector
|
||||||
return column.name.toString();
|
return column.name.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SimpleSelector(ColumnMetadata column, int idx, boolean useForPostOrdering, ProtocolVersion version)
|
private SimpleSelector(ColumnMetadata column, int idx, boolean useForPostOrdering)
|
||||||
{
|
{
|
||||||
super(Kind.SIMPLE_SELECTOR);
|
super(Kind.SIMPLE_SELECTOR);
|
||||||
this.column = column;
|
this.column = column;
|
||||||
|
|
@ -207,9 +210,13 @@ public final class SimpleSelector extends Selector
|
||||||
- The column doesn't have a mask
|
- The column doesn't have a mask
|
||||||
- This selector is for a query with ORDER BY post-ordering
|
- This selector is for a query with ORDER BY post-ordering
|
||||||
*/
|
*/
|
||||||
this.masker = useForPostOrdering || column.getMask() == null
|
this.masker = useForPostOrdering || column.getMask() == null ? null : NOT_A_MASKER;
|
||||||
? null
|
}
|
||||||
: column.getMask().masker(version);
|
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
if (masker != null)
|
||||||
|
masker = column.getMask().masker(context.options().getProtocolVersion(), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.terms.Tuples;
|
import org.apache.cassandra.cql3.terms.Tuples;
|
||||||
import org.apache.cassandra.db.TypeSizes;
|
import org.apache.cassandra.db.TypeSizes;
|
||||||
|
|
@ -140,6 +141,14 @@ final class TupleSelector extends Selector
|
||||||
this.elements = elements;
|
this.elements = elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
super.prepare(context);
|
||||||
|
for (Selector selector : elements)
|
||||||
|
selector.prepare(context);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import com.google.common.base.Objects;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.FieldIdentifier;
|
import org.apache.cassandra.cql3.FieldIdentifier;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.cql3.terms.UserTypes;
|
import org.apache.cassandra.cql3.terms.UserTypes;
|
||||||
|
|
@ -235,6 +236,14 @@ final class UserTypeSelector extends Selector
|
||||||
this.fields = fields;
|
this.fields = fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
super.prepare(context);
|
||||||
|
for (Selector selector : fields.values())
|
||||||
|
selector.prepare(context);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import java.util.Objects;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.terms.Lists;
|
import org.apache.cassandra.cql3.terms.Lists;
|
||||||
import org.apache.cassandra.db.filter.ColumnFilter;
|
import org.apache.cassandra.db.filter.ColumnFilter;
|
||||||
|
|
@ -74,6 +75,14 @@ public class VectorSelector extends Selector
|
||||||
this.elements = elements;
|
this.elements = elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
super.prepare(context);
|
||||||
|
for (Selector selector : elements)
|
||||||
|
selector.prepare(context);
|
||||||
|
}
|
||||||
|
|
||||||
public static Factory newFactory(final AbstractType<?> type, final SelectorFactories factories)
|
public static Factory newFactory(final AbstractType<?> type, final SelectorFactories factories)
|
||||||
{
|
{
|
||||||
assert type.isVector() : String.format("Unable to create vector selector from typs %s", type.asCQL3Type());
|
assert type.isVector() : String.format("Unable to create vector selector from typs %s", type.asCQL3Type());
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.db.TypeSizes;
|
import org.apache.cassandra.db.TypeSizes;
|
||||||
import org.apache.cassandra.db.filter.ColumnFilter;
|
import org.apache.cassandra.db.filter.ColumnFilter;
|
||||||
|
|
@ -179,6 +180,13 @@ final class WritetimeOrTTLSelector extends Selector
|
||||||
this.isMultiCell = isMultiCell;
|
this.isMultiCell = isMultiCell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepare(FunctionContext context)
|
||||||
|
{
|
||||||
|
super.prepare(context);
|
||||||
|
selected.prepare(context);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,11 @@ import accord.api.Update;
|
||||||
import accord.primitives.Keys;
|
import accord.primitives.Keys;
|
||||||
import accord.primitives.Txn;
|
import accord.primitives.Txn;
|
||||||
|
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext.PartialFunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.UpdateParameters;
|
import org.apache.cassandra.cql3.RowUpdateBuilder;
|
||||||
|
import org.apache.cassandra.cql3.RowUpdateBuilder.NoTimeRowUpdateBuilder;
|
||||||
import org.apache.cassandra.cql3.conditions.ColumnCondition;
|
import org.apache.cassandra.cql3.conditions.ColumnCondition;
|
||||||
import org.apache.cassandra.db.Clustering;
|
import org.apache.cassandra.db.Clustering;
|
||||||
import org.apache.cassandra.db.Columns;
|
import org.apache.cassandra.db.Columns;
|
||||||
|
|
@ -309,12 +312,12 @@ public class CQL3CasRequest implements CASRequest
|
||||||
return partitionUpdate;
|
return partitionUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CASUpdateParameters extends UpdateParameters
|
private static class CASUpdateBuilder extends RowUpdateBuilder implements PartialFunctionContext
|
||||||
{
|
{
|
||||||
final long timeUuidMsb;
|
final long timeUuidMsb;
|
||||||
long timeUuidNanos;
|
long timeUuidNanos;
|
||||||
|
|
||||||
public CASUpdateParameters(TableMetadata metadata, ClientState state, QueryOptions options, long timestamp, long nowInSec, int ttl, Map<DecoratedKey, Partition> prefetchedRows, long timeUuidMsb, long timeUuidNanos) throws InvalidRequestException
|
public CASUpdateBuilder(TableMetadata metadata, ClientState state, QueryOptions options, long timestamp, long nowInSec, int ttl, Map<DecoratedKey, Partition> prefetchedRows, long timeUuidMsb, long timeUuidNanos) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
super(metadata, state, options, timestamp, nowInSec, ttl, prefetchedRows);
|
super(metadata, state, options, timestamp, nowInSec, ttl, prefetchedRows);
|
||||||
this.timeUuidMsb = timeUuidMsb;
|
this.timeUuidMsb = timeUuidMsb;
|
||||||
|
|
@ -325,6 +328,11 @@ public class CQL3CasRequest implements CASRequest
|
||||||
{
|
{
|
||||||
return TimeUUID.toBytes(timeUuidMsb, TimeUUIDType.signedBytesToNativeLong(timeUuidNanos++));
|
return TimeUUID.toBytes(timeUuidMsb, TimeUUIDType.signedBytesToNativeLong(timeUuidNanos++));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long nowMicros()
|
||||||
|
{
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -353,8 +361,8 @@ public class CQL3CasRequest implements CASRequest
|
||||||
long applyUpdates(FilteredPartition current, PartitionUpdate.Builder updateBuilder, ClientState state, long timeUuidMsb, long timeUuidNanos)
|
long applyUpdates(FilteredPartition current, PartitionUpdate.Builder updateBuilder, ClientState state, long timeUuidMsb, long timeUuidNanos)
|
||||||
{
|
{
|
||||||
Map<DecoratedKey, Partition> map = stmt.requiresRead() ? Collections.singletonMap(key, current) : null;
|
Map<DecoratedKey, Partition> map = stmt.requiresRead() ? Collections.singletonMap(key, current) : null;
|
||||||
CASUpdateParameters params =
|
CASUpdateBuilder params =
|
||||||
new CASUpdateParameters(metadata, state, options, timestamp, nowInSeconds,
|
new CASUpdateBuilder(metadata, state, options, timestamp, nowInSeconds,
|
||||||
stmt.getTimeToLive(options), map, timeUuidMsb, timeUuidNanos);
|
stmt.getTimeToLive(options), map, timeUuidMsb, timeUuidNanos);
|
||||||
stmt.addUpdateForKey(updateBuilder, clustering, params);
|
stmt.addUpdateForKey(updateBuilder, clustering, params);
|
||||||
return params.timeUuidNanos;
|
return params.timeUuidNanos;
|
||||||
|
|
@ -382,14 +390,14 @@ public class CQL3CasRequest implements CASRequest
|
||||||
{
|
{
|
||||||
// No slice statements currently require a read, but this maintains consistency with RowUpdate, and future proofs us
|
// No slice statements currently require a read, but this maintains consistency with RowUpdate, and future proofs us
|
||||||
Map<DecoratedKey, Partition> map = stmt.requiresRead() ? Collections.singletonMap(key, current) : null;
|
Map<DecoratedKey, Partition> map = stmt.requiresRead() ? Collections.singletonMap(key, current) : null;
|
||||||
UpdateParameters params =
|
RowUpdateBuilder params =
|
||||||
new UpdateParameters(metadata,
|
new NoTimeRowUpdateBuilder(metadata,
|
||||||
state,
|
state,
|
||||||
options,
|
options,
|
||||||
timestamp,
|
timestamp,
|
||||||
nowInSeconds,
|
nowInSeconds,
|
||||||
stmt.getTimeToLive(options),
|
stmt.getTimeToLive(options),
|
||||||
map);
|
map);
|
||||||
stmt.addUpdateForKey(updateBuilder, slice, params);
|
stmt.addUpdateForKey(updateBuilder, slice, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -472,11 +480,11 @@ public class CQL3CasRequest implements CASRequest
|
||||||
super(clustering);
|
super(clustering);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addConditions(Collection<ColumnCondition> conds, QueryOptions options) throws InvalidRequestException
|
public void addConditions(Collection<ColumnCondition> conds, FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
for (ColumnCondition condition : conds)
|
for (ColumnCondition condition : conds)
|
||||||
{
|
{
|
||||||
conditions.add(condition.bind(options));
|
conditions.add(condition.bind(context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ import org.apache.cassandra.cql3.Attributes;
|
||||||
import org.apache.cassandra.cql3.Operation;
|
import org.apache.cassandra.cql3.Operation;
|
||||||
import org.apache.cassandra.cql3.Operations;
|
import org.apache.cassandra.cql3.Operations;
|
||||||
import org.apache.cassandra.cql3.QualifiedName;
|
import org.apache.cassandra.cql3.QualifiedName;
|
||||||
|
import org.apache.cassandra.cql3.RowUpdateBuilder;
|
||||||
import org.apache.cassandra.cql3.StatementSource;
|
import org.apache.cassandra.cql3.StatementSource;
|
||||||
import org.apache.cassandra.cql3.UpdateParameters;
|
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.WhereClause;
|
import org.apache.cassandra.cql3.WhereClause;
|
||||||
import org.apache.cassandra.cql3.conditions.ColumnCondition;
|
import org.apache.cassandra.cql3.conditions.ColumnCondition;
|
||||||
|
|
@ -69,7 +69,7 @@ public class DeleteStatement extends ModificationStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addUpdateForKey(PartitionUpdate.Builder updateBuilder, Clustering<?> clustering, UpdateParameters params)
|
public void addUpdateForKey(PartitionUpdate.Builder updateBuilder, Clustering<?> clustering, RowUpdateBuilder params)
|
||||||
throws InvalidRequestException
|
throws InvalidRequestException
|
||||||
{
|
{
|
||||||
TableMetadata metadata = metadata();
|
TableMetadata metadata = metadata();
|
||||||
|
|
@ -125,7 +125,7 @@ public class DeleteStatement extends ModificationStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addUpdateForKey(PartitionUpdate.Builder update, Slice slice, UpdateParameters params)
|
public void addUpdateForKey(PartitionUpdate.Builder update, Slice slice, RowUpdateBuilder params)
|
||||||
{
|
{
|
||||||
List<Operation> regularDeletions = getRegularOperations();
|
List<Operation> regularDeletions = getRegularOperations();
|
||||||
List<Operation> staticDeletions = getStaticOperations();
|
List<Operation> staticDeletions = getStaticOperations();
|
||||||
|
|
|
||||||
|
|
@ -48,14 +48,16 @@ import org.apache.cassandra.cql3.Attributes;
|
||||||
import org.apache.cassandra.cql3.CQLStatement;
|
import org.apache.cassandra.cql3.CQLStatement;
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.Operation;
|
import org.apache.cassandra.cql3.Operation;
|
||||||
import org.apache.cassandra.cql3.Operations;
|
import org.apache.cassandra.cql3.Operations;
|
||||||
import org.apache.cassandra.cql3.QualifiedName;
|
import org.apache.cassandra.cql3.QualifiedName;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.QueryProcessor;
|
import org.apache.cassandra.cql3.QueryProcessor;
|
||||||
import org.apache.cassandra.cql3.ResultSet;
|
import org.apache.cassandra.cql3.ResultSet;
|
||||||
|
import org.apache.cassandra.cql3.RowUpdateBuilder;
|
||||||
|
import org.apache.cassandra.cql3.RowUpdateBuilder.RegularRowUpdateBuilder;
|
||||||
import org.apache.cassandra.cql3.StatementSource;
|
import org.apache.cassandra.cql3.StatementSource;
|
||||||
import org.apache.cassandra.cql3.UpdateParameters;
|
|
||||||
import org.apache.cassandra.cql3.Validation;
|
import org.apache.cassandra.cql3.Validation;
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.WhereClause;
|
import org.apache.cassandra.cql3.WhereClause;
|
||||||
|
|
@ -330,9 +332,9 @@ public abstract class ModificationStatement implements CQLStatement.SingleKeyspa
|
||||||
return restrictions;
|
return restrictions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void addUpdateForKey(PartitionUpdate.Builder updateBuilder, Clustering<?> clustering, UpdateParameters params);
|
public abstract void addUpdateForKey(PartitionUpdate.Builder updateBuilder, Clustering<?> clustering, RowUpdateBuilder builder);
|
||||||
|
|
||||||
public abstract void addUpdateForKey(PartitionUpdate.Builder updateBuilder, Slice slice, UpdateParameters params);
|
public abstract void addUpdateForKey(PartitionUpdate.Builder updateBuilder, Slice slice, RowUpdateBuilder builder);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String keyspace()
|
public String keyspace()
|
||||||
|
|
@ -360,9 +362,9 @@ public abstract class ModificationStatement implements CQLStatement.SingleKeyspa
|
||||||
return metadata().isVirtual();
|
return metadata().isVirtual();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTimestamp(long now, QueryOptions options) throws InvalidRequestException
|
public long getTimestamp(long now, FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return attrs.getTimestamp(now, options);
|
return attrs.getTimestamp(now, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTimestampSet()
|
public boolean isTimestampSet()
|
||||||
|
|
@ -370,9 +372,9 @@ public abstract class ModificationStatement implements CQLStatement.SingleKeyspa
|
||||||
return attrs.isTimestampSet();
|
return attrs.isTimestampSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTimeToLive(QueryOptions options) throws InvalidRequestException
|
public int getTimeToLive(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
return attrs.getTimeToLive(options, metadata);
|
return attrs.getTimeToLive(context, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -454,12 +456,12 @@ public abstract class ModificationStatement implements CQLStatement.SingleKeyspa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateTimestamp(QueryState queryState, QueryOptions options)
|
public void validateTimestamp(QueryState queryState, FunctionContext context)
|
||||||
{
|
{
|
||||||
if (!isTimestampSet())
|
if (!isTimestampSet())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
long ts = attrs.getTimestamp(options.getTimestamp(queryState), options);
|
long ts = attrs.getTimestamp(context.options().getTimestamp(queryState), context);
|
||||||
Guardrails.maximumAllowableTimestamp.guard(ts, table(), false, queryState.getClientState());
|
Guardrails.maximumAllowableTimestamp.guard(ts, table(), false, queryState.getClientState());
|
||||||
Guardrails.minimumAllowableTimestamp.guard(ts, table(), false, queryState.getClientState());
|
Guardrails.minimumAllowableTimestamp.guard(ts, table(), false, queryState.getClientState());
|
||||||
}
|
}
|
||||||
|
|
@ -784,13 +786,13 @@ public abstract class ModificationStatement implements CQLStatement.SingleKeyspa
|
||||||
|
|
||||||
assert left.size() == 1;
|
assert left.size() == 1;
|
||||||
int size = left.metadata.names.size() + right.metadata.names.size();
|
int size = left.metadata.names.size() + right.metadata.names.size();
|
||||||
List<ColumnSpecification> specs = new ArrayList<ColumnSpecification>(size);
|
List<ColumnSpecification> specs = new ArrayList<>(size);
|
||||||
specs.addAll(left.metadata.names);
|
specs.addAll(left.metadata.names);
|
||||||
specs.addAll(right.metadata.names);
|
specs.addAll(right.metadata.names);
|
||||||
List<List<ByteBuffer>> rows = new ArrayList<>(right.size());
|
List<List<ByteBuffer>> rows = new ArrayList<>(right.size());
|
||||||
for (int i = 0; i < right.size(); i++)
|
for (int i = 0; i < right.size(); i++)
|
||||||
{
|
{
|
||||||
List<ByteBuffer> row = new ArrayList<ByteBuffer>(size);
|
List<ByteBuffer> row = new ArrayList<>(size);
|
||||||
row.addAll(left.rows.get(0));
|
row.addAll(left.rows.get(0));
|
||||||
row.addAll(right.rows.get(i));
|
row.addAll(right.rows.get(i));
|
||||||
rows.add(row);
|
rows.add(row);
|
||||||
|
|
@ -821,11 +823,10 @@ public abstract class ModificationStatement implements CQLStatement.SingleKeyspa
|
||||||
Iterables.addAll(defs, metadata.primaryKeyColumns());
|
Iterables.addAll(defs, metadata.primaryKeyColumns());
|
||||||
Iterables.addAll(defs, columnsWithConditions);
|
Iterables.addAll(defs, columnsWithConditions);
|
||||||
selection = Selection.forColumns(metadata, new ArrayList<>(defs), false);
|
selection = Selection.forColumns(metadata, new ArrayList<>(defs), false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Selectors selectors = selection.newSelectors(options);
|
Selectors selectors = selection.newSelectors(options);
|
||||||
ResultSetBuilder builder = new ResultSetBuilder(selection.getResultMetadata(), selectors, false);
|
ResultSetBuilder builder = new ResultSetBuilder(selection.getResultMetadata(), options, selectors, false);
|
||||||
SelectStatement.forSelection(metadata, selection)
|
SelectStatement.forSelection(metadata, selection)
|
||||||
.processPartition(partition, options, builder, nowInSeconds);
|
.processPartition(partition, options, builder, nowInSeconds);
|
||||||
|
|
||||||
|
|
@ -1087,7 +1088,7 @@ public abstract class ModificationStatement implements CQLStatement.SingleKeyspa
|
||||||
if (slices.isEmpty())
|
if (slices.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateParameters params = makeUpdateParameters(keys,
|
RowUpdateBuilder params = makeUpdateParameters(keys,
|
||||||
(slicesToFilter) -> new ClusteringIndexSliceFilter(slicesToFilter, false),
|
(slicesToFilter) -> new ClusteringIndexSliceFilter(slicesToFilter, false),
|
||||||
slices,
|
slices,
|
||||||
state,
|
state,
|
||||||
|
|
@ -1120,7 +1121,7 @@ public abstract class ModificationStatement implements CQLStatement.SingleKeyspa
|
||||||
if (restrictions.hasClusteringColumnsRestrictions() && clusterings.isEmpty())
|
if (restrictions.hasClusteringColumnsRestrictions() && clusterings.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateParameters params = makeUpdateParameters(keys, clusterings, state, options, local, timestamp, nowInSeconds, requestTime);
|
RowUpdateBuilder params = makeUpdateBuilder(keys, clusterings, state, options, local, timestamp, nowInSeconds, requestTime);
|
||||||
|
|
||||||
for (ByteBuffer key : keys)
|
for (ByteBuffer key : keys)
|
||||||
{
|
{
|
||||||
|
|
@ -1171,14 +1172,14 @@ public abstract class ModificationStatement implements CQLStatement.SingleKeyspa
|
||||||
return restrictions.getSlices(options);
|
return restrictions.getSlices(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UpdateParameters makeUpdateParameters(Collection<ByteBuffer> keys,
|
private RowUpdateBuilder makeUpdateBuilder(Collection<ByteBuffer> keys,
|
||||||
NavigableSet<Clustering<?>> clusterings,
|
NavigableSet<Clustering<?>> clusterings,
|
||||||
ClientState state,
|
ClientState state,
|
||||||
QueryOptions options,
|
QueryOptions options,
|
||||||
boolean local,
|
boolean local,
|
||||||
long timestamp,
|
long timestamp,
|
||||||
long nowInSeconds,
|
long nowInSeconds,
|
||||||
Dispatcher.RequestTime requestTime)
|
Dispatcher.RequestTime requestTime)
|
||||||
{
|
{
|
||||||
if (clusterings.contains(Clustering.STATIC_CLUSTERING))
|
if (clusterings.contains(Clustering.STATIC_CLUSTERING))
|
||||||
return makeUpdateParameters(keys,
|
return makeUpdateParameters(keys,
|
||||||
|
|
@ -1206,7 +1207,7 @@ public abstract class ModificationStatement implements CQLStatement.SingleKeyspa
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <F> UpdateParameters makeUpdateParameters(Collection<ByteBuffer> keys,
|
private <F> RowUpdateBuilder makeUpdateParameters(Collection<ByteBuffer> keys,
|
||||||
// filter is needed rarely, so we allocate it on demand
|
// filter is needed rarely, so we allocate it on demand
|
||||||
java.util.function.Function<F, ClusteringIndexFilter> filterBuilder,
|
java.util.function.Function<F, ClusteringIndexFilter> filterBuilder,
|
||||||
F filterArg,
|
F filterArg,
|
||||||
|
|
@ -1229,13 +1230,13 @@ public abstract class ModificationStatement implements CQLStatement.SingleKeyspa
|
||||||
nowInSeconds,
|
nowInSeconds,
|
||||||
requestTime);
|
requestTime);
|
||||||
|
|
||||||
return new UpdateParameters(metadata(),
|
return new RegularRowUpdateBuilder(metadata(),
|
||||||
state,
|
state,
|
||||||
options,
|
options,
|
||||||
getTimestamp(timestamp, options),
|
getTimestamp(timestamp, options),
|
||||||
nowInSeconds,
|
nowInSeconds,
|
||||||
getTimeToLive(options),
|
getTimeToLive(options),
|
||||||
lists);
|
lists);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static abstract class Parsed extends QualifiedStatement
|
public static abstract class Parsed extends QualifiedStatement
|
||||||
|
|
|
||||||
|
|
@ -1081,7 +1081,7 @@ public class SelectStatement implements CQLStatement.SingleKeyspaceCqlStatement,
|
||||||
ClientState state) throws InvalidRequestException
|
ClientState state) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
GroupMaker groupMaker = aggregationSpec == null ? null : aggregationSpec.newGroupMaker();
|
GroupMaker groupMaker = aggregationSpec == null ? null : aggregationSpec.newGroupMaker();
|
||||||
ResultSetBuilder result = new ResultSetBuilder(getResultMetadata(), selectors, unmask, groupMaker);
|
ResultSetBuilder result = new ResultSetBuilder(getResultMetadata(), options, selectors, unmask, groupMaker);
|
||||||
|
|
||||||
while (partitions.hasNext())
|
while (partitions.hasNext())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ import org.apache.cassandra.audit.AuditLogEntryType;
|
||||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||||
import org.apache.cassandra.cql3.CQLStatement;
|
import org.apache.cassandra.cql3.CQLStatement;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.ResultSet;
|
import org.apache.cassandra.cql3.ResultSet;
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
|
|
@ -80,8 +81,8 @@ import org.apache.cassandra.service.accord.serializers.TableMetadatas;
|
||||||
import org.apache.cassandra.service.accord.serializers.TableMetadatasAndKeys;
|
import org.apache.cassandra.service.accord.serializers.TableMetadatasAndKeys;
|
||||||
import org.apache.cassandra.service.accord.txn.AccordUpdate;
|
import org.apache.cassandra.service.accord.txn.AccordUpdate;
|
||||||
import org.apache.cassandra.service.accord.txn.TxnCondition;
|
import org.apache.cassandra.service.accord.txn.TxnCondition;
|
||||||
import org.apache.cassandra.service.accord.txn.TxnData;
|
|
||||||
import org.apache.cassandra.service.accord.txn.TxnDataKeyValue;
|
import org.apache.cassandra.service.accord.txn.TxnDataKeyValue;
|
||||||
|
import org.apache.cassandra.service.accord.txn.TxnDataResult;
|
||||||
import org.apache.cassandra.service.accord.txn.TxnNamedRead;
|
import org.apache.cassandra.service.accord.txn.TxnNamedRead;
|
||||||
import org.apache.cassandra.service.accord.txn.TxnQuery;
|
import org.apache.cassandra.service.accord.txn.TxnQuery;
|
||||||
import org.apache.cassandra.service.accord.txn.TxnRead;
|
import org.apache.cassandra.service.accord.txn.TxnRead;
|
||||||
|
|
@ -96,7 +97,6 @@ import org.apache.cassandra.tcm.ClusterMetadata;
|
||||||
import org.apache.cassandra.tcm.Epoch;
|
import org.apache.cassandra.tcm.Epoch;
|
||||||
import org.apache.cassandra.transport.Dispatcher;
|
import org.apache.cassandra.transport.Dispatcher;
|
||||||
import org.apache.cassandra.transport.messages.ResultMessage;
|
import org.apache.cassandra.transport.messages.ResultMessage;
|
||||||
import org.apache.cassandra.utils.FBUtilities;
|
|
||||||
import org.apache.cassandra.utils.NoSpamLogger;
|
import org.apache.cassandra.utils.NoSpamLogger;
|
||||||
|
|
||||||
import static accord.primitives.Txn.Kind.Read;
|
import static accord.primitives.Txn.Kind.Read;
|
||||||
|
|
@ -607,31 +607,35 @@ public class TransactionStatement implements CQLStatement.CompositeCQLStatement,
|
||||||
if (txnResult.kind() == retry_new_protocol)
|
if (txnResult.kind() == retry_new_protocol)
|
||||||
throw new InvalidRequestException(UNSUPPORTED_MIGRATION);
|
throw new InvalidRequestException(UNSUPPORTED_MIGRATION);
|
||||||
TxnValidationRejection.maybeThrow(txnResult);
|
TxnValidationRejection.maybeThrow(txnResult);
|
||||||
|
TxnDataResult data = (TxnDataResult)txnResult;
|
||||||
TxnData data = (TxnData)txnResult;
|
|
||||||
|
|
||||||
if (returningSelect != null)
|
if (returningSelect != null)
|
||||||
{
|
{
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
SinglePartitionReadQuery.Group<SinglePartitionReadCommand> selectQuery = (SinglePartitionReadQuery.Group<SinglePartitionReadCommand>) returningSelect.select.getQuery(options, 0);
|
SinglePartitionReadQuery.Group<SinglePartitionReadCommand> selectQuery = (SinglePartitionReadQuery.Group<SinglePartitionReadCommand>) returningSelect.select.getQuery(options, 0);
|
||||||
Selection.Selectors selectors = returningSelect.select.getSelection().newSelectors(options);
|
Selection.Selectors selectors = returningSelect.select.getSelection().newSelectors(options);
|
||||||
ResultSetBuilder result = new ResultSetBuilder(resultMetadata, selectors, false);
|
long atMicros = data.atMicros;
|
||||||
|
FunctionContext context = new FunctionContext.MicrosFunctionContext(atMicros)
|
||||||
|
{
|
||||||
|
@Override public QueryOptions options() { return options; }
|
||||||
|
};
|
||||||
|
ResultSetBuilder result = new ResultSetBuilder(resultMetadata, context, selectors, false);
|
||||||
|
long atSeconds = atMicros / 1000_000;
|
||||||
if (selectQuery.queries.size() == 1)
|
if (selectQuery.queries.size() == 1)
|
||||||
{
|
{
|
||||||
TxnDataKeyValue partition = (TxnDataKeyValue)data.get(txnDataName(RETURNING));
|
TxnDataKeyValue partition = (TxnDataKeyValue)data.get(txnDataName(RETURNING));
|
||||||
boolean reversed = selectQuery.queries.get(0).isReversed();
|
boolean reversed = selectQuery.queries.get(0).isReversed();
|
||||||
if (partition != null)
|
if (partition != null)
|
||||||
returningSelect.select.processPartition(partition.rowIterator(reversed), options, result, FBUtilities.nowInSeconds());
|
returningSelect.select.processPartition(partition.rowIterator(reversed), options, result, atSeconds);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
long nowInSec = FBUtilities.nowInSeconds();
|
|
||||||
for (int i = 0; i < selectQuery.queries.size(); i++)
|
for (int i = 0; i < selectQuery.queries.size(); i++)
|
||||||
{
|
{
|
||||||
TxnDataKeyValue partition = (TxnDataKeyValue)data.get(txnDataName(RETURNING, i));
|
TxnDataKeyValue partition = (TxnDataKeyValue)data.get(txnDataName(RETURNING, i));
|
||||||
boolean reversed = selectQuery.queries.get(i).isReversed();
|
boolean reversed = selectQuery.queries.get(i).isReversed();
|
||||||
if (partition != null)
|
if (partition != null)
|
||||||
returningSelect.select.processPartition(partition.rowIterator(reversed), options, result, nowInSec);
|
returningSelect.select.processPartition(partition.rowIterator(reversed), options, result, atSeconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new ResultMessage.Rows(result.build());
|
return new ResultMessage.Rows(result.build());
|
||||||
|
|
@ -649,7 +653,7 @@ public class TransactionStatement implements CQLStatement.CompositeCQLStatement,
|
||||||
columns.add(reference.column());
|
columns.add(reference.column());
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultSetBuilder result = new ResultSetBuilder(resultMetadata, Selection.noopSelector(), false);
|
ResultSetBuilder result = new ResultSetBuilder(resultMetadata, FunctionContext.NONE, Selection.noopSelector(), false);
|
||||||
result.newRow(options.getProtocolVersion(), null, null, columns);
|
result.newRow(options.getProtocolVersion(), null, null, columns);
|
||||||
|
|
||||||
for (int i = 0; i < returningReferences.size(); i++)
|
for (int i = 0; i < returningReferences.size(); i++)
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ import org.apache.cassandra.cql3.Operations;
|
||||||
import org.apache.cassandra.cql3.Operator;
|
import org.apache.cassandra.cql3.Operator;
|
||||||
import org.apache.cassandra.cql3.QualifiedName;
|
import org.apache.cassandra.cql3.QualifiedName;
|
||||||
import org.apache.cassandra.cql3.Relation;
|
import org.apache.cassandra.cql3.Relation;
|
||||||
|
import org.apache.cassandra.cql3.RowUpdateBuilder;
|
||||||
import org.apache.cassandra.cql3.StatementSource;
|
import org.apache.cassandra.cql3.StatementSource;
|
||||||
import org.apache.cassandra.cql3.UpdateParameters;
|
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.WhereClause;
|
import org.apache.cassandra.cql3.WhereClause;
|
||||||
import org.apache.cassandra.cql3.conditions.ColumnCondition;
|
import org.apache.cassandra.cql3.conditions.ColumnCondition;
|
||||||
|
|
@ -96,7 +96,7 @@ public class UpdateStatement extends ModificationStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addUpdateForKey(PartitionUpdate.Builder updateBuilder, Clustering<?> clustering, UpdateParameters params)
|
public void addUpdateForKey(PartitionUpdate.Builder updateBuilder, Clustering<?> clustering, RowUpdateBuilder params)
|
||||||
{
|
{
|
||||||
if (updatesRegularRows())
|
if (updatesRegularRows())
|
||||||
{
|
{
|
||||||
|
|
@ -142,7 +142,7 @@ public class UpdateStatement extends ModificationStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addUpdateForKey(PartitionUpdate.Builder update, Slice slice, UpdateParameters params)
|
public void addUpdateForKey(PartitionUpdate.Builder update, Slice slice, RowUpdateBuilder builder)
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ import java.nio.ByteBuffer;
|
||||||
import org.apache.cassandra.cql3.AssignmentTestable;
|
import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.Operation;
|
import org.apache.cassandra.cql3.Operation;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.RowUpdateBuilder;
|
||||||
import org.apache.cassandra.cql3.UpdateParameters;
|
|
||||||
import org.apache.cassandra.db.Clustering;
|
import org.apache.cassandra.db.Clustering;
|
||||||
import org.apache.cassandra.db.DecoratedKey;
|
import org.apache.cassandra.db.DecoratedKey;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
|
|
@ -63,9 +63,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||||
*/
|
*/
|
||||||
public abstract class Constants
|
public abstract class Constants
|
||||||
{
|
{
|
||||||
private static ByteBuffer getCurrentCellBuffer(ColumnMetadata column, DecoratedKey key, UpdateParameters params)
|
private static ByteBuffer getCurrentCellBuffer(ColumnMetadata column, DecoratedKey key, RowUpdateBuilder builder)
|
||||||
{
|
{
|
||||||
Row currentRow = params.getPrefetchedRow(key, column.isStatic() ? Clustering.STATIC_CLUSTERING : params.currentClustering());
|
Row currentRow = builder.getPrefetchedRow(key, column.isStatic() ? Clustering.STATIC_CLUSTERING : builder.currentClustering());
|
||||||
Cell<?> currentCell = currentRow == null ? null : currentRow.getCell(column);
|
Cell<?> currentCell = currentRow == null ? null : currentRow.getCell(column);
|
||||||
return currentCell == null ? null : currentCell.buffer();
|
return currentCell == null ? null : currentCell.buffer();
|
||||||
}
|
}
|
||||||
|
|
@ -228,7 +228,7 @@ public abstract class Constants
|
||||||
{
|
{
|
||||||
// TODO: The bind overriding should be removed. A user does not have to call bind on a Terminal.
|
// TODO: The bind overriding should be removed. A user does not have to call bind on a Terminal.
|
||||||
@Override
|
@Override
|
||||||
public Terminal bind(QueryOptions options)
|
public Terminal bind(FunctionContext context)
|
||||||
{
|
{
|
||||||
// We return null because that makes life easier for collections
|
// We return null because that makes life easier for collections
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -459,7 +459,7 @@ public abstract class Constants
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer bindAndGet(QueryOptions options)
|
public ByteBuffer bindAndGet(FunctionContext context)
|
||||||
{
|
{
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
@ -478,23 +478,23 @@ public abstract class Constants
|
||||||
super(column, t);
|
super(column, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
if (t.isByteArrayGetSupported(params.options))
|
if (t.isByteArrayGetSupported(builder))
|
||||||
{
|
{
|
||||||
byte[] value = t.bindAndGetByteArray(params.options);
|
byte[] value = t.bindAndGetByteArray(builder);
|
||||||
if (value == null)
|
if (value == null)
|
||||||
params.addTombstone(column);
|
builder.addTombstone(column);
|
||||||
else if (value != ByteArrayUtil.UNSET_BYTE_ARRAY) // use reference equality and not object equality
|
else if (value != ByteArrayUtil.UNSET_BYTE_ARRAY) // use reference equality and not object equality
|
||||||
params.addCell(column, value);
|
builder.addCell(column, value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ByteBuffer value = t.bindAndGet(params.options);
|
ByteBuffer value = t.bindAndGet(builder);
|
||||||
if (value == null)
|
if (value == null)
|
||||||
params.addTombstone(column);
|
builder.addTombstone(column);
|
||||||
else if (value != ByteBufferUtil.UNSET_BYTE_BUFFER) // use reference equality and not object equality
|
else if (value != ByteBufferUtil.UNSET_BYTE_BUFFER) // use reference equality and not object equality
|
||||||
params.addCell(column, value);
|
builder.addCell(column, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -511,43 +511,43 @@ public abstract class Constants
|
||||||
return !(column.type instanceof CounterColumnType);
|
return !(column.type instanceof CounterColumnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
if (column.type instanceof CounterColumnType)
|
if (column.type instanceof CounterColumnType)
|
||||||
{
|
{
|
||||||
ByteBuffer bytes = t.bindAndGet(params.options);
|
ByteBuffer bytes = t.bindAndGet(builder);
|
||||||
if (bytes == null)
|
if (bytes == null)
|
||||||
throw new InvalidRequestException("Invalid null value for counter increment");
|
throw new InvalidRequestException("Invalid null value for counter increment");
|
||||||
if (bytes == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
if (bytes == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
long increment = ByteBufferUtil.toLong(bytes);
|
long increment = ByteBufferUtil.toLong(bytes);
|
||||||
params.addCounter(column, increment);
|
builder.addCounter(column, increment);
|
||||||
}
|
}
|
||||||
else if (column.type instanceof NumberType<?>)
|
else if (column.type instanceof NumberType<?>)
|
||||||
{
|
{
|
||||||
@SuppressWarnings("unchecked") NumberType<Number> type = (NumberType<Number>) column.type;
|
@SuppressWarnings("unchecked") NumberType<Number> type = (NumberType<Number>) column.type;
|
||||||
ByteBuffer increment = type.sanitize(t.bindAndGet(params.options));
|
ByteBuffer increment = type.sanitize(t.bindAndGet(builder));
|
||||||
if (increment == null)
|
if (increment == null)
|
||||||
return;
|
return;
|
||||||
ByteBuffer current = type.sanitize(getCurrentCellBuffer(column, partitionKey, params));
|
ByteBuffer current = type.sanitize(getCurrentCellBuffer(column, partitionKey, builder));
|
||||||
if (current == null)
|
if (current == null)
|
||||||
return;
|
return;
|
||||||
ByteBuffer newValue = type.add(type.compose(current), type.compose(increment));
|
ByteBuffer newValue = type.add(type.compose(current), type.compose(increment));
|
||||||
params.addCell(column, newValue);
|
builder.addCell(column, newValue);
|
||||||
}
|
}
|
||||||
else if (column.type instanceof StringType)
|
else if (column.type instanceof StringType)
|
||||||
{
|
{
|
||||||
ByteBuffer append = t.bindAndGet(params.options);
|
ByteBuffer append = t.bindAndGet(builder);
|
||||||
if (append == null)
|
if (append == null)
|
||||||
return;
|
return;
|
||||||
ByteBuffer current = getCurrentCellBuffer(column, partitionKey, params);
|
ByteBuffer current = getCurrentCellBuffer(column, partitionKey, builder);
|
||||||
if (current == null)
|
if (current == null)
|
||||||
return;
|
return;
|
||||||
ByteBuffer newValue = ByteBuffer.allocate(current.remaining() + append.remaining());
|
ByteBuffer newValue = ByteBuffer.allocate(current.remaining() + append.remaining());
|
||||||
FastByteOperations.copy(current, current.position(), newValue, newValue.position(), current.remaining());
|
FastByteOperations.copy(current, current.position(), newValue, newValue.position(), current.remaining());
|
||||||
FastByteOperations.copy(append, append.position(), newValue, newValue.position() + current.remaining(), append.remaining());
|
FastByteOperations.copy(append, append.position(), newValue, newValue.position() + current.remaining(), append.remaining());
|
||||||
params.addCell(column, newValue);
|
builder.addCell(column, newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -565,11 +565,11 @@ public abstract class Constants
|
||||||
return !column.type.isCounter();
|
return !column.type.isCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
if (column.type instanceof CounterColumnType)
|
if (column.type instanceof CounterColumnType)
|
||||||
{
|
{
|
||||||
ByteBuffer bytes = t.bindAndGet(params.options);
|
ByteBuffer bytes = t.bindAndGet(builder);
|
||||||
if (bytes == null)
|
if (bytes == null)
|
||||||
throw new InvalidRequestException("Invalid null value for counter increment");
|
throw new InvalidRequestException("Invalid null value for counter increment");
|
||||||
if (bytes == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
if (bytes == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
||||||
|
|
@ -579,19 +579,19 @@ public abstract class Constants
|
||||||
if (increment == Long.MIN_VALUE)
|
if (increment == Long.MIN_VALUE)
|
||||||
throw new InvalidRequestException("The negation of " + increment + " overflows supported counter precision (signed 8 bytes integer)");
|
throw new InvalidRequestException("The negation of " + increment + " overflows supported counter precision (signed 8 bytes integer)");
|
||||||
|
|
||||||
params.addCounter(column, -increment);
|
builder.addCounter(column, -increment);
|
||||||
}
|
}
|
||||||
else if (column.type instanceof NumberType<?>)
|
else if (column.type instanceof NumberType<?>)
|
||||||
{
|
{
|
||||||
@SuppressWarnings("unchecked") NumberType<Number> type = (NumberType<Number>) column.type;
|
@SuppressWarnings("unchecked") NumberType<Number> type = (NumberType<Number>) column.type;
|
||||||
ByteBuffer increment = type.sanitize(t.bindAndGet(params.options));
|
ByteBuffer increment = type.sanitize(t.bindAndGet(builder));
|
||||||
if (increment == null)
|
if (increment == null)
|
||||||
return;
|
return;
|
||||||
ByteBuffer current = type.sanitize(getCurrentCellBuffer(column, partitionKey, params));
|
ByteBuffer current = type.sanitize(getCurrentCellBuffer(column, partitionKey, builder));
|
||||||
if (current == null)
|
if (current == null)
|
||||||
return;
|
return;
|
||||||
ByteBuffer newValue = type.substract(type.compose(current), type.compose(increment));
|
ByteBuffer newValue = type.substract(type.compose(current), type.compose(increment));
|
||||||
params.addCell(column, newValue);
|
builder.addCell(column, newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -605,12 +605,12 @@ public abstract class Constants
|
||||||
super(column, null);
|
super(column, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
if (column.type.isMultiCell())
|
if (column.type.isMultiCell())
|
||||||
params.setComplexDeletionTime(column);
|
builder.setComplexDeletionTime(column);
|
||||||
else
|
else
|
||||||
params.addTombstone(column);
|
builder.addTombstone(column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import java.util.List;
|
||||||
import org.apache.cassandra.cql3.AssignmentTestable;
|
import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
|
|
@ -60,9 +60,9 @@ public final class InMarker extends Terms.NonTerminals
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminals bind(QueryOptions options)
|
public Terminals bind(FunctionContext context)
|
||||||
{
|
{
|
||||||
ByteBuffer values = options.getValues().get(bindIndex);
|
ByteBuffer values = context.options().getValues().get(bindIndex);
|
||||||
if (values == null)
|
if (values == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|
@ -95,16 +95,16 @@ public final class InMarker extends Terms.NonTerminals
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ByteBuffer> bindAndGet(QueryOptions options)
|
public List<ByteBuffer> bindAndGet(FunctionContext context)
|
||||||
{
|
{
|
||||||
Terminals terminals = bind(options);
|
Terminals terminals = bind(context);
|
||||||
return terminals == null ? null : terminals.get();
|
return terminals == null ? null : terminals.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<List<ByteBuffer>> bindAndGetElements(QueryOptions options)
|
public List<List<ByteBuffer>> bindAndGetElements(FunctionContext context)
|
||||||
{
|
{
|
||||||
Terminals terminals = bind(options);
|
Terminals terminals = bind(context);
|
||||||
return terminals == null ? null : terminals.getElements();
|
return terminals == null ? null : terminals.getElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,9 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.apache.cassandra.cql3.AssignmentTestable;
|
import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.Operation;
|
import org.apache.cassandra.cql3.Operation;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.RowUpdateBuilder;
|
||||||
import org.apache.cassandra.cql3.UpdateParameters;
|
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.db.DecoratedKey;
|
import org.apache.cassandra.db.DecoratedKey;
|
||||||
import org.apache.cassandra.db.guardrails.Guardrails;
|
import org.apache.cassandra.db.guardrails.Guardrails;
|
||||||
|
|
@ -180,7 +180,7 @@ public abstract class Lists
|
||||||
values.add(t);
|
values.add(t);
|
||||||
}
|
}
|
||||||
MultiElements.DelayedValue value = new MultiElements.DelayedValue((MultiElementType<?>) receiver.type.unwrap(), values);
|
MultiElements.DelayedValue value = new MultiElements.DelayedValue((MultiElementType<?>) receiver.type.unwrap(), values);
|
||||||
return allTerminal ? value.bind(QueryOptions.DEFAULT) : value;
|
return allTerminal ? value.bind(FunctionContext.NONE) : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateAssignableTo(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
|
private void validateAssignableTo(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
|
||||||
|
|
@ -304,16 +304,16 @@ public abstract class Lists
|
||||||
return column.type.isMultiCell();
|
return column.type.isMultiCell();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
Term.Terminal value = t.bind(params.options);
|
Term.Terminal value = t.bind(builder);
|
||||||
if (value == UNSET_VALUE)
|
if (value == UNSET_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// delete + append
|
// delete + append
|
||||||
if (column.type.isMultiCell())
|
if (column.type.isMultiCell())
|
||||||
params.setComplexDeletionTimeForOverwrite(column);
|
builder.setComplexDeletionTimeForOverwrite(column);
|
||||||
Appender.doAppend(value, column, params);
|
Appender.doAppend(value, column, builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -349,23 +349,23 @@ public abstract class Lists
|
||||||
idx.collectMarkerSpecification(boundNames, owner);
|
idx.collectMarkerSpecification(boundNames, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
// we should not get here for frozen lists
|
// we should not get here for frozen lists
|
||||||
assert column.type.isMultiCell() : "Attempted to set an individual element on a frozen list";
|
assert column.type.isMultiCell() : "Attempted to set an individual element on a frozen list";
|
||||||
|
|
||||||
Guardrails.readBeforeWriteListOperationsEnabled
|
Guardrails.readBeforeWriteListOperationsEnabled
|
||||||
.ensureEnabled("Setting of list items by index requiring read before write", params.clientState);
|
.ensureEnabled("Setting of list items by index requiring read before write", builder.clientState);
|
||||||
|
|
||||||
ByteBuffer index = idx.bindAndGet(params.options);
|
ByteBuffer index = idx.bindAndGet(builder);
|
||||||
ByteBuffer value = t.bindAndGet(params.options);
|
ByteBuffer value = t.bindAndGet(builder);
|
||||||
|
|
||||||
if (index == null)
|
if (index == null)
|
||||||
throw new InvalidRequestException("Invalid null value for list index");
|
throw new InvalidRequestException("Invalid null value for list index");
|
||||||
if (index == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
if (index == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
||||||
throw new InvalidRequestException("Invalid unset value for list index");
|
throw new InvalidRequestException("Invalid unset value for list index");
|
||||||
|
|
||||||
Row existingRow = params.getPrefetchedRow(partitionKey, params.currentClustering());
|
Row existingRow = builder.getPrefetchedRow(partitionKey, builder.currentClustering());
|
||||||
int existingSize = existingSize(existingRow, column);
|
int existingSize = existingSize(existingRow, column);
|
||||||
int idx = ByteBufferUtil.toInt(index);
|
int idx = ByteBufferUtil.toInt(index);
|
||||||
if (existingSize == 0)
|
if (existingSize == 0)
|
||||||
|
|
@ -375,9 +375,9 @@ public abstract class Lists
|
||||||
|
|
||||||
CellPath elementPath = existingRow.getComplexColumnData(column).getCellByIndex(idx).path();
|
CellPath elementPath = existingRow.getComplexColumnData(column).getCellByIndex(idx).path();
|
||||||
if (value == null)
|
if (value == null)
|
||||||
params.addTombstone(column, elementPath);
|
builder.addTombstone(column, elementPath);
|
||||||
else if (value != ByteBufferUtil.UNSET_BYTE_BUFFER)
|
else if (value != ByteBufferUtil.UNSET_BYTE_BUFFER)
|
||||||
params.addCell(column, elementPath, value);
|
builder.addCell(column, elementPath, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -388,11 +388,11 @@ public abstract class Lists
|
||||||
super(column, t);
|
super(column, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
assert column.type.isMultiCell() : "Attempted to append to a frozen list";
|
assert column.type.isMultiCell() : "Attempted to append to a frozen list";
|
||||||
Term.Terminal value = t.bind(params.options);
|
Term.Terminal value = t.bind(builder);
|
||||||
doAppend(value, column, params);
|
doAppend(value, column, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -401,7 +401,7 @@ public abstract class Lists
|
||||||
return column.type.isMultiCell();
|
return column.type.isMultiCell();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void doAppend(Term.Terminal value, ColumnMetadata column, UpdateParameters params) throws InvalidRequestException
|
static void doAppend(Term.Terminal value, ColumnMetadata column, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
ListType<?> type = (ListType<?>) column.type;
|
ListType<?> type = (ListType<?>) column.type;
|
||||||
|
|
||||||
|
|
@ -409,7 +409,7 @@ public abstract class Lists
|
||||||
{
|
{
|
||||||
// for frozen lists, we're overwriting the whole cell value
|
// for frozen lists, we're overwriting the whole cell value
|
||||||
if (!type.isMultiCell())
|
if (!type.isMultiCell())
|
||||||
params.addTombstone(column);
|
builder.addTombstone(column);
|
||||||
|
|
||||||
// If we append null, do nothing. Note that for Setter, we've
|
// If we append null, do nothing. Note that for Setter, we've
|
||||||
// already removed the previous value so we're good here too
|
// already removed the previous value so we're good here too
|
||||||
|
|
@ -426,22 +426,22 @@ public abstract class Lists
|
||||||
// Guardrails about collection size are only checked for the added elements without considering
|
// Guardrails about collection size are only checked for the added elements without considering
|
||||||
// already existent elements. This is done so to avoid read-before-write, having additional checks
|
// already existent elements. This is done so to avoid read-before-write, having additional checks
|
||||||
// during SSTable write.
|
// during SSTable write.
|
||||||
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, params.clientState);
|
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, builder.clientState);
|
||||||
|
|
||||||
int dataSize = 0;
|
int dataSize = 0;
|
||||||
for (ByteBuffer buffer : elements)
|
for (ByteBuffer buffer : elements)
|
||||||
{
|
{
|
||||||
ByteBuffer cellPath = ByteBuffer.wrap(params.nextTimeUUIDAsBytes());
|
ByteBuffer cellPath = ByteBuffer.wrap(builder.nextTimeUUIDAsBytes());
|
||||||
Cell<?> cell = params.addCell(column, CellPath.create(cellPath), buffer);
|
Cell<?> cell = builder.addCell(column, CellPath.create(cellPath), buffer);
|
||||||
dataSize += cell.dataSize();
|
dataSize += cell.dataSize();
|
||||||
}
|
}
|
||||||
Guardrails.collectionListSize.guard(dataSize, column.name.toString(), false, params.clientState);
|
Guardrails.collectionListSize.guard(dataSize, column.name.toString(), false, builder.clientState);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, params.clientState);
|
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, builder.clientState);
|
||||||
Cell<?> cell = params.addCell(column, value.get());
|
Cell<?> cell = builder.addCell(column, value.get());
|
||||||
Guardrails.collectionListSize.guard(cell.dataSize(), column.name.toString(), false, params.clientState);
|
Guardrails.collectionListSize.guard(cell.dataSize(), column.name.toString(), false, builder.clientState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -459,10 +459,10 @@ public abstract class Lists
|
||||||
return column.type.isMultiCell();
|
return column.type.isMultiCell();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
assert column.type.isMultiCell() : "Attempted to prepend to a frozen list";
|
assert column.type.isMultiCell() : "Attempted to prepend to a frozen list";
|
||||||
Term.Terminal value = t.bind(params.options);
|
Term.Terminal value = t.bind(builder);
|
||||||
if (value == null || value == UNSET_VALUE)
|
if (value == null || value == UNSET_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -484,7 +484,7 @@ public abstract class Lists
|
||||||
|
|
||||||
// TODO: is this safe as part of LWTs?
|
// TODO: is this safe as part of LWTs?
|
||||||
ByteBuffer uuid = ByteBuffer.wrap(atUnixMillisAsBytes(pt.millis, (pt.nanos + remainingInBatch--)));
|
ByteBuffer uuid = ByteBuffer.wrap(atUnixMillisAsBytes(pt.millis, (pt.nanos + remainingInBatch--)));
|
||||||
params.addCell(column, CellPath.create(uuid), toAdd.get(i));
|
builder.addCell(column, CellPath.create(uuid), toAdd.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -502,17 +502,17 @@ public abstract class Lists
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
assert column.type.isMultiCell() : "Attempted to delete from a frozen list";
|
assert column.type.isMultiCell() : "Attempted to delete from a frozen list";
|
||||||
|
|
||||||
Guardrails.readBeforeWriteListOperationsEnabled
|
Guardrails.readBeforeWriteListOperationsEnabled
|
||||||
.ensureEnabled("Removal of list items requiring read before write", params.clientState);
|
.ensureEnabled("Removal of list items requiring read before write", builder.clientState);
|
||||||
|
|
||||||
// We want to call bind before possibly returning to reject queries where the value provided is not a list.
|
// We want to call bind before possibly returning to reject queries where the value provided is not a list.
|
||||||
Term.Terminal value = t.bind(params.options);
|
Term.Terminal value = t.bind(builder);
|
||||||
|
|
||||||
Row existingRow = params.getPrefetchedRow(partitionKey, params.currentClustering());
|
Row existingRow = builder.getPrefetchedRow(partitionKey, builder.currentClustering());
|
||||||
ComplexColumnData complexData = existingRow == null ? null : existingRow.getComplexColumnData(column);
|
ComplexColumnData complexData = existingRow == null ? null : existingRow.getComplexColumnData(column);
|
||||||
if (value == null || value == UNSET_VALUE || complexData == null)
|
if (value == null || value == UNSET_VALUE || complexData == null)
|
||||||
return;
|
return;
|
||||||
|
|
@ -525,7 +525,7 @@ public abstract class Lists
|
||||||
for (Cell<?> cell : complexData)
|
for (Cell<?> cell : complexData)
|
||||||
{
|
{
|
||||||
if (toDiscard.contains(cell.buffer()))
|
if (toDiscard.contains(cell.buffer()))
|
||||||
params.addTombstone(column, cell.path());
|
builder.addTombstone(column, cell.path());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -543,20 +543,20 @@ public abstract class Lists
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
assert column.type.isMultiCell() : "Attempted to delete an item by index from a frozen list";
|
assert column.type.isMultiCell() : "Attempted to delete an item by index from a frozen list";
|
||||||
|
|
||||||
Guardrails.readBeforeWriteListOperationsEnabled
|
Guardrails.readBeforeWriteListOperationsEnabled
|
||||||
.ensureEnabled("Removal of list items by index requiring read before write", params.clientState);
|
.ensureEnabled("Removal of list items by index requiring read before write", builder.clientState);
|
||||||
|
|
||||||
Term.Terminal index = t.bind(params.options);
|
Term.Terminal index = t.bind(builder);
|
||||||
if (index == null)
|
if (index == null)
|
||||||
throw new InvalidRequestException("Invalid null value for list index");
|
throw new InvalidRequestException("Invalid null value for list index");
|
||||||
if (index == Constants.UNSET_VALUE)
|
if (index == Constants.UNSET_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Row existingRow = params.getPrefetchedRow(partitionKey, params.currentClustering());
|
Row existingRow = builder.getPrefetchedRow(partitionKey, builder.currentClustering());
|
||||||
int existingSize = existingSize(existingRow, column);
|
int existingSize = existingSize(existingRow, column);
|
||||||
int idx = ByteBufferUtil.toInt(index.get());
|
int idx = ByteBufferUtil.toInt(index.get());
|
||||||
if (existingSize == 0)
|
if (existingSize == 0)
|
||||||
|
|
@ -564,7 +564,7 @@ public abstract class Lists
|
||||||
if (idx < 0 || idx >= existingSize)
|
if (idx < 0 || idx >= existingSize)
|
||||||
throw new InvalidRequestException(String.format("List index %d out of bound, list has size %d", idx, existingSize));
|
throw new InvalidRequestException(String.format("List index %d out of bound, list has size %d", idx, existingSize));
|
||||||
|
|
||||||
params.addTombstone(column, existingRow.getComplexColumnData(column).getCellByIndex(idx).path());
|
builder.addTombstone(column, existingRow.getComplexColumnData(column).getCellByIndex(idx).path());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.Operation;
|
import org.apache.cassandra.cql3.Operation;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.UpdateParameters;
|
import org.apache.cassandra.cql3.RowUpdateBuilder;
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.db.DecoratedKey;
|
import org.apache.cassandra.db.DecoratedKey;
|
||||||
import org.apache.cassandra.db.guardrails.Guardrails;
|
import org.apache.cassandra.db.guardrails.Guardrails;
|
||||||
|
|
@ -252,16 +252,16 @@ public final class Maps
|
||||||
super(column, t);
|
super(column, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
Term.Terminal value = t.bind(params.options);
|
Term.Terminal value = t.bind(builder);
|
||||||
if (value == UNSET_VALUE)
|
if (value == UNSET_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// delete + put
|
// delete + put
|
||||||
if (column.type.isMultiCell())
|
if (column.type.isMultiCell())
|
||||||
params.setComplexDeletionTimeForOverwrite(column);
|
builder.setComplexDeletionTimeForOverwrite(column);
|
||||||
Putter.doPut(value, column, params);
|
Putter.doPut(value, column, builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -282,11 +282,11 @@ public final class Maps
|
||||||
k.collectMarkerSpecification(boundNames, owner);
|
k.collectMarkerSpecification(boundNames, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
assert column.type.isMultiCell() : "Attempted to set a value for a single key on a frozen map";
|
assert column.type.isMultiCell() : "Attempted to set a value for a single key on a frozen map";
|
||||||
ByteBuffer key = k.bindAndGet(params.options);
|
ByteBuffer key = k.bindAndGet(builder);
|
||||||
ByteBuffer value = t.bindAndGet(params.options);
|
ByteBuffer value = t.bindAndGet(builder);
|
||||||
if (key == null)
|
if (key == null)
|
||||||
throw new InvalidRequestException("Invalid null map key");
|
throw new InvalidRequestException("Invalid null map key");
|
||||||
if (key == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
if (key == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
||||||
|
|
@ -296,11 +296,11 @@ public final class Maps
|
||||||
|
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
params.addTombstone(column, path);
|
builder.addTombstone(column, path);
|
||||||
}
|
}
|
||||||
else if (value != ByteBufferUtil.UNSET_BYTE_BUFFER)
|
else if (value != ByteBufferUtil.UNSET_BYTE_BUFFER)
|
||||||
{
|
{
|
||||||
params.addCell(column, path, value);
|
builder.addCell(column, path, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -312,15 +312,15 @@ public final class Maps
|
||||||
super(column, t);
|
super(column, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
assert column.type.isMultiCell() : "Attempted to add items to a frozen map";
|
assert column.type.isMultiCell() : "Attempted to add items to a frozen map";
|
||||||
Term.Terminal value = t.bind(params.options);
|
Term.Terminal value = t.bind(builder);
|
||||||
if (value != UNSET_VALUE)
|
if (value != UNSET_VALUE)
|
||||||
doPut(value, column, params);
|
doPut(value, column, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void doPut(Term.Terminal value, ColumnMetadata column, UpdateParameters params) throws InvalidRequestException
|
static void doPut(Term.Terminal value, ColumnMetadata column, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
MapType<?, ?> type = (MapType<?, ?>) column.type;
|
MapType<?, ?> type = (MapType<?, ?>) column.type;
|
||||||
|
|
||||||
|
|
@ -328,7 +328,7 @@ public final class Maps
|
||||||
{
|
{
|
||||||
// for frozen maps, we're overwriting the whole cell
|
// for frozen maps, we're overwriting the whole cell
|
||||||
if (!type.isMultiCell())
|
if (!type.isMultiCell())
|
||||||
params.addTombstone(column);
|
builder.addTombstone(column);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -343,22 +343,22 @@ public final class Maps
|
||||||
// Guardrails about collection size are only checked for the added elements without considering
|
// Guardrails about collection size are only checked for the added elements without considering
|
||||||
// already existent elements. This is done so to avoid read-before-write, having additional checks
|
// already existent elements. This is done so to avoid read-before-write, having additional checks
|
||||||
// during SSTable write.
|
// during SSTable write.
|
||||||
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, params.clientState);
|
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, builder.clientState);
|
||||||
|
|
||||||
int dataSize = 0;
|
int dataSize = 0;
|
||||||
Iterator<ByteBuffer> iter = elements.iterator();
|
Iterator<ByteBuffer> iter = elements.iterator();
|
||||||
while(iter.hasNext())
|
while(iter.hasNext())
|
||||||
{
|
{
|
||||||
Cell<?> cell = params.addCell(column, CellPath.create(iter.next()), iter.next());
|
Cell<?> cell = builder.addCell(column, CellPath.create(iter.next()), iter.next());
|
||||||
dataSize += cell.dataSize();
|
dataSize += cell.dataSize();
|
||||||
}
|
}
|
||||||
Guardrails.collectionMapSize.guard(dataSize, column.name.toString(), false, params.clientState);
|
Guardrails.collectionMapSize.guard(dataSize, column.name.toString(), false, builder.clientState);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, params.clientState);
|
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, builder.clientState);
|
||||||
Cell<?> cell = params.addCell(column, value.get());
|
Cell<?> cell = builder.addCell(column, value.get());
|
||||||
Guardrails.collectionMapSize.guard(cell.dataSize(), column.name.toString(), false, params.clientState);
|
Guardrails.collectionMapSize.guard(cell.dataSize(), column.name.toString(), false, builder.clientState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -370,16 +370,16 @@ public final class Maps
|
||||||
super(column, k);
|
super(column, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
assert column.type.isMultiCell() : "Attempted to delete a single key in a frozen map";
|
assert column.type.isMultiCell() : "Attempted to delete a single key in a frozen map";
|
||||||
Term.Terminal key = t.bind(params.options);
|
Term.Terminal key = t.bind(builder);
|
||||||
if (key == null)
|
if (key == null)
|
||||||
throw new InvalidRequestException("Invalid null map key");
|
throw new InvalidRequestException("Invalid null map key");
|
||||||
if (key == Constants.UNSET_VALUE)
|
if (key == Constants.UNSET_VALUE)
|
||||||
throw new InvalidRequestException("Invalid unset map key");
|
throw new InvalidRequestException("Invalid unset map key");
|
||||||
|
|
||||||
params.addTombstone(column, CellPath.create(key.get()));
|
builder.addTombstone(column, CellPath.create(key.get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.AssignmentTestable;
|
import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
|
|
@ -42,7 +42,7 @@ public final class Marker extends Term.NonTerminal
|
||||||
/**
|
/**
|
||||||
* The index of the bind variable within the query options.
|
* The index of the bind variable within the query options.
|
||||||
* <p>When a query is executed the value of this placeholder is retrieved from the query options values using
|
* <p>When a query is executed the value of this placeholder is retrieved from the query options values using
|
||||||
* the bindIndex. (see {@link Marker#bind(QueryOptions)}</p>
|
* the bindIndex. (see {@link Term#bind(FunctionContext)}</p>
|
||||||
*/
|
*/
|
||||||
private final int bindIndex;
|
private final int bindIndex;
|
||||||
|
|
||||||
|
|
@ -72,11 +72,11 @@ public final class Marker extends Term.NonTerminal
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Term.Terminal bind(QueryOptions options) throws InvalidRequestException
|
public Term.Terminal bind(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ByteBuffer bytes = options.getValue(bindIndex);
|
ByteBuffer bytes = context.options().getValues().get(bindIndex);
|
||||||
if (bytes == null)
|
if (bytes == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|
@ -97,11 +97,11 @@ public final class Marker extends Term.NonTerminal
|
||||||
|
|
||||||
// an optimized version without allocating interim Terminal objects
|
// an optimized version without allocating interim Terminal objects
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer bindAndGet(QueryOptions options)
|
public ByteBuffer bindAndGet(FunctionContext context)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ByteBuffer bytes = options.getValue(bindIndex);
|
ByteBuffer bytes = context.options().getValue(bindIndex);
|
||||||
if (bytes == null)
|
if (bytes == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|
@ -122,20 +122,20 @@ public final class Marker extends Term.NonTerminal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isByteArrayGetSupported(QueryOptions options)
|
public boolean isByteArrayGetSupported(FunctionContext context)
|
||||||
{
|
{
|
||||||
return options.isByteArrayValuesGetSupported();
|
return context.options().isByteArrayValuesGetSupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Same logic as bind() but it returns byte[] instead of ByteBuffer and there is no Value wrapper usage
|
Same logic as bind() but it returns byte[] instead of ByteBuffer and there is no Value wrapper usage
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public byte[] bindAndGetByteArray(QueryOptions options) throws InvalidRequestException
|
public byte[] bindAndGetByteArray(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
byte[] bytes = options.getByteArrayValues()[bindIndex];
|
byte[] bytes = context.options().getByteArrayValues()[bindIndex];
|
||||||
if (bytes == null)
|
if (bytes == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.db.marshal.MultiElementType;
|
import org.apache.cassandra.db.marshal.MultiElementType;
|
||||||
|
|
@ -126,14 +126,14 @@ public final class MultiElements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminal bind(QueryOptions options)
|
public Terminal bind(FunctionContext context)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<ByteBuffer> buffers = new ArrayList<>(elements.size());
|
List<ByteBuffer> buffers = new ArrayList<>(elements.size());
|
||||||
for (Term t : elements)
|
for (Term t : elements)
|
||||||
{
|
{
|
||||||
buffers.add(t.bindAndGet(options));
|
buffers.add(t.bindAndGet(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
buffers = type.filterSortAndValidateElements(buffers);
|
buffers = type.filterSortAndValidateElements(buffers);
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ import java.util.stream.StreamSupport;
|
||||||
import org.apache.cassandra.cql3.AssignmentTestable;
|
import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.Operation;
|
import org.apache.cassandra.cql3.Operation;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.RowUpdateBuilder;
|
||||||
import org.apache.cassandra.cql3.UpdateParameters;
|
|
||||||
import org.apache.cassandra.db.DecoratedKey;
|
import org.apache.cassandra.db.DecoratedKey;
|
||||||
import org.apache.cassandra.db.guardrails.Guardrails;
|
import org.apache.cassandra.db.guardrails.Guardrails;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
|
|
@ -172,7 +172,7 @@ public final class Sets
|
||||||
values.add(t);
|
values.add(t);
|
||||||
}
|
}
|
||||||
MultiElements.DelayedValue value = new MultiElements.DelayedValue((MultiElementType<?>) receiver.type.unwrap(), values);
|
MultiElements.DelayedValue value = new MultiElements.DelayedValue((MultiElementType<?>) receiver.type.unwrap(), values);
|
||||||
return allTerminal ? value.bind(QueryOptions.DEFAULT) : value;
|
return allTerminal ? value.bind(FunctionContext.NONE) : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateAssignableTo(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
|
private void validateAssignableTo(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
|
||||||
|
|
@ -227,16 +227,16 @@ public final class Sets
|
||||||
super(column, t);
|
super(column, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
Term.Terminal value = t.bind(params.options);
|
Term.Terminal value = t.bind(builder);
|
||||||
if (value == UNSET_VALUE)
|
if (value == UNSET_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// delete + add
|
// delete + add
|
||||||
if (column.type.isMultiCell())
|
if (column.type.isMultiCell())
|
||||||
params.setComplexDeletionTimeForOverwrite(column);
|
builder.setComplexDeletionTimeForOverwrite(column);
|
||||||
Adder.doAdd(value, column, params);
|
Adder.doAdd(value, column, builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,15 +247,15 @@ public final class Sets
|
||||||
super(column, t);
|
super(column, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
assert column.type.isMultiCell() : "Attempted to add items to a frozen set";
|
assert column.type.isMultiCell() : "Attempted to add items to a frozen set";
|
||||||
Term.Terminal value = t.bind(params.options);
|
Term.Terminal value = t.bind(builder);
|
||||||
if (value != UNSET_VALUE)
|
if (value != UNSET_VALUE)
|
||||||
doAdd(value, column, params);
|
doAdd(value, column, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void doAdd(Term.Terminal value, ColumnMetadata column, UpdateParameters params) throws InvalidRequestException
|
static void doAdd(Term.Terminal value, ColumnMetadata column, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
SetType<?> type = (SetType<?>) column.type;
|
SetType<?> type = (SetType<?>) column.type;
|
||||||
|
|
||||||
|
|
@ -263,7 +263,7 @@ public final class Sets
|
||||||
{
|
{
|
||||||
// for frozen sets, we're overwriting the whole cell
|
// for frozen sets, we're overwriting the whole cell
|
||||||
if (!type.isMultiCell())
|
if (!type.isMultiCell())
|
||||||
params.addTombstone(column);
|
builder.addTombstone(column);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -278,7 +278,7 @@ public final class Sets
|
||||||
// Guardrails about collection size are only checked for the added elements without considering
|
// Guardrails about collection size are only checked for the added elements without considering
|
||||||
// already existent elements. This is done so to avoid read-before-write, having additional checks
|
// already existent elements. This is done so to avoid read-before-write, having additional checks
|
||||||
// during SSTable write.
|
// during SSTable write.
|
||||||
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, params.clientState);
|
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, builder.clientState);
|
||||||
|
|
||||||
int dataSize = 0;
|
int dataSize = 0;
|
||||||
for (ByteBuffer bb : elements)
|
for (ByteBuffer bb : elements)
|
||||||
|
|
@ -286,16 +286,16 @@ public final class Sets
|
||||||
if (bb == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
if (bb == ByteBufferUtil.UNSET_BYTE_BUFFER)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Cell<?> cell = params.addCell(column, CellPath.create(bb), ByteBufferUtil.EMPTY_BYTE_BUFFER);
|
Cell<?> cell = builder.addCell(column, CellPath.create(bb), ByteBufferUtil.EMPTY_BYTE_BUFFER);
|
||||||
dataSize += cell.dataSize();
|
dataSize += cell.dataSize();
|
||||||
}
|
}
|
||||||
Guardrails.collectionSetSize.guard(dataSize, column.name.toString(), false, params.clientState);
|
Guardrails.collectionSetSize.guard(dataSize, column.name.toString(), false, builder.clientState);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, params.clientState);
|
Guardrails.itemsPerCollection.guard(type.collectionSize(elements), column.name.toString(), false, builder.clientState);
|
||||||
Cell<?> cell = params.addCell(column, value.get());
|
Cell<?> cell = builder.addCell(column, value.get());
|
||||||
Guardrails.collectionSetSize.guard(cell.dataSize(), column.name.toString(), false, params.clientState);
|
Guardrails.collectionSetSize.guard(cell.dataSize(), column.name.toString(), false, builder.clientState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -308,11 +308,11 @@ public final class Sets
|
||||||
super(column, t);
|
super(column, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
assert column.type.isMultiCell() : "Attempted to remove items from a frozen set";
|
assert column.type.isMultiCell() : "Attempted to remove items from a frozen set";
|
||||||
|
|
||||||
Term.Terminal value = t.bind(params.options);
|
Term.Terminal value = t.bind(builder);
|
||||||
if (value == null || value == UNSET_VALUE)
|
if (value == null || value == UNSET_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -320,7 +320,7 @@ public final class Sets
|
||||||
List<ByteBuffer> toDiscard = value.getElements();
|
List<ByteBuffer> toDiscard = value.getElements();
|
||||||
|
|
||||||
for (ByteBuffer bb : toDiscard)
|
for (ByteBuffer bb : toDiscard)
|
||||||
params.addTombstone(column, CellPath.create(bb));
|
builder.addTombstone(column, CellPath.create(bb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,14 +331,14 @@ public final class Sets
|
||||||
super(column, k);
|
super(column, k);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
assert column.type.isMultiCell() : "Attempted to delete a single element in a frozen set";
|
assert column.type.isMultiCell() : "Attempted to delete a single element in a frozen set";
|
||||||
Term.Terminal elt = t.bind(params.options);
|
Term.Terminal elt = t.bind(builder);
|
||||||
if (elt == null)
|
if (elt == null)
|
||||||
throw new InvalidRequestException("Invalid null set element");
|
throw new InvalidRequestException("Invalid null set element");
|
||||||
|
|
||||||
params.addTombstone(column, CellPath.create(elt.get()));
|
builder.addTombstone(column, CellPath.create(elt.get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import org.apache.cassandra.cql3.CQLFragmentParser;
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.CqlParser;
|
import org.apache.cassandra.cql3.CqlParser;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
|
|
@ -77,10 +78,10 @@ public interface Term
|
||||||
* Bind the values in this term to the values contained in the {@code options}.
|
* Bind the values in this term to the values contained in the {@code options}.
|
||||||
* This is obviously a no-op if the term is Terminal.
|
* This is obviously a no-op if the term is Terminal.
|
||||||
*
|
*
|
||||||
* @param options the values to bind markers to.
|
* @param context the values to bind markers to.
|
||||||
* @return the {@code Terminal} resulting of binding the values contained in the {@code options}.
|
* @return the {@code Terminal} resulting of binding the values contained in the {@code options}.
|
||||||
*/
|
*/
|
||||||
Terminal bind(QueryOptions options);
|
Terminal bind(FunctionContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A shorter for {@code bind(options).get()}.
|
* A shorter for {@code bind(options).get()}.
|
||||||
|
|
@ -88,13 +89,13 @@ public interface Term
|
||||||
* object between the bind and the get (note that we still want to be able
|
* object between the bind and the get (note that we still want to be able
|
||||||
* to separate bind and get for collections).
|
* to separate bind and get for collections).
|
||||||
*/
|
*/
|
||||||
ByteBuffer bindAndGet(QueryOptions options);
|
ByteBuffer bindAndGet(FunctionContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return true if an optimized bindAndGetByteArray() method is implemented and can be used for this type of Term
|
* return true if an optimized bindAndGetByteArray() method is implemented and can be used for this type of Term
|
||||||
* to retrieve a value as byte[] instead of default ByteBuffer provided by bindAndGet()
|
* to retrieve a value as byte[] instead of default ByteBuffer provided by bindAndGet()
|
||||||
*/
|
*/
|
||||||
default boolean isByteArrayGetSupported(QueryOptions options)
|
default boolean isByteArrayGetSupported(FunctionContext context)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +103,7 @@ public interface Term
|
||||||
/**
|
/**
|
||||||
* an allocation-optimized version of bindAndGet() method
|
* an allocation-optimized version of bindAndGet() method
|
||||||
*/
|
*/
|
||||||
default byte[] bindAndGetByteArray(QueryOptions options) throws InvalidRequestException
|
default byte[] bindAndGetByteArray(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
throw new IllegalStateException("bindAndGetByteArray() method is not implemented, " +
|
throw new IllegalStateException("bindAndGetByteArray() method is not implemented, " +
|
||||||
"isByteArrayGetSupported() must be always checked before invoking this method");
|
"isByteArrayGetSupported() must be always checked before invoking this method");
|
||||||
|
|
@ -113,7 +114,7 @@ public interface Term
|
||||||
* We expose it mainly because for constants it can avoid allocating a temporary
|
* We expose it mainly because for constants it can avoid allocating a temporary
|
||||||
* object between the bind and the getElements.
|
* object between the bind and the getElements.
|
||||||
*/
|
*/
|
||||||
List<ByteBuffer> bindAndGetElements(QueryOptions options);
|
List<ByteBuffer> bindAndGetElements(FunctionContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether that term contains at least one bind marker.
|
* Whether that term contains at least one bind marker.
|
||||||
|
|
@ -250,7 +251,7 @@ public interface Term
|
||||||
public void collectMarkerSpecification(VariableSpecifications boundNames, Object owner) {}
|
public void collectMarkerSpecification(VariableSpecifications boundNames, Object owner) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminal bind(QueryOptions options) { return this; }
|
public Terminal bind(FunctionContext context) { return this; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addFunctionsTo(List<Function> functions)
|
public void addFunctionsTo(List<Function> functions)
|
||||||
|
|
@ -291,13 +292,13 @@ public interface Term
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer bindAndGet(QueryOptions options)
|
public ByteBuffer bindAndGet(FunctionContext context)
|
||||||
{
|
{
|
||||||
return get();
|
return get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ByteBuffer> bindAndGetElements(QueryOptions options)
|
public List<ByteBuffer> bindAndGetElements(FunctionContext context)
|
||||||
{
|
{
|
||||||
return getElements();
|
return getElements();
|
||||||
}
|
}
|
||||||
|
|
@ -318,16 +319,16 @@ public interface Term
|
||||||
abstract class NonTerminal implements Term
|
abstract class NonTerminal implements Term
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer bindAndGet(QueryOptions options) throws InvalidRequestException
|
public ByteBuffer bindAndGet(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
Terminal t = bind(options);
|
Terminal t = bind(context);
|
||||||
return t == null ? null : t.get();
|
return t == null ? null : t.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ByteBuffer> bindAndGetElements(QueryOptions options)
|
public List<ByteBuffer> bindAndGetElements(FunctionContext context)
|
||||||
{
|
{
|
||||||
Terminal t = bind(options);
|
Terminal t = bind(context);
|
||||||
return t == null ? Collections.emptyList() : t.getElements();
|
return t == null ? Collections.emptyList() : t.getElements();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.AssignmentTestable;
|
import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.cql3.terms.Term.NonTerminal;
|
import org.apache.cassandra.cql3.terms.Term.NonTerminal;
|
||||||
|
|
@ -104,25 +104,26 @@ public interface Terms
|
||||||
* Bind the values in these terms to the values contained in {@code options}.
|
* Bind the values in these terms to the values contained in {@code options}.
|
||||||
* This is obviously a no-op if this {@code Terms} are Terminals.
|
* This is obviously a no-op if this {@code Terms} are Terminals.
|
||||||
*
|
*
|
||||||
* @param options the query options containing the values to bind markers to.
|
* @param context the query options containing the values to bind markers to.
|
||||||
* @return the result of binding all the variables of these NonTerminals.
|
* @return the result of binding all the variables of these NonTerminals.
|
||||||
*/
|
*/
|
||||||
Terminals bind(QueryOptions options);
|
Terminals bind(FunctionContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A shorter for {@code bind(options).get()}.
|
* A shorter for {@code bind(options).get()}.
|
||||||
* We expose it mainly because for constants it can avoid allocating a temporary
|
* We expose it mainly because for constants it can avoid allocating a temporary
|
||||||
* object between the bind and the get.
|
* object between the bind and the get.
|
||||||
* @param options the query options containing the values to bind markers to.
|
*
|
||||||
|
* @param context the query options containing the values to bind markers to.
|
||||||
*/
|
*/
|
||||||
List<ByteBuffer> bindAndGet(QueryOptions options);
|
List<ByteBuffer> bindAndGet(FunctionContext context);
|
||||||
|
|
||||||
default boolean isSingleTerm(QueryOptions options)
|
default boolean isSingleTerm(FunctionContext context)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
default ByteBuffer bindAndGetSingleTermValue(QueryOptions options)
|
default ByteBuffer bindAndGetSingleTermValue(FunctionContext context)
|
||||||
{
|
{
|
||||||
throw new IllegalStateException("bindAndGetSingleTermValue() method is not implemented, " +
|
throw new IllegalStateException("bindAndGetSingleTermValue() method is not implemented, " +
|
||||||
"isSingleTerm() must be always checked before invoking this method");
|
"isSingleTerm() must be always checked before invoking this method");
|
||||||
|
|
@ -132,9 +133,10 @@ public interface Terms
|
||||||
* A shorter for {@code bind(options).getElements()}.
|
* A shorter for {@code bind(options).getElements()}.
|
||||||
* We expose it mainly because for constants it can avoid allocating a temporary
|
* We expose it mainly because for constants it can avoid allocating a temporary
|
||||||
* object between the {@code bind} and the {@code getElements}.
|
* object between the {@code bind} and the {@code getElements}.
|
||||||
* @param options the query options containing the values to bind markers to.
|
*
|
||||||
|
* @param context the query options containing the values to bind markers to.
|
||||||
*/
|
*/
|
||||||
List<List<ByteBuffer>> bindAndGetElements(QueryOptions options);
|
List<List<ByteBuffer>> bindAndGetElements(FunctionContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code Terms} containing a single {@code Term}.
|
* Creates a {@code Terms} containing a single {@code Term}.
|
||||||
|
|
@ -457,19 +459,19 @@ public interface Terms
|
||||||
public void collectMarkerSpecification(VariableSpecifications boundNames, Object owner) {}
|
public void collectMarkerSpecification(VariableSpecifications boundNames, Object owner) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Terminals bind(QueryOptions options)
|
public final Terminals bind(FunctionContext context)
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ByteBuffer> bindAndGet(QueryOptions options)
|
public List<ByteBuffer> bindAndGet(FunctionContext context)
|
||||||
{
|
{
|
||||||
return get();
|
return get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<List<ByteBuffer>> bindAndGetElements(QueryOptions options)
|
public List<List<ByteBuffer>> bindAndGetElements(FunctionContext context)
|
||||||
{
|
{
|
||||||
return getElements();
|
return getElements();
|
||||||
}
|
}
|
||||||
|
|
@ -628,34 +630,34 @@ public interface Terms
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminals bind(QueryOptions options)
|
public Terminals bind(FunctionContext context)
|
||||||
{
|
{
|
||||||
return Terminals.of(term.bind(options));
|
return Terminals.of(term.bind(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ByteBuffer> bindAndGet(QueryOptions options)
|
public List<ByteBuffer> bindAndGet(FunctionContext context)
|
||||||
{
|
{
|
||||||
return Collections.singletonList(term.bindAndGet(options));
|
return Collections.singletonList(term.bindAndGet(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSingleTerm(QueryOptions options)
|
public boolean isSingleTerm(FunctionContext context)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer bindAndGetSingleTermValue(QueryOptions options)
|
public ByteBuffer bindAndGetSingleTermValue(FunctionContext context)
|
||||||
{
|
{
|
||||||
return term.bindAndGet(options);
|
return term.bindAndGet(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<List<ByteBuffer>> bindAndGetElements(QueryOptions options)
|
public List<List<ByteBuffer>> bindAndGetElements(FunctionContext context)
|
||||||
{
|
{
|
||||||
return Collections.singletonList(term.bindAndGetElements(options));
|
return Collections.singletonList(term.bindAndGetElements(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -698,40 +700,40 @@ public interface Terms
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminals bind(QueryOptions options)
|
public Terminals bind(FunctionContext context)
|
||||||
{
|
{
|
||||||
int size = terms.size();
|
int size = terms.size();
|
||||||
List<Terminal> terminals = new ArrayList<>(size);
|
List<Terminal> terminals = new ArrayList<>(size);
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
Term term = terms.get(i);
|
Term term = terms.get(i);
|
||||||
terminals.add(term.bind(options));
|
terminals.add(term.bind(context));
|
||||||
}
|
}
|
||||||
return Terminals.of(terminals);
|
return Terminals.of(terminals);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ByteBuffer> bindAndGet(QueryOptions options)
|
public List<ByteBuffer> bindAndGet(FunctionContext context)
|
||||||
{
|
{
|
||||||
int size = terms.size();
|
int size = terms.size();
|
||||||
List<ByteBuffer> buffers = new ArrayList<>(size);
|
List<ByteBuffer> buffers = new ArrayList<>(size);
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
Term term = terms.get(i);
|
Term term = terms.get(i);
|
||||||
buffers.add(term.bindAndGet(options));
|
buffers.add(term.bindAndGet(context));
|
||||||
}
|
}
|
||||||
return buffers;
|
return buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<List<ByteBuffer>> bindAndGetElements(QueryOptions options)
|
public List<List<ByteBuffer>> bindAndGetElements(FunctionContext context)
|
||||||
{
|
{
|
||||||
int size = terms.size();
|
int size = terms.size();
|
||||||
List<List<ByteBuffer>> buffers = new ArrayList<>(size);
|
List<List<ByteBuffer>> buffers = new ArrayList<>(size);
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
Term term = terms.get(i);
|
Term term = terms.get(i);
|
||||||
buffers.add(term.bindAndGetElements(options));
|
buffers.add(term.bindAndGetElements(context));
|
||||||
}
|
}
|
||||||
return buffers;
|
return buffers;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import java.util.stream.StreamSupport;
|
||||||
import org.apache.cassandra.cql3.AssignmentTestable;
|
import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.ReversedType;
|
import org.apache.cassandra.db.marshal.ReversedType;
|
||||||
import org.apache.cassandra.db.marshal.TupleType;
|
import org.apache.cassandra.db.marshal.TupleType;
|
||||||
|
|
@ -88,7 +88,7 @@ public final class Tuples
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiElements.DelayedValue value = new MultiElements.DelayedValue(tupleType, values);
|
MultiElements.DelayedValue value = new MultiElements.DelayedValue(tupleType, values);
|
||||||
return allTerminal ? value.bind(QueryOptions.DEFAULT) : value;
|
return allTerminal ? value.bind(FunctionContext.NONE) : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestResult testAssignment(String keyspace, ColumnSpecification receiver)
|
public TestResult testAssignment(String keyspace, ColumnSpecification receiver)
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,9 @@ import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.FieldIdentifier;
|
import org.apache.cassandra.cql3.FieldIdentifier;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.Operation;
|
import org.apache.cassandra.cql3.Operation;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.RowUpdateBuilder;
|
||||||
import org.apache.cassandra.cql3.UpdateParameters;
|
|
||||||
import org.apache.cassandra.db.DecoratedKey;
|
import org.apache.cassandra.db.DecoratedKey;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.UserType;
|
import org.apache.cassandra.db.marshal.UserType;
|
||||||
|
|
@ -170,7 +170,7 @@ public final class UserTypes
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiElements.DelayedValue value = new MultiElements.DelayedValue(((UserType)receiver.type.unwrap()), values);
|
MultiElements.DelayedValue value = new MultiElements.DelayedValue(((UserType)receiver.type.unwrap()), values);
|
||||||
return allTerminal ? value.bind(QueryOptions.DEFAULT) : value;
|
return allTerminal ? value.bind(FunctionContext.NONE) : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateAssignableTo(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
|
private void validateAssignableTo(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
|
||||||
|
|
@ -220,9 +220,9 @@ public final class UserTypes
|
||||||
super(column, t);
|
super(column, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
Term.Terminal value = t.bind(params.options);
|
Term.Terminal value = t.bind(builder);
|
||||||
if (value == UNSET_VALUE)
|
if (value == UNSET_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -230,7 +230,7 @@ public final class UserTypes
|
||||||
if (type.isMultiCell())
|
if (type.isMultiCell())
|
||||||
{
|
{
|
||||||
// setting a whole UDT at once means we overwrite all cells, so delete existing cells
|
// setting a whole UDT at once means we overwrite all cells, so delete existing cells
|
||||||
params.setComplexDeletionTimeForOverwrite(column);
|
builder.setComplexDeletionTimeForOverwrite(column);
|
||||||
if (value == null)
|
if (value == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -243,16 +243,16 @@ public final class UserTypes
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CellPath fieldPath = type.cellPathForField(fieldName);
|
CellPath fieldPath = type.cellPathForField(fieldName);
|
||||||
params.addCell(column, fieldPath, buffer);
|
builder.addCell(column, fieldPath, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// for frozen UDTs, we're overwriting the whole cell value
|
// for frozen UDTs, we're overwriting the whole cell value
|
||||||
if (value == null)
|
if (value == null)
|
||||||
params.addTombstone(column);
|
builder.addTombstone(column);
|
||||||
else
|
else
|
||||||
params.addCell(column, value.get());
|
builder.addCell(column, value.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -267,20 +267,20 @@ public final class UserTypes
|
||||||
this.field = field;
|
this.field = field;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
// we should not get here for frozen UDTs
|
// we should not get here for frozen UDTs
|
||||||
assert column.type.isMultiCell() : "Attempted to set an individual field on a frozen UDT";
|
assert column.type.isMultiCell() : "Attempted to set an individual field on a frozen UDT";
|
||||||
|
|
||||||
Term.Terminal value = t.bind(params.options);
|
Term.Terminal value = t.bind(builder);
|
||||||
if (value == UNSET_VALUE)
|
if (value == UNSET_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CellPath fieldPath = ((UserType) column.type).cellPathForField(field);
|
CellPath fieldPath = ((UserType) column.type).cellPathForField(field);
|
||||||
if (value == null)
|
if (value == null)
|
||||||
params.addTombstone(column, fieldPath);
|
builder.addTombstone(column, fieldPath);
|
||||||
else
|
else
|
||||||
params.addCell(column, fieldPath, value.get());
|
builder.addCell(column, fieldPath, value.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -294,13 +294,13 @@ public final class UserTypes
|
||||||
this.field = field;
|
this.field = field;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(DecoratedKey partitionKey, UpdateParameters params) throws InvalidRequestException
|
public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
// we should not get here for frozen UDTs
|
// we should not get here for frozen UDTs
|
||||||
assert column.type.isMultiCell() : "Attempted to delete a single field from a frozen UDT";
|
assert column.type.isMultiCell() : "Attempted to delete a single field from a frozen UDT";
|
||||||
|
|
||||||
CellPath fieldPath = ((UserType) column.type).cellPathForField(field);
|
CellPath fieldPath = ((UserType) column.type).cellPathForField(field);
|
||||||
params.addTombstone(column, fieldPath);
|
builder.addTombstone(column, fieldPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import java.util.stream.Collectors;
|
||||||
import org.apache.cassandra.cql3.AssignmentTestable;
|
import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.VectorType;
|
import org.apache.cassandra.db.marshal.VectorType;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
|
|
@ -139,7 +139,7 @@ public final class Vectors
|
||||||
values.add(t);
|
values.add(t);
|
||||||
}
|
}
|
||||||
MultiElements.DelayedValue value = new MultiElements.DelayedValue(type, values);
|
MultiElements.DelayedValue value = new MultiElements.DelayedValue(type, values);
|
||||||
return allTerminal ? value.bind(QueryOptions.DEFAULT) : value;
|
return allTerminal ? value.bind(FunctionContext.NONE) : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
package org.apache.cassandra.cql3.transactions;
|
package org.apache.cassandra.cql3.transactions;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.terms.Term;
|
import org.apache.cassandra.cql3.terms.Term;
|
||||||
import org.apache.cassandra.db.marshal.AbstractType;
|
import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
|
|
@ -31,7 +31,7 @@ import static org.apache.cassandra.cql3.statements.RequestValidations.checkTrue;
|
||||||
|
|
||||||
public abstract class ReferenceValue
|
public abstract class ReferenceValue
|
||||||
{
|
{
|
||||||
public abstract TxnReferenceValue bindAndGet(QueryOptions options);
|
public abstract TxnReferenceValue bindAndGet(FunctionContext context);
|
||||||
|
|
||||||
public static abstract class Raw extends Term.Raw
|
public static abstract class Raw extends Term.Raw
|
||||||
{
|
{
|
||||||
|
|
@ -48,9 +48,9 @@ public abstract class ReferenceValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TxnReferenceValue bindAndGet(QueryOptions options)
|
public TxnReferenceValue bindAndGet(FunctionContext context)
|
||||||
{
|
{
|
||||||
return new TxnReferenceValue.Constant(term.bindAndGet(options));
|
return new TxnReferenceValue.Constant(term.bindAndGet(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Raw extends ReferenceValue.Raw
|
public static class Raw extends ReferenceValue.Raw
|
||||||
|
|
@ -104,9 +104,9 @@ public abstract class ReferenceValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TxnReferenceValue bindAndGet(QueryOptions options)
|
public TxnReferenceValue bindAndGet(FunctionContext context)
|
||||||
{
|
{
|
||||||
return new TxnReferenceValue.Substitution(reference.toTxnReference(options).asColumn());
|
return new TxnReferenceValue.Substitution(reference.toTxnReference(context).asColumn());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Raw extends ReferenceValue.Raw
|
public static class Raw extends ReferenceValue.Raw
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import org.apache.cassandra.cql3.AssignmentTestable;
|
||||||
import org.apache.cassandra.cql3.ColumnIdentifier;
|
import org.apache.cassandra.cql3.ColumnIdentifier;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.FieldIdentifier;
|
import org.apache.cassandra.cql3.FieldIdentifier;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.VariableSpecifications;
|
import org.apache.cassandra.cql3.VariableSpecifications;
|
||||||
import org.apache.cassandra.cql3.functions.Function;
|
import org.apache.cassandra.cql3.functions.Function;
|
||||||
import org.apache.cassandra.cql3.functions.types.utils.Bytes;
|
import org.apache.cassandra.cql3.functions.types.utils.Bytes;
|
||||||
|
|
@ -84,7 +84,7 @@ public class RowDataReference extends Term.NonTerminal
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminal bind(QueryOptions options) throws InvalidRequestException
|
public Terminal bind(FunctionContext context) throws InvalidRequestException
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
@ -174,20 +174,20 @@ public class RowDataReference extends Term.NonTerminal
|
||||||
return UserTypes.fieldSpecOf(column, field);
|
return UserTypes.fieldSpecOf(column, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CellPath bindCellPath(QueryOptions options)
|
private CellPath bindCellPath(FunctionContext context)
|
||||||
{
|
{
|
||||||
if (fieldPath != null)
|
if (fieldPath != null)
|
||||||
return fieldPath;
|
return fieldPath;
|
||||||
|
|
||||||
return elementPath != null ? CellPath.create(elementPath.bindAndGet(options)) : null;
|
return elementPath != null ? CellPath.create(elementPath.bindAndGet(context)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TxnReference toTxnReference(QueryOptions options)
|
public TxnReference toTxnReference(FunctionContext context)
|
||||||
{
|
{
|
||||||
Preconditions.checkState(elementPath == null || column.isComplex() || column.type.isFrozenCollection());
|
Preconditions.checkState(elementPath == null || column.isComplex() || column.type.isFrozenCollection());
|
||||||
Preconditions.checkState(fieldPath == null || column.isComplex() || column.type.isUDT());
|
Preconditions.checkState(fieldPath == null || column.isComplex() || column.type.isUDT());
|
||||||
|
|
||||||
return TxnReference.columnOrRow(txnDataName, table, column, bindCellPath(options));
|
return TxnReference.columnOrRow(txnDataName, table, column, bindCellPath(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ColumnIdentifier getFullyQualifiedName()
|
public ColumnIdentifier getFullyQualifiedName()
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,7 @@ import org.apache.cassandra.utils.concurrent.UncheckedInterruptedException;
|
||||||
import static org.apache.cassandra.concurrent.ExecutorFactory.Global.executorFactory;
|
import static org.apache.cassandra.concurrent.ExecutorFactory.Global.executorFactory;
|
||||||
import static org.apache.cassandra.config.DatabaseDescriptor.getFlushWriters;
|
import static org.apache.cassandra.config.DatabaseDescriptor.getFlushWriters;
|
||||||
import static org.apache.cassandra.db.commitlog.CommitLogPosition.NONE;
|
import static org.apache.cassandra.db.commitlog.CommitLogPosition.NONE;
|
||||||
|
import static org.apache.cassandra.db.compaction.CompactionManager.NO_GC;
|
||||||
import static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;
|
import static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;
|
||||||
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
|
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
|
||||||
import static org.apache.cassandra.utils.Throwables.maybeFail;
|
import static org.apache.cassandra.utils.Throwables.maybeFail;
|
||||||
|
|
@ -2011,9 +2012,19 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner
|
||||||
return paxosRepairHistory.get().getBallotForToken(key.getToken());
|
return paxosRepairHistory.get().getBallotForToken(key.getToken());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getDefaultGcBefore(long nowInSec)
|
||||||
|
{
|
||||||
|
// 2ndary indexes have ExpiringColumns too, so we need to purge tombstones deleted before now. We do not need to
|
||||||
|
// add any GcGrace however since 2ndary indexes are local to a node.
|
||||||
|
return isIndex() ? nowInSec : gcBefore(nowInSec);
|
||||||
|
}
|
||||||
|
|
||||||
public long gcBefore(long nowInSec)
|
public long gcBefore(long nowInSec)
|
||||||
{
|
{
|
||||||
return nowInSec - metadata().params.gcGraceSeconds;
|
TableMetadata metadata = metadata();
|
||||||
|
if (metadata.isAccordEnabled())
|
||||||
|
return NO_GC;
|
||||||
|
return nowInSec - metadata.params.gcGraceSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RefViewFragment selectAndReference(Function<View, Iterable<SSTableReader>> filter)
|
public RefViewFragment selectAndReference(Function<View, Iterable<SSTableReader>> filter)
|
||||||
|
|
|
||||||
|
|
@ -961,6 +961,9 @@ public abstract class ReadCommand extends AbstractReadQuery
|
||||||
ColumnFamilyStore cfs,
|
ColumnFamilyStore cfs,
|
||||||
ReadExecutionController controller)
|
ReadExecutionController controller)
|
||||||
{
|
{
|
||||||
|
if (nowInSec() == 0)
|
||||||
|
return iterator;
|
||||||
|
|
||||||
class WithoutPurgeableTombstones extends PurgeFunction
|
class WithoutPurgeableTombstones extends PurgeFunction
|
||||||
{
|
{
|
||||||
public WithoutPurgeableTombstones()
|
public WithoutPurgeableTombstones()
|
||||||
|
|
|
||||||
|
|
@ -224,7 +224,8 @@ public abstract class GroupMaker
|
||||||
{
|
{
|
||||||
input.add(argument);
|
input.add(argument);
|
||||||
|
|
||||||
// For computing groups we do not need to use the client protocol version.
|
// For computing groups we do not need to use the specific client protocol version.
|
||||||
|
selector.prepare(ProtocolVersion.CURRENT);
|
||||||
selector.addInput(input);
|
selector.addInput(input);
|
||||||
ByteBuffer output = selector.getOutput(ProtocolVersion.CURRENT);
|
ByteBuffer output = selector.getOutput(ProtocolVersion.CURRENT);
|
||||||
selector.reset();
|
selector.reset();
|
||||||
|
|
|
||||||
|
|
@ -195,7 +195,7 @@ public class CompactionIterator extends CompactionInfo.Holder implements Unfilte
|
||||||
private static IAccordService accord(AbstractCompactionController controller)
|
private static IAccordService accord(AbstractCompactionController controller)
|
||||||
{
|
{
|
||||||
IAccordService accord = AccordService.tryGetUnsafe();
|
IAccordService accord = AccordService.tryGetUnsafe();
|
||||||
Invariants.require(accord != null || (!isAccordJournal(controller.cfs) && !isAccordCommandsForKey(controller.cfs)));
|
Invariants.require(accord != null || !isAccordSystemTable(controller.cfs.metadata()));
|
||||||
return accord;
|
return accord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,19 +261,28 @@ public class CompactionIterator extends CompactionInfo.Holder implements Unfilte
|
||||||
|
|
||||||
private Transformation<UnfilteredRowIterator> purger(ColumnFamilyStore cfs, Supplier<AccordCompactionInfos> compactionInfos, Supplier<Version> version)
|
private Transformation<UnfilteredRowIterator> purger(ColumnFamilyStore cfs, Supplier<AccordCompactionInfos> compactionInfos, Supplier<Version> version)
|
||||||
{
|
{
|
||||||
if (isPaxos(cfs) && paxosStatePurging() != legacy)
|
TableMetadata metadata = cfs.metadata.get();
|
||||||
|
|
||||||
|
if (isPaxos(metadata) && paxosStatePurging() != legacy)
|
||||||
return new PaxosPurger();
|
return new PaxosPurger();
|
||||||
|
|
||||||
// Topologies uses regular deletion so it can use a regular Purger
|
// Topologies uses regular deletion so it can use a regular Purger
|
||||||
if (!requiresAccordSpecificPurger(cfs))
|
if (isAccordSystemTable(metadata))
|
||||||
return new Purger(controller, nowInSec);
|
{
|
||||||
|
if (isAccordJournal(metadata))
|
||||||
|
return new AccordJournalPurger(compactionInfos.get(), version.get(), cfs);
|
||||||
|
if (isAccordCommandsForKey(metadata))
|
||||||
|
return new AccordCommandsForKeyPurger(AccordKeyspace.CFKAccessor, compactionInfos);
|
||||||
|
|
||||||
if (isAccordJournal(cfs))
|
// at time of writing there are no other accord system tables,
|
||||||
return new AccordJournalPurger(compactionInfos.get(), version.get(), cfs);
|
// but unless otherwise stated additional tables should be treated as normal
|
||||||
if (isAccordCommandsForKey(cfs))
|
}
|
||||||
return new AccordCommandsForKeyPurger(AccordKeyspace.CFKAccessor, compactionInfos);
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Unhandled accord table: " + cfs.keyspace.getName() + '.' + cfs.name);
|
long nowInSec = this.nowInSec;
|
||||||
|
if (metadata.isAccordEnabled() || metadata.migratingFromAccord())
|
||||||
|
nowInSec = controller.gcBefore;
|
||||||
|
|
||||||
|
return new Purger(controller, nowInSec);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TableMetadata metadata()
|
public TableMetadata metadata()
|
||||||
|
|
@ -907,7 +916,7 @@ public class CompactionIterator extends CompactionInfo.Holder implements Unfilte
|
||||||
switch (key.type)
|
switch (key.type)
|
||||||
{
|
{
|
||||||
case COMMAND_DIFF:
|
case COMMAND_DIFF:
|
||||||
compactor = new AccordCommandRowCompactor(infos, userVersion, nowInSec);
|
compactor = new AccordCommandRowCompactor(infos, userVersion);
|
||||||
break;
|
break;
|
||||||
case TOPOLOGY_UPDATE:
|
case TOPOLOGY_UPDATE:
|
||||||
compactor = new TopologyCompactor(userVersion, infos.minEpoch);
|
compactor = new TopologyCompactor(userVersion, infos.minEpoch);
|
||||||
|
|
@ -1112,20 +1121,18 @@ public class CompactionIterator extends CompactionInfo.Holder implements Unfilte
|
||||||
final AccordCompactionInfos infos;
|
final AccordCompactionInfos infos;
|
||||||
final Version userVersion;
|
final Version userVersion;
|
||||||
final ColumnData userVersionCell;
|
final ColumnData userVersionCell;
|
||||||
final long nowInSec;
|
|
||||||
|
|
||||||
final CommandChanges mainBuilder = new CommandChanges();
|
final CommandChanges mainBuilder = new CommandChanges();
|
||||||
final List<AccordCommandRowEntry> entries = new ArrayList<>();
|
final List<AccordCommandRowEntry> entries = new ArrayList<>();
|
||||||
final ArrayDeque<AccordCommandRowEntry> reuseEntries = new ArrayDeque<>();
|
final ArrayDeque<AccordCommandRowEntry> reuseEntries = new ArrayDeque<>();
|
||||||
AccordCompactionInfo info;
|
AccordCompactionInfo info;
|
||||||
|
|
||||||
AccordCommandRowCompactor(AccordCompactionInfos infos, Version userVersion, long nowInSec)
|
AccordCommandRowCompactor(AccordCompactionInfos infos, Version userVersion)
|
||||||
{
|
{
|
||||||
super((CommandChangeSerializer) JournalKey.Type.COMMAND_DIFF.serializer);
|
super((CommandChangeSerializer) JournalKey.Type.COMMAND_DIFF.serializer);
|
||||||
this.infos = infos;
|
this.infos = infos;
|
||||||
this.userVersion = userVersion;
|
this.userVersion = userVersion;
|
||||||
this.userVersionCell = BufferCell.live(AccordKeyspace.JournalColumns.user_version, timestamp, Int32Type.instance.decompose(userVersion.version));
|
this.userVersionCell = BufferCell.live(AccordKeyspace.JournalColumns.user_version, timestamp, Int32Type.instance.decompose(userVersion.version));
|
||||||
this.nowInSec = nowInSec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -1258,30 +1265,23 @@ public class CompactionIterator extends CompactionInfo.Holder implements Unfilte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPaxos(ColumnFamilyStore cfs)
|
private static boolean isPaxos(TableMetadata metadata)
|
||||||
{
|
{
|
||||||
return cfs.name.equals(SystemKeyspace.PAXOS) && cfs.getKeyspaceName().equals(SchemaConstants.SYSTEM_KEYSPACE_NAME);
|
return metadata.name.equals(SystemKeyspace.PAXOS) && metadata.keyspace.equals(SchemaConstants.SYSTEM_KEYSPACE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean requiresAccordSpecificPurger(ColumnFamilyStore cfs)
|
private static boolean isAccordSystemTable(TableMetadata metadata)
|
||||||
{
|
{
|
||||||
return cfs.getKeyspaceName().equals(SchemaConstants.ACCORD_KEYSPACE_NAME) &&
|
return metadata.keyspace.equals(SchemaConstants.ACCORD_KEYSPACE_NAME);
|
||||||
(cfs.getTableName().contains(AccordKeyspace.JOURNAL) ||
|
|
||||||
AccordKeyspace.COMMANDS_FOR_KEY.equals(cfs.getTableName()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isAccordTable(ColumnFamilyStore cfs, String name)
|
private static boolean isAccordJournal(TableMetadata metadata)
|
||||||
{
|
{
|
||||||
return cfs.name.equals(name) && cfs.getKeyspaceName().equals(SchemaConstants.ACCORD_KEYSPACE_NAME);
|
return metadata.name.startsWith(AccordKeyspace.JOURNAL) && metadata.keyspace.equals(SchemaConstants.ACCORD_KEYSPACE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isAccordJournal(ColumnFamilyStore cfs)
|
private static boolean isAccordCommandsForKey(TableMetadata metadata)
|
||||||
{
|
{
|
||||||
return cfs.getKeyspaceName().equals(SchemaConstants.ACCORD_KEYSPACE_NAME) && cfs.name.startsWith(AccordKeyspace.JOURNAL);
|
return metadata.name.equals(AccordKeyspace.COMMANDS_FOR_KEY) && metadata.keyspace.equals(SchemaConstants.ACCORD_KEYSPACE_NAME);
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isAccordCommandsForKey(ColumnFamilyStore cfs)
|
|
||||||
{
|
|
||||||
return isAccordTable(cfs, AccordKeyspace.COMMANDS_FOR_KEY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,6 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
|
||||||
public final AtomicInteger currentlyBackgroundUpgrading = new AtomicInteger(0);
|
public final AtomicInteger currentlyBackgroundUpgrading = new AtomicInteger(0);
|
||||||
|
|
||||||
public static final int NO_GC = Integer.MIN_VALUE;
|
public static final int NO_GC = Integer.MIN_VALUE;
|
||||||
public static final int GC_ALL = Integer.MAX_VALUE;
|
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
|
|
@ -395,7 +394,7 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
|
||||||
}
|
}
|
||||||
|
|
||||||
CompactionStrategyManager strategy = cfs.getCompactionStrategyManager();
|
CompactionStrategyManager strategy = cfs.getCompactionStrategyManager();
|
||||||
tasks = strategy.getNextBackgroundTasks(getDefaultGcBefore(cfs, FBUtilities.nowInSeconds()));
|
tasks = strategy.getNextBackgroundTasks(cfs.getDefaultGcBefore(FBUtilities.nowInSeconds()));
|
||||||
if (tasks == null || tasks.isEmpty())
|
if (tasks == null || tasks.isEmpty())
|
||||||
{
|
{
|
||||||
if (DatabaseDescriptor.automaticSSTableUpgrade())
|
if (DatabaseDescriptor.automaticSSTableUpgrade())
|
||||||
|
|
@ -885,10 +884,10 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
|
||||||
public void execute(LifecycleTransaction txn) throws IOException
|
public void execute(LifecycleTransaction txn) throws IOException
|
||||||
{
|
{
|
||||||
logger.debug("Garbage collecting {}", txn.originals());
|
logger.debug("Garbage collecting {}", txn.originals());
|
||||||
CompactionTask task = new CompactionTask(cfStore, txn, getDefaultGcBefore(cfStore, FBUtilities.nowInSeconds()))
|
CompactionTask task = new CompactionTask(cfStore, txn, cfStore.getDefaultGcBefore(FBUtilities.nowInSeconds()))
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected CompactionController getCompactionController(Set<SSTableReader> toCompact)
|
protected CompactionController getCompactionController(Set<SSTableReader> toCompact, long gcBefore)
|
||||||
{
|
{
|
||||||
return new CompactionController(cfStore, toCompact, gcBefore, null, tombstoneOption);
|
return new CompactionController(cfStore, toCompact, gcBefore, null, tombstoneOption);
|
||||||
}
|
}
|
||||||
|
|
@ -1153,12 +1152,12 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
|
||||||
|
|
||||||
public void performMaximal(final ColumnFamilyStore cfStore, boolean splitOutput, int permittedParallelism)
|
public void performMaximal(final ColumnFamilyStore cfStore, boolean splitOutput, int permittedParallelism)
|
||||||
{
|
{
|
||||||
FBUtilities.waitOnFutures(submitMaximal(cfStore, getDefaultGcBefore(cfStore, FBUtilities.nowInSeconds()), splitOutput, permittedParallelism));
|
FBUtilities.waitOnFutures(submitMaximal(cfStore, cfStore.getDefaultGcBefore(FBUtilities.nowInSeconds()), splitOutput, permittedParallelism));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Future<?>> submitMaximal(final ColumnFamilyStore cfStore, boolean splitOutput, int permittedParallelism)
|
public List<Future<?>> submitMaximal(final ColumnFamilyStore cfStore, boolean splitOutput, int permittedParallelism)
|
||||||
{
|
{
|
||||||
return submitMaximal(cfStore, getDefaultGcBefore(cfStore, FBUtilities.nowInSeconds()), splitOutput, permittedParallelism);
|
return submitMaximal(cfStore, cfStore.getDefaultGcBefore(FBUtilities.nowInSeconds()), splitOutput, permittedParallelism);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Future<?>> submitMaximal(final ColumnFamilyStore cfStore, final long gcBefore, boolean splitOutput, int permittedParallelism)
|
public List<Future<?>> submitMaximal(final ColumnFamilyStore cfStore, final long gcBefore, boolean splitOutput, int permittedParallelism)
|
||||||
|
|
@ -1218,7 +1217,7 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
|
||||||
logger.debug("No sstables found for the provided token range");
|
logger.debug("No sstables found for the provided token range");
|
||||||
return CompactionTasks.empty();
|
return CompactionTasks.empty();
|
||||||
}
|
}
|
||||||
return cfStore.getCompactionStrategyManager().getUserDefinedTasks(sstables, getDefaultGcBefore(cfStore, FBUtilities.nowInSeconds()));
|
return cfStore.getCompactionStrategyManager().getUserDefinedTasks(sstables, cfStore.getDefaultGcBefore(FBUtilities.nowInSeconds()));
|
||||||
};
|
};
|
||||||
|
|
||||||
try (CompactionTasks tasks = cfStore.runWithCompactionsDisabled(taskCreator,
|
try (CompactionTasks tasks = cfStore.runWithCompactionsDisabled(taskCreator,
|
||||||
|
|
@ -1354,7 +1353,7 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
|
||||||
List<Future<?>> futures = new ArrayList<>(descriptors.size());
|
List<Future<?>> futures = new ArrayList<>(descriptors.size());
|
||||||
long nowInSec = FBUtilities.nowInSeconds();
|
long nowInSec = FBUtilities.nowInSeconds();
|
||||||
for (ColumnFamilyStore cfs : descriptors.keySet())
|
for (ColumnFamilyStore cfs : descriptors.keySet())
|
||||||
futures.add(submitUserDefined(cfs, descriptors.get(cfs), getDefaultGcBefore(cfs, nowInSec)));
|
futures.add(submitUserDefined(cfs, descriptors.get(cfs), cfs.getDefaultGcBefore(nowInSec)));
|
||||||
FBUtilities.waitOnFutures(futures);
|
FBUtilities.waitOnFutures(futures);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1645,7 +1644,7 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
|
||||||
long nowInSec = FBUtilities.nowInSeconds();
|
long nowInSec = FBUtilities.nowInSeconds();
|
||||||
try (SSTableRewriter writer = SSTableRewriter.construct(cfs, txn, false, sstable.maxDataAge);
|
try (SSTableRewriter writer = SSTableRewriter.construct(cfs, txn, false, sstable.maxDataAge);
|
||||||
ISSTableScanner scanner = cleanupStrategy.getScanner(sstable);
|
ISSTableScanner scanner = cleanupStrategy.getScanner(sstable);
|
||||||
CompactionController controller = new CompactionController(cfs, txn.originals(), getDefaultGcBefore(cfs, nowInSec));
|
CompactionController controller = new CompactionController(cfs, txn.originals(), cfs.getDefaultGcBefore(nowInSec));
|
||||||
Refs<SSTableReader> refs = Refs.ref(Collections.singleton(sstable));
|
Refs<SSTableReader> refs = Refs.ref(Collections.singleton(sstable));
|
||||||
CompactionIterator ci = new CompactionIterator(OperationType.CLEANUP, Collections.singletonList(scanner), controller, nowInSec, nextTimeUUID(), active, null))
|
CompactionIterator ci = new CompactionIterator(OperationType.CLEANUP, Collections.singletonList(scanner), controller, nowInSec, nextTimeUUID(), active, null))
|
||||||
{
|
{
|
||||||
|
|
@ -1992,7 +1991,7 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
|
||||||
SSTableRewriter unrepairedWriter = SSTableRewriter.constructWithoutEarlyOpening(sharedTxn, false, groupMaxDataAge);
|
SSTableRewriter unrepairedWriter = SSTableRewriter.constructWithoutEarlyOpening(sharedTxn, false, groupMaxDataAge);
|
||||||
|
|
||||||
AbstractCompactionStrategy.ScannerList scanners = strategy.getScanners(txn.originals());
|
AbstractCompactionStrategy.ScannerList scanners = strategy.getScanners(txn.originals());
|
||||||
CompactionController controller = new CompactionController(cfs, sstableAsSet, getDefaultGcBefore(cfs, nowInSec));
|
CompactionController controller = new CompactionController(cfs, sstableAsSet, cfs.getDefaultGcBefore(nowInSec));
|
||||||
CompactionIterator ci = getAntiCompactionIterator(scanners.scanners, controller, nowInSec, nextTimeUUID(), active, isCancelled))
|
CompactionIterator ci = getAntiCompactionIterator(scanners.scanners, controller, nowInSec, nextTimeUUID(), active, isCancelled))
|
||||||
{
|
{
|
||||||
int expectedBloomFilterSize = Math.max(cfs.metadata().params.minIndexInterval, (int)(SSTableReader.getApproximateKeyCount(sstableAsSet)));
|
int expectedBloomFilterSize = Math.max(cfs.metadata().params.minIndexInterval, (int)(SSTableReader.getApproximateKeyCount(sstableAsSet)));
|
||||||
|
|
@ -2178,13 +2177,6 @@ public class CompactionManager implements CompactionManagerMBean, ICompactionMan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getDefaultGcBefore(ColumnFamilyStore cfs, long nowInSec)
|
|
||||||
{
|
|
||||||
// 2ndary indexes have ExpiringColumns too, so we need to purge tombstones deleted before now. We do not need to
|
|
||||||
// add any GcGrace however since 2ndary indexes are local to a node.
|
|
||||||
return cfs.isIndex() ? nowInSec : cfs.gcBefore(nowInSec);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Future<Long> submitViewBuilder(final ViewBuilderTask task)
|
public Future<Long> submitViewBuilder(final ViewBuilderTask task)
|
||||||
{
|
{
|
||||||
return submitViewBuilder(task, active);
|
return submitViewBuilder(task, active);
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,12 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import accord.local.CommandStores;
|
||||||
|
import accord.local.CommandStores.StoreFinder;
|
||||||
|
import accord.local.Node;
|
||||||
|
import accord.primitives.Ranges;
|
||||||
|
import accord.utils.Invariants;
|
||||||
|
|
||||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||||
import org.apache.cassandra.db.ColumnFamilyStore;
|
import org.apache.cassandra.db.ColumnFamilyStore;
|
||||||
import org.apache.cassandra.db.Directories;
|
import org.apache.cassandra.db.Directories;
|
||||||
|
|
@ -55,7 +61,11 @@ import org.apache.cassandra.io.sstable.ISSTableScanner;
|
||||||
import org.apache.cassandra.io.sstable.format.SSTableReader;
|
import org.apache.cassandra.io.sstable.format.SSTableReader;
|
||||||
import org.apache.cassandra.io.sstable.metadata.MetadataCollector;
|
import org.apache.cassandra.io.sstable.metadata.MetadataCollector;
|
||||||
import org.apache.cassandra.io.util.File;
|
import org.apache.cassandra.io.util.File;
|
||||||
|
import org.apache.cassandra.schema.TableMetadata;
|
||||||
import org.apache.cassandra.service.ActiveRepairService;
|
import org.apache.cassandra.service.ActiveRepairService;
|
||||||
|
import org.apache.cassandra.service.accord.AccordService;
|
||||||
|
import org.apache.cassandra.service.accord.TokenRange;
|
||||||
|
import org.apache.cassandra.service.accord.api.TokenKey;
|
||||||
import org.apache.cassandra.service.snapshot.SnapshotManager;
|
import org.apache.cassandra.service.snapshot.SnapshotManager;
|
||||||
import org.apache.cassandra.service.snapshot.SnapshotOptions;
|
import org.apache.cassandra.service.snapshot.SnapshotOptions;
|
||||||
import org.apache.cassandra.service.snapshot.SnapshotType;
|
import org.apache.cassandra.service.snapshot.SnapshotType;
|
||||||
|
|
@ -63,6 +73,8 @@ import org.apache.cassandra.utils.FBUtilities;
|
||||||
import org.apache.cassandra.utils.TimeUUID;
|
import org.apache.cassandra.utils.TimeUUID;
|
||||||
import org.apache.cassandra.utils.concurrent.Refs;
|
import org.apache.cassandra.utils.concurrent.Refs;
|
||||||
|
|
||||||
|
import static accord.local.RedundantStatus.Property.LOCALLY_APPLIED;
|
||||||
|
import static org.apache.cassandra.db.compaction.CompactionManager.NO_GC;
|
||||||
import static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;
|
import static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;
|
||||||
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
|
import static org.apache.cassandra.utils.Clock.Global.nanoTime;
|
||||||
|
|
||||||
|
|
@ -71,20 +83,20 @@ public class CompactionTask extends AbstractCompactionTask
|
||||||
private static final int MEGABYTE = 1024 * 1024;
|
private static final int MEGABYTE = 1024 * 1024;
|
||||||
protected static final Logger logger = LoggerFactory.getLogger(CompactionTask.class);
|
protected static final Logger logger = LoggerFactory.getLogger(CompactionTask.class);
|
||||||
|
|
||||||
protected final long gcBefore;
|
protected final long gcBeforeSeconds;
|
||||||
protected final boolean keepOriginals;
|
protected final boolean keepOriginals;
|
||||||
protected static long totalBytesCompacted = 0;
|
protected static long totalBytesCompacted = 0;
|
||||||
private ActiveCompactionsTracker activeCompactions;
|
private ActiveCompactionsTracker activeCompactions;
|
||||||
|
|
||||||
public CompactionTask(ColumnFamilyStore cfs, ILifecycleTransaction txn, long gcBefore)
|
public CompactionTask(ColumnFamilyStore cfs, ILifecycleTransaction txn, long gcBeforeSeconds)
|
||||||
{
|
{
|
||||||
this(cfs, txn, gcBefore, false);
|
this(cfs, txn, gcBeforeSeconds, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompactionTask(ColumnFamilyStore cfs, ILifecycleTransaction txn, long gcBefore, boolean keepOriginals)
|
public CompactionTask(ColumnFamilyStore cfs, ILifecycleTransaction txn, long gcBeforeSeconds, boolean keepOriginals)
|
||||||
{
|
{
|
||||||
super(cfs, txn);
|
super(cfs, txn);
|
||||||
this.gcBefore = gcBefore;
|
this.gcBeforeSeconds = gcBeforeSeconds;
|
||||||
this.keepOriginals = keepOriginals;
|
this.keepOriginals = keepOriginals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -546,7 +558,33 @@ public class CompactionTask extends AbstractCompactionTask
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CompactionController getCompactionController(Set<SSTableReader> toCompact)
|
protected final CompactionController getCompactionController(Set<SSTableReader> toCompact)
|
||||||
|
{
|
||||||
|
long gcBeforeSeconds = this.gcBeforeSeconds;
|
||||||
|
TableMetadata metadata = cfs.metadata();
|
||||||
|
if (metadata.isAccordEnabled())
|
||||||
|
{
|
||||||
|
Invariants.expect(gcBeforeSeconds <= 0);
|
||||||
|
TokenRange[] rs = new TokenRange[toCompact.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (SSTableReader reader : toCompact)
|
||||||
|
rs[i++] = TokenRange.create(TokenKey.before(metadata.id, reader.getFirst().getToken()), TokenKey.after(metadata.id, reader.getLast().getToken()));
|
||||||
|
Ranges ranges = Ranges.of(rs);
|
||||||
|
Node node = AccordService.unsafeInstance().node();
|
||||||
|
// TODO (expected): we shouldn't need to limit to universalBefore, but this is a safety margin esp. against bugs with repairing tombstones or incomplete information in CommandStore;
|
||||||
|
// we should impose stronger guarantees on incoming streams (that they don't contain tombstones), and validate our CommandStore-derived bounds
|
||||||
|
gcBeforeSeconds = node.durableBefore().foldlWithDefault(ranges, (e, v) -> e == null ? NO_GC : Math.min(e.universal.hlc(), v), null, Long.MAX_VALUE);
|
||||||
|
CommandStores.StoreSelector selector = StoreFinder.selector(ranges, Long.MIN_VALUE, Long.MAX_VALUE);
|
||||||
|
gcBeforeSeconds = node.commandStores().mapReduceUnsafe(selector, commandStore -> commandStore.unsafeGetRedundantBefore().foldl(ranges, (bs, v) -> bs.maxBound(LOCALLY_APPLIED).hlc(), Long.MAX_VALUE), Math::min, gcBeforeSeconds);
|
||||||
|
if (gcBeforeSeconds == Long.MAX_VALUE)
|
||||||
|
gcBeforeSeconds = NO_GC;
|
||||||
|
else
|
||||||
|
gcBeforeSeconds = TimeUnit.MICROSECONDS.toSeconds(gcBeforeSeconds);
|
||||||
|
}
|
||||||
|
return getCompactionController(toCompact, gcBeforeSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CompactionController getCompactionController(Set<SSTableReader> toCompact, long gcBefore)
|
||||||
{
|
{
|
||||||
return new CompactionController(cfs, toCompact, gcBefore);
|
return new CompactionController(cfs, toCompact, gcBefore);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ public class SSTableSplitter
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CompactionController getCompactionController(Set<SSTableReader> toCompact)
|
protected CompactionController getCompactionController(Set<SSTableReader> toCompact, long gcBefore)
|
||||||
{
|
{
|
||||||
return new SplitController(cfs);
|
return new SplitController(cfs);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ public class TimeWindowCompactionTask extends CompactionTask
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompactionController getCompactionController(Set<SSTableReader> toCompact)
|
public CompactionController getCompactionController(Set<SSTableReader> toCompact, long gcBefore)
|
||||||
{
|
{
|
||||||
return new TimeWindowCompactionController(cfs, toCompact, gcBefore, ignoreOverlaps);
|
return new TimeWindowCompactionController(cfs, toCompact, gcBefore, ignoreOverlaps);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
import org.apache.cassandra.cql3.Duration;
|
import org.apache.cassandra.cql3.Duration;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.terms.Constants;
|
import org.apache.cassandra.cql3.terms.Constants;
|
||||||
import org.apache.cassandra.cql3.terms.Term;
|
import org.apache.cassandra.cql3.terms.Term;
|
||||||
import org.apache.cassandra.serializers.MarshalException;
|
import org.apache.cassandra.serializers.MarshalException;
|
||||||
|
|
@ -32,7 +33,6 @@ import org.apache.cassandra.utils.bytecomparable.ByteSource;
|
||||||
import org.apache.cassandra.utils.bytecomparable.ByteSourceInverse;
|
import org.apache.cassandra.utils.bytecomparable.ByteSourceInverse;
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
import static org.apache.cassandra.utils.TimeUUID.Generator.nextTimeUUIDAsBytes;
|
|
||||||
|
|
||||||
// Fully compatible with UUID, and indeed is interpreted as UUID for UDF
|
// Fully compatible with UUID, and indeed is interpreted as UUID for UDF
|
||||||
public abstract class AbstractTimeUUIDType<T> extends TemporalType<T>
|
public abstract class AbstractTimeUUIDType<T> extends TemporalType<T>
|
||||||
|
|
@ -218,9 +218,9 @@ public abstract class AbstractTimeUUIDType<T> extends TemporalType<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer now()
|
public ByteBuffer now(FunctionContext context)
|
||||||
{
|
{
|
||||||
return ByteBuffer.wrap(nextTimeUUIDAsBytes());
|
return ByteBuffer.wrap(context.nextTimeUUIDAsBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,10 @@ import java.nio.ByteBuffer;
|
||||||
import org.apache.commons.lang3.mutable.MutableLong;
|
import org.apache.commons.lang3.mutable.MutableLong;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.Duration;
|
import org.apache.cassandra.cql3.Duration;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.ArgumentDeserializer;
|
import org.apache.cassandra.cql3.functions.ArgumentDeserializer;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
|
|
||||||
import static org.apache.cassandra.utils.Clock.Global.currentTimeMillis;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base type for temporal types (timestamp, date ...).
|
* Base type for temporal types (timestamp, date ...).
|
||||||
*
|
*
|
||||||
|
|
@ -42,9 +41,9 @@ public abstract class TemporalType<T> extends AbstractType<T>
|
||||||
* Returns the current temporal value.
|
* Returns the current temporal value.
|
||||||
* @return the current temporal value.
|
* @return the current temporal value.
|
||||||
*/
|
*/
|
||||||
public ByteBuffer now()
|
public ByteBuffer now(FunctionContext context)
|
||||||
{
|
{
|
||||||
return fromTimeInMillis(currentTimeMillis());
|
return fromTimeInMillis(context.nowMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import java.time.LocalTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
|
||||||
import org.apache.cassandra.cql3.CQL3Type;
|
import org.apache.cassandra.cql3.CQL3Type;
|
||||||
|
import org.apache.cassandra.cql3.FunctionContext;
|
||||||
import org.apache.cassandra.cql3.functions.ArgumentDeserializer;
|
import org.apache.cassandra.cql3.functions.ArgumentDeserializer;
|
||||||
import org.apache.cassandra.cql3.terms.Constants;
|
import org.apache.cassandra.cql3.terms.Constants;
|
||||||
import org.apache.cassandra.cql3.terms.Term;
|
import org.apache.cassandra.cql3.terms.Term;
|
||||||
|
|
@ -110,9 +111,10 @@ public class TimeType extends TemporalType<Long>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer now()
|
public ByteBuffer now(FunctionContext context)
|
||||||
{
|
{
|
||||||
return decompose(LocalTime.now(ZoneOffset.UTC).toNanoOfDay());
|
long nanoOfDay = LocalTime.ofInstant(context.now(), ZoneOffset.UTC).toNanoOfDay();
|
||||||
|
return decompose(nanoOfDay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,6 @@ public abstract class AbstractBTreePartition implements Partition, Iterable<Row>
|
||||||
if (rt != null && rt.deletionTime().supersedes(activeDeletion))
|
if (rt != null && rt.deletionTime().supersedes(activeDeletion))
|
||||||
activeDeletion = rt.deletionTime();
|
activeDeletion = rt.deletionTime();
|
||||||
|
|
||||||
|
|
||||||
if (row == null)
|
if (row == null)
|
||||||
{
|
{
|
||||||
// this means our partition level deletion supersedes all other deletions and we don't have to keep the row deletions
|
// this means our partition level deletion supersedes all other deletions and we don't have to keep the row deletions
|
||||||
|
|
|
||||||
|
|
@ -99,13 +99,6 @@ public class CassandraValidationIterator extends ValidationPartitionIterator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getDefaultGcBefore(ColumnFamilyStore cfs, long nowInSec)
|
|
||||||
{
|
|
||||||
// 2ndary indexes have ExpiringColumns too, so we need to purge tombstones deleted before now. We do not need to
|
|
||||||
// add any GcGrace however since 2ndary indexes are local to a node.
|
|
||||||
return cfs.isIndex() ? nowInSec : cfs.gcBefore(nowInSec);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ValidationCompactionIterator extends CompactionIterator
|
private static class ValidationCompactionIterator extends CompactionIterator
|
||||||
{
|
{
|
||||||
public ValidationCompactionIterator(List<ISSTableScanner> scanners, ValidationCompactionController controller, long nowInSec, ActiveCompactionsTracker activeCompactions, TopPartitionTracker.Collector topPartitionCollector)
|
public ValidationCompactionIterator(List<ISSTableScanner> scanners, ValidationCompactionController controller, long nowInSec, ActiveCompactionsTracker activeCompactions, TopPartitionTracker.Collector topPartitionCollector)
|
||||||
|
|
@ -219,7 +212,7 @@ public class CassandraValidationIterator extends ValidationPartitionIterator
|
||||||
cfs.getKeyspaceName(),
|
cfs.getKeyspaceName(),
|
||||||
cfs.getTableName());
|
cfs.getTableName());
|
||||||
|
|
||||||
long gcBefore = dontPurgeTombstones ? Long.MIN_VALUE : getDefaultGcBefore(cfs, nowInSec);
|
long gcBefore = dontPurgeTombstones ? Long.MIN_VALUE : cfs.getDefaultGcBefore(nowInSec);
|
||||||
controller = new ValidationCompactionController(cfs, gcBefore);
|
controller = new ValidationCompactionController(cfs, gcBefore);
|
||||||
scanners = cfs.getCompactionStrategyManager().getScanners(sstables, ranges);
|
scanners = cfs.getCompactionStrategyManager().getScanners(sstables, ranges);
|
||||||
ci = new ValidationCompactionIterator(scanners.scanners, controller, nowInSec, CompactionManager.instance.active, topPartitionCollector);
|
ci = new ValidationCompactionIterator(scanners.scanners, controller, nowInSec, CompactionManager.instance.active, topPartitionCollector);
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,8 @@ import org.apache.cassandra.config.DatabaseDescriptor;
|
||||||
import org.apache.cassandra.cql3.ColumnSpecification;
|
import org.apache.cassandra.cql3.ColumnSpecification;
|
||||||
import org.apache.cassandra.cql3.QueryOptions;
|
import org.apache.cassandra.cql3.QueryOptions;
|
||||||
import org.apache.cassandra.cql3.QueryProcessor;
|
import org.apache.cassandra.cql3.QueryProcessor;
|
||||||
import org.apache.cassandra.cql3.UpdateParameters;
|
import org.apache.cassandra.cql3.RowUpdateBuilder;
|
||||||
|
import org.apache.cassandra.cql3.RowUpdateBuilder.RegularRowUpdateBuilder;
|
||||||
import org.apache.cassandra.cql3.functions.types.TypeCodec;
|
import org.apache.cassandra.cql3.functions.types.TypeCodec;
|
||||||
import org.apache.cassandra.cql3.functions.types.UserType;
|
import org.apache.cassandra.cql3.functions.types.UserType;
|
||||||
import org.apache.cassandra.cql3.statements.ModificationStatement;
|
import org.apache.cassandra.cql3.statements.ModificationStatement;
|
||||||
|
|
@ -285,13 +286,13 @@ public class CQLSSTableWriter implements Closeable
|
||||||
long now = currentTimeMillis();
|
long now = currentTimeMillis();
|
||||||
// Note that we asks indexes to not validate values (the last 'false' arg below) because that triggers a 'Keyspace.open'
|
// Note that we asks indexes to not validate values (the last 'false' arg below) because that triggers a 'Keyspace.open'
|
||||||
// and that forces a lot of initialization that we don't want.
|
// and that forces a lot of initialization that we don't want.
|
||||||
UpdateParameters params = new UpdateParameters(modificationStatement.metadata,
|
RowUpdateBuilder builder = new RegularRowUpdateBuilder(modificationStatement.metadata,
|
||||||
ClientState.forInternalCalls(),
|
ClientState.forInternalCalls(),
|
||||||
options,
|
options,
|
||||||
modificationStatement.getTimestamp(TimeUnit.MILLISECONDS.toMicros(now), options),
|
modificationStatement.getTimestamp(TimeUnit.MILLISECONDS.toMicros(now), options),
|
||||||
options.getNowInSec((int) TimeUnit.MILLISECONDS.toSeconds(now)),
|
options.getNowInSec((int) TimeUnit.MILLISECONDS.toSeconds(now)),
|
||||||
modificationStatement.getTimeToLive(options),
|
modificationStatement.getTimeToLive(options),
|
||||||
Collections.emptyMap());
|
null);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -302,7 +303,7 @@ public class CQLSSTableWriter implements Closeable
|
||||||
for (ByteBuffer key : keys)
|
for (ByteBuffer key : keys)
|
||||||
{
|
{
|
||||||
for (Slice slice : slices)
|
for (Slice slice : slices)
|
||||||
modificationStatement.addUpdateForKey(writer.getUpdateFor(key), slice, params);
|
modificationStatement.addUpdateForKey(writer.getUpdateFor(key), slice, builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -312,7 +313,7 @@ public class CQLSSTableWriter implements Closeable
|
||||||
for (ByteBuffer key : keys)
|
for (ByteBuffer key : keys)
|
||||||
{
|
{
|
||||||
for (Clustering clustering : clusterings)
|
for (Clustering clustering : clusterings)
|
||||||
modificationStatement.addUpdateForKey(writer.getUpdateFor(key), clustering, params);
|
modificationStatement.addUpdateForKey(writer.getUpdateFor(key), clustering, builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@ public class RepairSession extends AsyncFuture<RepairSessionResult> implements I
|
||||||
public final boolean isIncremental;
|
public final boolean isIncremental;
|
||||||
public final boolean allReplicas;
|
public final boolean allReplicas;
|
||||||
public final PreviewKind previewKind;
|
public final PreviewKind previewKind;
|
||||||
|
// TODO (expected): introduce forceRepairData and ignore repairData for Accord tables
|
||||||
public final boolean repairData;
|
public final boolean repairData;
|
||||||
public final boolean repairPaxos;
|
public final boolean repairPaxos;
|
||||||
public final boolean repairAccord;
|
public final boolean repairAccord;
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,6 @@ abstract class AccordExecutorAbstractLockLoop extends AccordExecutorAbstractLoop
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
Thread self = Thread.currentThread();
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
Task task = null;
|
Task task = null;
|
||||||
while (true)
|
while (true)
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,9 @@ import org.apache.cassandra.dht.Murmur3Partitioner;
|
||||||
import org.apache.cassandra.schema.TableId;
|
import org.apache.cassandra.schema.TableId;
|
||||||
import org.apache.cassandra.service.accord.api.PartitionKey;
|
import org.apache.cassandra.service.accord.api.PartitionKey;
|
||||||
import org.apache.cassandra.service.accord.api.TokenKey;
|
import org.apache.cassandra.service.accord.api.TokenKey;
|
||||||
import org.apache.cassandra.service.accord.serializers.ResultSerializers;
|
|
||||||
import org.apache.cassandra.service.accord.serializers.TableMetadatasAndKeys;
|
import org.apache.cassandra.service.accord.serializers.TableMetadatasAndKeys;
|
||||||
import org.apache.cassandra.service.accord.txn.AccordUpdate;
|
import org.apache.cassandra.service.accord.txn.AccordUpdate;
|
||||||
|
import org.apache.cassandra.service.accord.txn.TxnDataResult;
|
||||||
import org.apache.cassandra.service.accord.txn.TxnQuery;
|
import org.apache.cassandra.service.accord.txn.TxnQuery;
|
||||||
import org.apache.cassandra.service.accord.txn.TxnRead;
|
import org.apache.cassandra.service.accord.txn.TxnRead;
|
||||||
import org.apache.cassandra.service.accord.txn.TxnWrite;
|
import org.apache.cassandra.service.accord.txn.TxnWrite;
|
||||||
|
|
@ -318,7 +318,7 @@ public class AccordObjectSizes
|
||||||
builder.waitingOn(WaitingOn.empty(Domain.Key));
|
builder.waitingOn(WaitingOn.empty(Domain.Key));
|
||||||
|
|
||||||
if (saveStatus.known.is(Known.Outcome.Apply))
|
if (saveStatus.known.is(Known.Outcome.Apply))
|
||||||
builder.result(ResultSerializers.APPLIED);
|
builder.result(TxnDataResult.PERSISTABLE);
|
||||||
|
|
||||||
return builder.build(saveStatus);
|
return builder.build(saveStatus);
|
||||||
}
|
}
|
||||||
|
|
@ -400,6 +400,7 @@ public class AccordObjectSizes
|
||||||
size += sizeNullable(command.partialDeps(), AccordObjectSizes::dependencies);
|
size += sizeNullable(command.partialDeps(), AccordObjectSizes::dependencies);
|
||||||
size += sizeNullable(command.acceptedOrCommitted(), AccordObjectSizes::timestamp);
|
size += sizeNullable(command.acceptedOrCommitted(), AccordObjectSizes::timestamp);
|
||||||
size += sizeNullable(command.writes(), AccordObjectSizes::writes);
|
size += sizeNullable(command.writes(), AccordObjectSizes::writes);
|
||||||
|
// no need to measure command.results(), as should always be a sentinel value
|
||||||
size += sizeNullable(command.waitingOn(), AccordObjectSizes::waitingOn);
|
size += sizeNullable(command.waitingOn(), AccordObjectSizes::waitingOn);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,11 @@ public final class TokenKey extends AccordRoutableKey implements RoutingKey, Ran
|
||||||
return new TokenKey(table, BEFORE_TOKEN_SENTINEL, token);
|
return new TokenKey(table, BEFORE_TOKEN_SENTINEL, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TokenKey after(TableId table, Token token)
|
||||||
|
{
|
||||||
|
return new TokenKey(table, AFTER_TOKEN_SENTINEL, token);
|
||||||
|
}
|
||||||
|
|
||||||
public static final NoTableSerializer noTableSerializer = new NoTableSerializer();
|
public static final NoTableSerializer noTableSerializer = new NoTableSerializer();
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,9 @@ import org.apache.cassandra.io.util.DataOutputPlus;
|
||||||
import org.apache.cassandra.journal.Journal;
|
import org.apache.cassandra.journal.Journal;
|
||||||
import org.apache.cassandra.service.accord.serializers.CommandSerializers;
|
import org.apache.cassandra.service.accord.serializers.CommandSerializers;
|
||||||
import org.apache.cassandra.service.accord.serializers.DepsSerializers;
|
import org.apache.cassandra.service.accord.serializers.DepsSerializers;
|
||||||
import org.apache.cassandra.service.accord.serializers.ResultSerializers;
|
|
||||||
import org.apache.cassandra.service.accord.serializers.Version;
|
import org.apache.cassandra.service.accord.serializers.Version;
|
||||||
import org.apache.cassandra.service.accord.serializers.WaitingOnSerializer;
|
import org.apache.cassandra.service.accord.serializers.WaitingOnSerializer;
|
||||||
|
import org.apache.cassandra.service.accord.txn.TxnDataResult;
|
||||||
|
|
||||||
import static accord.impl.CommandChange.anyFieldChanged;
|
import static accord.impl.CommandChange.anyFieldChanged;
|
||||||
import static accord.impl.CommandChange.describeFlags;
|
import static accord.impl.CommandChange.describeFlags;
|
||||||
|
|
@ -140,7 +140,7 @@ public class CommandChangeWriter implements Journal.Writer
|
||||||
CommandSerializers.writes.serialize(command.writes(), out, userVersion);
|
CommandSerializers.writes.serialize(command.writes(), out, userVersion);
|
||||||
break;
|
break;
|
||||||
case RESULT:
|
case RESULT:
|
||||||
ResultSerializers.result.serialize(command.result(), out);
|
TxnDataResult.persistable.serialize(command.result(), out);
|
||||||
break;
|
break;
|
||||||
case CLEANUP:
|
case CLEANUP:
|
||||||
Cleanup cleanup;
|
Cleanup cleanup;
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,9 @@ import org.apache.cassandra.io.util.DataOutputPlus;
|
||||||
import org.apache.cassandra.service.accord.JournalKey;
|
import org.apache.cassandra.service.accord.JournalKey;
|
||||||
import org.apache.cassandra.service.accord.serializers.CommandSerializers;
|
import org.apache.cassandra.service.accord.serializers.CommandSerializers;
|
||||||
import org.apache.cassandra.service.accord.serializers.DepsSerializers;
|
import org.apache.cassandra.service.accord.serializers.DepsSerializers;
|
||||||
import org.apache.cassandra.service.accord.serializers.ResultSerializers;
|
|
||||||
import org.apache.cassandra.service.accord.serializers.Version;
|
import org.apache.cassandra.service.accord.serializers.Version;
|
||||||
import org.apache.cassandra.service.accord.serializers.WaitingOnSerializer;
|
import org.apache.cassandra.service.accord.serializers.WaitingOnSerializer;
|
||||||
|
import org.apache.cassandra.service.accord.txn.TxnDataResult;
|
||||||
|
|
||||||
import static accord.api.Journal.Load.ALL;
|
import static accord.api.Journal.Load.ALL;
|
||||||
import static accord.impl.CommandChange.Field.CLEANUP;
|
import static accord.impl.CommandChange.Field.CLEANUP;
|
||||||
|
|
@ -205,7 +205,7 @@ public class CommandChanges extends CommandChange.Builder implements Merger
|
||||||
break;
|
break;
|
||||||
case RESULT:
|
case RESULT:
|
||||||
Invariants.require(result != null, "%s", this);
|
Invariants.require(result != null, "%s", this);
|
||||||
ResultSerializers.result.serialize(result, out);
|
TxnDataResult.persistable.serialize(result, out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -309,7 +309,7 @@ public class CommandChanges extends CommandChange.Builder implements Merger
|
||||||
cleanup = newCleanup;
|
cleanup = newCleanup;
|
||||||
break;
|
break;
|
||||||
case RESULT:
|
case RESULT:
|
||||||
result = ResultSerializers.result.deserialize(in);
|
result = TxnDataResult.persistable.deserialize(in);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -355,8 +355,7 @@ public class CommandChanges extends CommandChange.Builder implements Merger
|
||||||
CommandSerializers.writes.skip(in, userVersion);
|
CommandSerializers.writes.skip(in, userVersion);
|
||||||
break;
|
break;
|
||||||
case RESULT:
|
case RESULT:
|
||||||
// TODO (expected): skip
|
TxnDataResult.persistable.skip(in);
|
||||||
ResultSerializers.result.skip(in);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue