Merge branch 'cassandra-3.0' into trunk
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/6237022e Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/6237022e Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/6237022e Branch: refs/heads/trunk Commit: 6237022e0234a71f5ca3d01aaefcecfd28bcdf71 Parents: bf25e66 c6ed2e0 Author: Robert Stupp <[email protected]> Authored: Thu Feb 25 07:49:39 2016 -0800 Committer: Robert Stupp <[email protected]> Committed: Thu Feb 25 07:49:39 2016 -0800 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../org/apache/cassandra/cql3/CQL3Type.java | 238 ++++++++----------- .../org/apache/cassandra/cql3/Constants.java | 9 +- .../cassandra/cql3/functions/CastFcts.java | 4 +- .../statements/CreateAggregateStatement.java | 21 ++ .../apache/cassandra/schema/SchemaKeyspace.java | 2 +- .../serializers/AbstractTextSerializer.java | 30 +-- .../cassandra/serializers/BytesSerializer.java | 14 +- .../serializers/TimestampSerializer.java | 9 +- .../cassandra/serializers/TypeSerializer.java | 9 +- .../cassandra/cql3/CQL3TypeLiteralTest.java | 88 +++---- .../validation/operations/AggregationTest.java | 72 ++++++ 12 files changed, 251 insertions(+), 246 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/6237022e/CHANGES.txt ---------------------------------------------------------------------- diff --cc CHANGES.txt index bc21818,bdcf328..fbf9085 --- a/CHANGES.txt +++ b/CHANGES.txt @@@ -1,34 -1,5 +1,35 @@@ -3.0.4 +3.4 + * Allow custom tracing implementations (CASSANDRA-10392) + * Extract LoaderOptions to be able to be used from outside (CASSANDRA-10637) + * fix OnDiskIndexTest to properly treat empty ranges (CASSANDRA-11205) + * fix TrackerTest to handle new notifications (CASSANDRA-11178) + * add SASI validation for partitioner and complex columns (CASSANDRA-11169) + * Add caching of encrypted credentials in PasswordAuthenticator (CASSANDRA-7715) + * fix SASI memtable switching on flush (CASSANDRA-11159) + * Remove duplicate offline compaction tracking (CASSANDRA-11148) + * fix EQ semantics of analyzed SASI indexes (CASSANDRA-11130) + * Support long name output for nodetool commands (CASSANDRA-7950) + * Encrypted hints (CASSANDRA-11040) + * SASI index options validation (CASSANDRA-11136) + * Optimize disk seek using min/max column name meta data when the LIMIT clause is used + (CASSANDRA-8180) + * Add LIKE support to CQL3 (CASSANDRA-11067) + * Generic Java UDF types (CASSANDRA-10819) + * cqlsh: Include sub-second precision in timestamps by default (CASSANDRA-10428) + * Set javac encoding to utf-8 (CASSANDRA-11077) + * Integrate SASI index into Cassandra (CASSANDRA-10661) + * Add --skip-flush option to nodetool snapshot + * Skip values for non-queried columns (CASSANDRA-10657) + * Add support for secondary indexes on static columns (CASSANDRA-8103) + * CommitLogUpgradeTestMaker creates broken commit logs (CASSANDRA-11051) + * Add metric for number of dropped mutations (CASSANDRA-10866) + * Simplify row cache invalidation code (CASSANDRA-10396) + * Support user-defined compaction through nodetool (CASSANDRA-10660) + * Stripe view locks by key and table ID to reduce contention (CASSANDRA-10981) + * Add nodetool gettimeout and settimeout commands (CASSANDRA-10953) + * Add 3.0 metadata to sstablemetadata output (CASSANDRA-10838) +Merged from 3.0: + * Failed aggregate creation breaks server permanently (CASSANDRA-11064) * Add sstabledump tool (CASSANDRA-7464) * Introduce backpressure for hints (CASSANDRA-10972) * Fix ClusteringPrefix not being able to read tombstone range boundaries (CASSANDRA-11158) http://git-wip-us.apache.org/repos/asf/cassandra/blob/6237022e/src/java/org/apache/cassandra/cql3/CQL3Type.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/6237022e/src/java/org/apache/cassandra/cql3/functions/CastFcts.java ---------------------------------------------------------------------- diff --cc src/java/org/apache/cassandra/cql3/functions/CastFcts.java index 8669225,0000000..b5d3698 mode 100644,000000..100644 --- a/src/java/org/apache/cassandra/cql3/functions/CastFcts.java +++ b/src/java/org/apache/cassandra/cql3/functions/CastFcts.java @@@ -1,344 -1,0 +1,342 @@@ +/* + * 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.functions; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.cassandra.cql3.CQL3Type; +import org.apache.cassandra.db.marshal.AbstractType; +import org.apache.cassandra.db.marshal.AsciiType; +import org.apache.cassandra.db.marshal.BooleanType; +import org.apache.cassandra.db.marshal.ByteType; +import org.apache.cassandra.db.marshal.CounterColumnType; +import org.apache.cassandra.db.marshal.DecimalType; +import org.apache.cassandra.db.marshal.DoubleType; +import org.apache.cassandra.db.marshal.FloatType; +import org.apache.cassandra.db.marshal.InetAddressType; +import org.apache.cassandra.db.marshal.Int32Type; +import org.apache.cassandra.db.marshal.IntegerType; +import org.apache.cassandra.db.marshal.LongType; +import org.apache.cassandra.db.marshal.ShortType; +import org.apache.cassandra.db.marshal.SimpleDateType; +import org.apache.cassandra.db.marshal.TimeType; +import org.apache.cassandra.db.marshal.TimeUUIDType; +import org.apache.cassandra.db.marshal.TimestampType; +import org.apache.cassandra.db.marshal.UTF8Type; +import org.apache.cassandra.db.marshal.UUIDType; +import org.apache.commons.lang3.text.WordUtils; + +/** + * Casting functions + * + */ +public final class CastFcts +{ + private static final String FUNCTION_NAME_PREFIX = "castAs"; + + public static Collection<Function> all() + { + List<Function> functions = new ArrayList<>(); + + @SuppressWarnings("unchecked") + final AbstractType<? extends Number>[] numericTypes = new AbstractType[] {ByteType.instance, + ShortType.instance, + Int32Type.instance, + LongType.instance, + FloatType.instance, + DoubleType.instance, + DecimalType.instance, + CounterColumnType.instance, + IntegerType.instance}; + + for (AbstractType<? extends Number> inputType : numericTypes) + { + addFunctionIfNeeded(functions, inputType, ByteType.instance, Number::byteValue); + addFunctionIfNeeded(functions, inputType, ShortType.instance, Number::shortValue); + addFunctionIfNeeded(functions, inputType, Int32Type.instance, Number::intValue); + addFunctionIfNeeded(functions, inputType, LongType.instance, Number::longValue); + addFunctionIfNeeded(functions, inputType, FloatType.instance, Number::floatValue); + addFunctionIfNeeded(functions, inputType, DoubleType.instance, Number::doubleValue); + addFunctionIfNeeded(functions, inputType, DecimalType.instance, p -> BigDecimal.valueOf(p.doubleValue())); + addFunctionIfNeeded(functions, inputType, IntegerType.instance, p -> BigInteger.valueOf(p.longValue())); + functions.add(CastAsTextFunction.create(inputType, AsciiType.instance)); + functions.add(CastAsTextFunction.create(inputType, UTF8Type.instance)); + } + + functions.add(JavaFunctionWrapper.create(AsciiType.instance, UTF8Type.instance, p -> p)); + + functions.add(CastAsTextFunction.create(InetAddressType.instance, AsciiType.instance)); + functions.add(CastAsTextFunction.create(InetAddressType.instance, UTF8Type.instance)); + + functions.add(CastAsTextFunction.create(BooleanType.instance, AsciiType.instance)); + functions.add(CastAsTextFunction.create(BooleanType.instance, UTF8Type.instance)); + + functions.add(CassandraFunctionWrapper.create(TimeUUIDType.instance, SimpleDateType.instance, TimeFcts.timeUuidtoDate)); + functions.add(CassandraFunctionWrapper.create(TimeUUIDType.instance, TimestampType.instance, TimeFcts.timeUuidToTimestamp)); + functions.add(CastAsTextFunction.create(TimeUUIDType.instance, AsciiType.instance)); + functions.add(CastAsTextFunction.create(TimeUUIDType.instance, UTF8Type.instance)); + functions.add(CassandraFunctionWrapper.create(TimestampType.instance, SimpleDateType.instance, TimeFcts.timestampToDate)); + functions.add(CastAsTextFunction.create(TimestampType.instance, AsciiType.instance)); + functions.add(CastAsTextFunction.create(TimestampType.instance, UTF8Type.instance)); + functions.add(CassandraFunctionWrapper.create(SimpleDateType.instance, TimestampType.instance, TimeFcts.dateToTimestamp)); + functions.add(CastAsTextFunction.create(SimpleDateType.instance, AsciiType.instance)); + functions.add(CastAsTextFunction.create(SimpleDateType.instance, UTF8Type.instance)); + functions.add(CastAsTextFunction.create(TimeType.instance, AsciiType.instance)); + functions.add(CastAsTextFunction.create(TimeType.instance, UTF8Type.instance)); + + functions.add(CastAsTextFunction.create(UUIDType.instance, AsciiType.instance)); + functions.add(CastAsTextFunction.create(UUIDType.instance, UTF8Type.instance)); + + return functions; + } + + /** + * Creates the name of the cast function use to cast to the specified type. + * + * @param outputType the output type + * @return the name of the cast function use to cast to the specified type + */ + public static String getFunctionName(AbstractType<?> outputType) + { + return getFunctionName(outputType.asCQL3Type()); + } + + /** + * Creates the name of the cast function use to cast to the specified type. + * + * @param outputType the output type + * @return the name of the cast function use to cast to the specified type + */ + public static String getFunctionName(CQL3Type outputType) + { + return FUNCTION_NAME_PREFIX + WordUtils.capitalize(toLowerCaseString(outputType)); + } + + /** + * Adds to the list a function converting the input type in to the output type if they are not the same. + * + * @param functions the list to add to + * @param inputType the input type + * @param outputType the output type + * @param converter the function use to convert the input type into the output type + */ + private static <I, O> void addFunctionIfNeeded(List<Function> functions, + AbstractType<I> inputType, + AbstractType<O> outputType, + java.util.function.Function<I, O> converter) + { + if (!inputType.equals(outputType)) + functions.add(wrapJavaFunction(inputType, outputType, converter)); + } + + @SuppressWarnings("unchecked") + private static <O, I> Function wrapJavaFunction(AbstractType<I> inputType, + AbstractType<O> outputType, + java.util.function.Function<I, O> converter) + { + return inputType.equals(CounterColumnType.instance) + ? JavaCounterFunctionWrapper.create(outputType, (java.util.function.Function<Long, O>) converter) + : JavaFunctionWrapper.create(inputType, outputType, converter); + } + + private static String toLowerCaseString(CQL3Type type) + { + return type.toString().toLowerCase(); + } + + /** + * Base class for the CAST functions. + * + * @param <I> the input type + * @param <O> the output type + */ + private static abstract class CastFunction<I, O> extends NativeScalarFunction + { + public CastFunction(AbstractType<I> inputType, AbstractType<O> outputType) + { + super(getFunctionName(outputType), outputType, inputType); + } + + @Override + public String columnName(List<String> columnNames) + { + return String.format("cast(%s as %s)", columnNames.get(0), toLowerCaseString(outputType().asCQL3Type())); + } + + @SuppressWarnings("unchecked") + protected AbstractType<O> outputType() + { + return (AbstractType<O>) returnType; + } + + @SuppressWarnings("unchecked") + protected AbstractType<I> inputType() + { + return (AbstractType<I>) argTypes.get(0); + } + } + + /** + * <code>CastFunction</code> that implements casting by wrapping a java <code>Function</code>. + * + * @param <I> the input parameter + * @param <O> the output parameter + */ + private static class JavaFunctionWrapper<I, O> extends CastFunction<I, O> + { + /** + * The java function used to convert the input type into the output one. + */ + private final java.util.function.Function<I, O> converter; + + public static <I, O> JavaFunctionWrapper<I, O> create(AbstractType<I> inputType, + AbstractType<O> outputType, + java.util.function.Function<I, O> converter) + { + return new JavaFunctionWrapper<I, O>(inputType, outputType, converter); + } + + protected JavaFunctionWrapper(AbstractType<I> inputType, + AbstractType<O> outputType, + java.util.function.Function<I, O> converter) + { + super(inputType, outputType); + this.converter = converter; + } + + public final ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters) + { + ByteBuffer bb = parameters.get(0); + if (bb == null) + return null; + + return outputType().decompose(converter.apply(compose(bb))); + } + + protected I compose(ByteBuffer bb) + { + return inputType().compose(bb); + } + } + + /** + * <code>JavaFunctionWrapper</code> for counter columns. + * + * <p>Counter columns need to be handled in a special way because their binary representation is converted into + * the one of a BIGINT before functions are applied.</p> + * + * @param <O> the output parameter + */ + private static class JavaCounterFunctionWrapper<O> extends JavaFunctionWrapper<Long, O> + { + public static <O> JavaFunctionWrapper<Long, O> create(AbstractType<O> outputType, + java.util.function.Function<Long, O> converter) + { + return new JavaCounterFunctionWrapper<O>(outputType, converter); + } + + protected JavaCounterFunctionWrapper(AbstractType<O> outputType, + java.util.function.Function<Long, O> converter) + { + super(CounterColumnType.instance, outputType, converter); + } + + protected Long compose(ByteBuffer bb) + { + return LongType.instance.compose(bb); + } + } + + /** + * <code>CastFunction</code> that implements casting by wrapping an existing <code>NativeScalarFunction</code>. + * + * @param <I> the input parameter + * @param <O> the output parameter + */ + private static final class CassandraFunctionWrapper<I, O> extends CastFunction<I, O> + { + /** + * The native scalar function used to perform the conversion. + */ + private final NativeScalarFunction delegate; + + public static <I, O> CassandraFunctionWrapper<I, O> create(AbstractType<I> inputType, + AbstractType<O> outputType, + NativeScalarFunction delegate) + { + return new CassandraFunctionWrapper<I, O>(inputType, outputType, delegate); + } + + private CassandraFunctionWrapper(AbstractType<I> inputType, + AbstractType<O> outputType, + NativeScalarFunction delegate) + { + super(inputType, outputType); + assert delegate.argTypes().size() == 1 && inputType.equals(delegate.argTypes().get(0)); + assert outputType.equals(delegate.returnType()); + this.delegate = delegate; + } + + public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters) + { + return delegate.execute(protocolVersion, parameters); + } + } + + /** + * <code>CastFunction</code> that can be used to cast a type into ascii or text types. + * + * @param <I> the input parameter + */ + private static final class CastAsTextFunction<I> extends CastFunction<I, String> + { + + public static <I> CastAsTextFunction<I> create(AbstractType<I> inputType, + AbstractType<String> outputType) + { + return new CastAsTextFunction<I>(inputType, outputType); + } + + private CastAsTextFunction(AbstractType<I> inputType, + AbstractType<String> outputType) + { + super(inputType, outputType); + } + + public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters) + { + ByteBuffer bb = parameters.get(0); + if (bb == null) + return null; + - StringBuilder builder = new StringBuilder(); - inputType().getSerializer().toCQLLiteral(bb, builder); - return outputType().decompose(builder.toString()); ++ return outputType().decompose(inputType().getSerializer().toCQLLiteral(bb)); + } + } + + /** + * The class must not be instantiated as it contains only static variables. + */ + private CastFcts() + { + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/6237022e/src/java/org/apache/cassandra/schema/SchemaKeyspace.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/6237022e/src/java/org/apache/cassandra/serializers/TypeSerializer.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/6237022e/test/unit/org/apache/cassandra/cql3/validation/operations/AggregationTest.java ----------------------------------------------------------------------
