mirror of https://github.com/apache/cassandra
Add functions to convert timeuuid to date or time, deprecate dateOf and unixTimestampOf
patch by Benjamin Lerer; reviewed by Robert Stupp for CASSANDRA-9229
This commit is contained in:
parent
6dfde0e32e
commit
c08aaabd95
|
|
@ -24,6 +24,7 @@
|
|||
* Revert CASSANDRA-7807 (tracing completion client notifications) (CASSANDRA-9429)
|
||||
* Add ability to stop compaction by ID (CASSANDRA-7207)
|
||||
* Let CassandraVersion handle SNAPSHOT version (CASSANDRA-9438)
|
||||
* Add functions to convert timeuuid to date or time, deprecate dateOf and unixTimestampOf (CASSANDRA-9229)
|
||||
Merged from 2.1:
|
||||
* Make nodetool exit with non-0 status on failure (CASSANDRA-9569)
|
||||
* (cqlsh) Fix using COPY through SOURCE or -f (CASSANDRA-9083)
|
||||
|
|
|
|||
7
NEWS.txt
7
NEWS.txt
|
|
@ -88,6 +88,13 @@ New features
|
|||
- New `ShortType` (cql smallint). 2-byte signed integer
|
||||
- New `SimpleDateType` (cql date). 4-byte unsigned integer
|
||||
- New `TimeType` (cql time). 8-byte long
|
||||
- The toDate(timeuuid), toTimestamp(timeuuid) and toUnixTimestamp(timeuuid) functions have been added to allow
|
||||
to convert from timeuuid into date type, timestamp type and bigint raw value.
|
||||
The functions unixTimestampOf(timeuuid) and dateOf(timeuuid) have been deprecated.
|
||||
- The toDate(timestamp) and toUnixTimestamp(timestamp) functions have been added to allow
|
||||
to convert from timestamp into date type and bigint raw value.
|
||||
- The toTimestamp(date) and toUnixTimestamp(date) functions have been added to allow
|
||||
to convert from date into timestamp type and bigint raw value.
|
||||
|
||||
|
||||
Upgrading
|
||||
|
|
|
|||
|
|
@ -1819,9 +1819,20 @@ will select all rows where the @timeuuid@ column @t@ is strictly older than '201
|
|||
|
||||
_Warning_: We called the values generated by @minTimeuuid@ and @maxTimeuuid@ _fake_ UUID because they do no respect the Time-Based UUID generation process specified by the "RFC 4122":http://www.ietf.org/rfc/rfc4122.txt. In particular, the value returned by these 2 methods will not be unique. This means you should only use those methods for querying (as in the example above). Inserting the result of those methods is almost certainly _a bad idea_.
|
||||
|
||||
h4. @dateOf@ and @unixTimestampOf@
|
||||
h3(#timeFun). Time conversion functions
|
||||
|
||||
The @dateOf@ and @unixTimestampOf@ functions take a @timeuuid@ argument and extract the embedded timestamp. However, while the @dateof@ function return it with the @timestamp@ type (that most client, including cqlsh, interpret as a date), the @unixTimestampOf@ function returns it as a @bigint@ raw value.
|
||||
A number of functions are provided to "convert" a @timeuuid@, a @timestamp@ or a @date@ into another @native@ type.
|
||||
|
||||
|_. function name |_. input type |_. description|
|
||||
|@toDate@ |@timeuuid@ |Converts the @timeuuid@ argument into a @date@ type|
|
||||
|@toDate@ |@timestamp@ |Converts the @timestamp@ argument into a @date@ type|
|
||||
|@toTimestamp@ |@timeuuid@ |Converts the @timeuuid@ argument into a @timestamp@ type|
|
||||
|@toTimestamp@ |@date@ |Converts the @date@ argument into a @timestamp@ type|
|
||||
|@toUnixTimestamp@ |@timeuuid@ |Converts the @timeuuid@ argument into a @bigInt@ raw value|
|
||||
|@toUnixTimestamp@ |@timestamp@ |Converts the @timestamp@ argument into a @bigInt@ raw value|
|
||||
|@toUnixTimestamp@ |@date@ |Converts the @date@ argument into a @bigInt@ raw value|
|
||||
|@dateOf@ |@timeuuid@ |Similar to @toTimestamp(timeuuid)@ (DEPRECATED)|
|
||||
|@unixTimestampOf@ |@timeuuid@ |Similar to @toUnixTimestamp(timeuuid)@ (DEPRECATED)|
|
||||
|
||||
h3(#blobFun). Blob conversion functions
|
||||
|
||||
|
|
|
|||
|
|
@ -46,11 +46,18 @@ public abstract class Functions
|
|||
static
|
||||
{
|
||||
declare(AggregateFcts.countRowsFunction);
|
||||
declare(TimeuuidFcts.nowFct);
|
||||
declare(TimeuuidFcts.minTimeuuidFct);
|
||||
declare(TimeuuidFcts.maxTimeuuidFct);
|
||||
declare(TimeuuidFcts.dateOfFct);
|
||||
declare(TimeuuidFcts.unixTimestampOfFct);
|
||||
declare(TimeFcts.nowFct);
|
||||
declare(TimeFcts.minTimeuuidFct);
|
||||
declare(TimeFcts.maxTimeuuidFct);
|
||||
declare(TimeFcts.dateOfFct);
|
||||
declare(TimeFcts.unixTimestampOfFct);
|
||||
declare(TimeFcts.timeUuidtoDate);
|
||||
declare(TimeFcts.timeUuidToTimestamp);
|
||||
declare(TimeFcts.timeUuidToUnixTimestamp);
|
||||
declare(TimeFcts.timestampToDate);
|
||||
declare(TimeFcts.timestampToUnixTimestamp);
|
||||
declare(TimeFcts.dateToTimestamp);
|
||||
declare(TimeFcts.dateToUnixTimestamp);
|
||||
declare(UuidFcts.uuidFct);
|
||||
|
||||
for (CQL3Type type : CQL3Type.Native.values())
|
||||
|
|
|
|||
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* 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.nio.ByteBuffer;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.apache.cassandra.db.marshal.*;
|
||||
import org.apache.cassandra.serializers.TimestampSerializer;
|
||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||
import org.apache.cassandra.utils.UUIDGen;
|
||||
|
||||
public abstract class TimeFcts
|
||||
{
|
||||
public static Logger logger = LoggerFactory.getLogger(TimeFcts.class);
|
||||
|
||||
public static final Function nowFct = new NativeScalarFunction("now", TimeUUIDType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
return ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
|
||||
}
|
||||
};
|
||||
|
||||
public static final Function minTimeuuidFct = new NativeScalarFunction("mintimeuuid", TimeUUIDType.instance, TimestampType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
return ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.minTimeUUID(TimestampType.instance.compose(bb).getTime())));
|
||||
}
|
||||
};
|
||||
|
||||
public static final Function maxTimeuuidFct = new NativeScalarFunction("maxtimeuuid", TimeUUIDType.instance, TimestampType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
return ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.maxTimeUUID(TimestampType.instance.compose(bb).getTime())));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that convert a value of <code>TIMEUUID</code> into a value of type <code>TIMESTAMP</code>.
|
||||
* @deprecated Replaced by the {@link #timeUuidToTimestamp} function
|
||||
*/
|
||||
public static final Function dateOfFct = new NativeScalarFunction("dateof", TimestampType.instance, TimeUUIDType.instance)
|
||||
{
|
||||
private volatile boolean hasLoggedDeprecationWarning;
|
||||
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
if (!hasLoggedDeprecationWarning)
|
||||
{
|
||||
hasLoggedDeprecationWarning = true;
|
||||
logger.warn("The function 'dateof' is deprecated." +
|
||||
" Use the function 'toTimestamp' instead.");
|
||||
}
|
||||
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
long timeInMillis = UUIDGen.unixTimestamp(UUIDGen.getUUID(bb));
|
||||
return ByteBufferUtil.bytes(timeInMillis);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that convert a value of type <code>TIMEUUID</code> into an UNIX timestamp.
|
||||
* @deprecated Replaced by the {@link #timeUuidToUnixTimestamp} function
|
||||
*/
|
||||
public static final Function unixTimestampOfFct = new NativeScalarFunction("unixtimestampof", LongType.instance, TimeUUIDType.instance)
|
||||
{
|
||||
private volatile boolean hasLoggedDeprecationWarning;
|
||||
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
if (!hasLoggedDeprecationWarning)
|
||||
{
|
||||
hasLoggedDeprecationWarning = true;
|
||||
logger.warn("The function 'unixtimestampof' is deprecated." +
|
||||
" Use the function 'toUnixTimestamp' instead.");
|
||||
}
|
||||
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
return ByteBufferUtil.bytes(UUIDGen.unixTimestamp(UUIDGen.getUUID(bb)));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that convert a value of <code>TIMEUUID</code> into a value of type <code>DATE</code>.
|
||||
*/
|
||||
public static final Function timeUuidtoDate = new NativeScalarFunction("todate", SimpleDateType.instance, TimeUUIDType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
long timeInMillis = UUIDGen.unixTimestamp(UUIDGen.getUUID(bb));
|
||||
return SimpleDateType.instance.fromTimeInMillis(timeInMillis);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that convert a value of type <code>TIMEUUID</code> into a value of type <code>TIMESTAMP</code>.
|
||||
*/
|
||||
public static final Function timeUuidToTimestamp = new NativeScalarFunction("totimestamp", TimestampType.instance, TimeUUIDType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
long timeInMillis = UUIDGen.unixTimestamp(UUIDGen.getUUID(bb));
|
||||
return TimestampType.instance.fromTimeInMillis(timeInMillis);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that convert a value of type <code>TIMEUUID</code> into an UNIX timestamp.
|
||||
*/
|
||||
public static final Function timeUuidToUnixTimestamp = new NativeScalarFunction("tounixtimestamp", LongType.instance, TimeUUIDType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
return ByteBufferUtil.bytes(UUIDGen.unixTimestamp(UUIDGen.getUUID(bb)));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that convert a value of type <code>TIMESTAMP</code> into an UNIX timestamp.
|
||||
*/
|
||||
public static final Function timestampToUnixTimestamp = new NativeScalarFunction("tounixtimestamp", LongType.instance, TimestampType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
Date date = TimestampType.instance.compose(bb);
|
||||
return date == null ? null : ByteBufferUtil.bytes(date.getTime());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that convert a value of type <code>TIMESTAMP</code> into a <code>DATE</code>.
|
||||
*/
|
||||
public static final Function timestampToDate = new NativeScalarFunction("todate", SimpleDateType.instance, TimestampType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
Date date = TimestampType.instance.compose(bb);
|
||||
return date == null ? null : SimpleDateType.instance.fromTimeInMillis(date.getTime());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that convert a value of type <code>TIMESTAMP</code> into a <code>DATE</code>.
|
||||
*/
|
||||
public static final Function dateToTimestamp = new NativeScalarFunction("totimestamp", TimestampType.instance, SimpleDateType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
long millis = SimpleDateType.instance.toTimeInMillis(bb);
|
||||
return TimestampType.instance.fromTimeInMillis(millis);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that convert a value of type <code>DATE</code> into an UNIX timestamp.
|
||||
*/
|
||||
public static final Function dateToUnixTimestamp = new NativeScalarFunction("tounixtimestamp", LongType.instance, SimpleDateType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
return ByteBufferUtil.bytes(SimpleDateType.instance.toTimeInMillis(bb));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* 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.nio.ByteBuffer;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cassandra.db.marshal.TimestampType;
|
||||
import org.apache.cassandra.db.marshal.TimeUUIDType;
|
||||
import org.apache.cassandra.db.marshal.LongType;
|
||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||
import org.apache.cassandra.utils.UUIDGen;
|
||||
|
||||
public abstract class TimeuuidFcts
|
||||
{
|
||||
public static final Function nowFct = new NativeScalarFunction("now", TimeUUIDType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
return ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
|
||||
}
|
||||
};
|
||||
|
||||
public static final Function minTimeuuidFct = new NativeScalarFunction("mintimeuuid", TimeUUIDType.instance, TimestampType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
return ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.minTimeUUID(TimestampType.instance.compose(bb).getTime())));
|
||||
}
|
||||
};
|
||||
|
||||
public static final Function maxTimeuuidFct = new NativeScalarFunction("maxtimeuuid", TimeUUIDType.instance, TimestampType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
return ByteBuffer.wrap(UUIDGen.decompose(UUIDGen.maxTimeUUID(TimestampType.instance.compose(bb).getTime())));
|
||||
}
|
||||
};
|
||||
|
||||
public static final Function dateOfFct = new NativeScalarFunction("dateof", TimestampType.instance, TimeUUIDType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
return TimestampType.instance.decompose(new Date(UUIDGen.unixTimestamp(UUIDGen.getUUID(bb))));
|
||||
}
|
||||
};
|
||||
|
||||
public static final Function unixTimestampOfFct = new NativeScalarFunction("unixtimestampof", LongType.instance, TimeUUIDType.instance)
|
||||
{
|
||||
public ByteBuffer execute(int protocolVersion, List<ByteBuffer> parameters)
|
||||
{
|
||||
ByteBuffer bb = parameters.get(0);
|
||||
if (bb == null)
|
||||
return null;
|
||||
|
||||
return ByteBufferUtil.bytes(UUIDGen.unixTimestamp(UUIDGen.getUUID(bb)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -50,6 +50,16 @@ public class SimpleDateType extends AbstractType<Integer>
|
|||
return ByteBufferUtil.bytes(SimpleDateSerializer.dateStringToDays(source));
|
||||
}
|
||||
|
||||
public ByteBuffer fromTimeInMillis(long millis) throws MarshalException
|
||||
{
|
||||
return ByteBufferUtil.bytes(SimpleDateSerializer.timeInMillisToDay(millis));
|
||||
}
|
||||
|
||||
public long toTimeInMillis(ByteBuffer buffer) throws MarshalException
|
||||
{
|
||||
return SimpleDateSerializer.dayToTimeInMillis(ByteBufferUtil.toInt(buffer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompatibleWith(AbstractType<?> previous)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -64,6 +64,11 @@ public class TimestampType extends AbstractType<Date>
|
|||
return ByteBufferUtil.bytes(TimestampSerializer.dateStringToTimestamp(source));
|
||||
}
|
||||
|
||||
public ByteBuffer fromTimeInMillis(long millis) throws MarshalException
|
||||
{
|
||||
return ByteBufferUtil.bytes(millis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Term fromJSONObject(Object parsed) throws MarshalException
|
||||
{
|
||||
|
|
|
|||
|
|
@ -105,14 +105,14 @@ public final class SystemDistributedKeyspace
|
|||
{
|
||||
|
||||
String query = "INSERT INTO %s.%s (parent_id, keyspace_name, columnfamily_names, requested_ranges, started_at)"+
|
||||
" VALUES (%s, '%s', { '%s' }, { '%s' }, dateOf(now()))";
|
||||
" VALUES (%s, '%s', { '%s' }, { '%s' }, toTimestamp(now()))";
|
||||
String fmtQry = String.format(query, NAME, PARENT_REPAIR_HISTORY, parent_id.toString(), keyspaceName, Joiner.on("','").join(cfnames), Joiner.on("','").join(ranges));
|
||||
processSilent(fmtQry);
|
||||
}
|
||||
|
||||
public static void failParentRepair(UUID parent_id, Throwable t)
|
||||
{
|
||||
String query = "UPDATE %s.%s SET finished_at = dateOf(now()), exception_message=?, exception_stacktrace=? WHERE parent_id=%s";
|
||||
String query = "UPDATE %s.%s SET finished_at = toTimestamp(now()), exception_message=?, exception_stacktrace=? WHERE parent_id=%s";
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
|
|
@ -123,7 +123,7 @@ public final class SystemDistributedKeyspace
|
|||
|
||||
public static void successfulParentRepair(UUID parent_id, Collection<Range<Token>> successfulRanges)
|
||||
{
|
||||
String query = "UPDATE %s.%s SET finished_at = dateOf(now()), successful_ranges = {'%s'} WHERE parent_id=%s";
|
||||
String query = "UPDATE %s.%s SET finished_at = toTimestamp(now()), successful_ranges = {'%s'} WHERE parent_id=%s";
|
||||
String fmtQuery = String.format(query, NAME, PARENT_REPAIR_HISTORY, Joiner.on("','").join(successfulRanges), parent_id.toString());
|
||||
processSilent(fmtQuery);
|
||||
}
|
||||
|
|
@ -138,7 +138,7 @@ public final class SystemDistributedKeyspace
|
|||
|
||||
String query =
|
||||
"INSERT INTO %s.%s (keyspace_name, columnfamily_name, id, parent_id, range_begin, range_end, coordinator, participants, status, started_at) " +
|
||||
"VALUES ( '%s', '%s', %s, %s, '%s', '%s', '%s', { '%s' }, '%s', dateOf(now()))";
|
||||
"VALUES ( '%s', '%s', %s, %s, '%s', '%s', '%s', { '%s' }, '%s', toTimestamp(now()))";
|
||||
|
||||
for (String cfname : cfnames)
|
||||
{
|
||||
|
|
@ -164,7 +164,7 @@ public final class SystemDistributedKeyspace
|
|||
|
||||
public static void successfulRepairJob(UUID id, String keyspaceName, String cfname)
|
||||
{
|
||||
String query = "UPDATE %s.%s SET status = '%s', finished_at = dateOf(now()) WHERE keyspace_name = '%s' AND columnfamily_name = '%s' AND id = %s";
|
||||
String query = "UPDATE %s.%s SET status = '%s', finished_at = toTimestamp(now()) WHERE keyspace_name = '%s' AND columnfamily_name = '%s' AND id = %s";
|
||||
String fmtQuery = String.format(query, NAME, REPAIR_HISTORY,
|
||||
RepairState.SUCCESS.toString(),
|
||||
keyspaceName,
|
||||
|
|
@ -175,7 +175,7 @@ public final class SystemDistributedKeyspace
|
|||
|
||||
public static void failedRepairJob(UUID id, String keyspaceName, String cfname, Throwable t)
|
||||
{
|
||||
String query = "UPDATE %s.%s SET status = '%s', finished_at = dateOf(now()), exception_message=?, exception_stacktrace=? WHERE keyspace_name = '%s' AND columnfamily_name = '%s' AND id = %s";
|
||||
String query = "UPDATE %s.%s SET status = '%s', finished_at = toTimestamp(now()), exception_message=?, exception_stacktrace=? WHERE keyspace_name = '%s' AND columnfamily_name = '%s' AND id = %s";
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
t.printStackTrace(pw);
|
||||
|
|
|
|||
|
|
@ -86,9 +86,7 @@ public class SimpleDateSerializer implements TypeSerializer<Integer>
|
|||
if (millis > maxSupportedDateMillis)
|
||||
throw new MarshalException(String.format("Input date %s is greater than max supported date %s", source, new LocalDate(maxSupportedDateMillis).toString()));
|
||||
|
||||
Integer result = (int)TimeUnit.MILLISECONDS.toDays(millis);
|
||||
result -= Integer.MIN_VALUE;
|
||||
return result;
|
||||
return timeInMillisToDay(millis);
|
||||
}
|
||||
catch (IllegalArgumentException e1)
|
||||
{
|
||||
|
|
@ -96,6 +94,18 @@ public class SimpleDateSerializer implements TypeSerializer<Integer>
|
|||
}
|
||||
}
|
||||
|
||||
public static int timeInMillisToDay(long millis)
|
||||
{
|
||||
Integer result = (int) TimeUnit.MILLISECONDS.toDays(millis);
|
||||
result -= Integer.MIN_VALUE;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static long dayToTimeInMillis(int days)
|
||||
{
|
||||
return TimeUnit.DAYS.toMillis(days - Integer.MIN_VALUE);
|
||||
}
|
||||
|
||||
public void validate(ByteBuffer bytes) throws MarshalException
|
||||
{
|
||||
if (bytes.remaining() != 4)
|
||||
|
|
@ -107,7 +117,7 @@ public class SimpleDateSerializer implements TypeSerializer<Integer>
|
|||
if (value == null)
|
||||
return "";
|
||||
|
||||
return formatter.print(new LocalDate(TimeUnit.DAYS.toMillis(value - Integer.MIN_VALUE), DateTimeZone.UTC));
|
||||
return formatter.print(new LocalDate(dayToTimeInMillis(value), DateTimeZone.UTC));
|
||||
}
|
||||
|
||||
public Class<Integer> getType()
|
||||
|
|
|
|||
|
|
@ -111,10 +111,10 @@ public class AggregationTest extends CQLTester
|
|||
"LANGUAGE JAVA " +
|
||||
"AS 'return Double.valueOf(Math.copySign(magnitude, sign));';");
|
||||
|
||||
assertColumnNames(execute("SELECT max(a), max(unixTimestampOf(b)) FROM %s"), "system.max(a)", "system.max(system.unixtimestampof(b))");
|
||||
assertRows(execute("SELECT max(a), max(unixTimestampOf(b)) FROM %s"), row(null, null));
|
||||
assertColumnNames(execute("SELECT max(a), unixTimestampOf(max(b)) FROM %s"), "system.max(a)", "system.unixtimestampof(system.max(b))");
|
||||
assertRows(execute("SELECT max(a), unixTimestampOf(max(b)) FROM %s"), row(null, null));
|
||||
assertColumnNames(execute("SELECT max(a), max(toUnixTimestamp(b)) FROM %s"), "system.max(a)", "system.max(system.tounixtimestamp(b))");
|
||||
assertRows(execute("SELECT max(a), max(toUnixTimestamp(b)) FROM %s"), row(null, null));
|
||||
assertColumnNames(execute("SELECT max(a), toUnixTimestamp(max(b)) FROM %s"), "system.max(a)", "system.tounixtimestamp(system.max(b))");
|
||||
assertRows(execute("SELECT max(a), toUnixTimestamp(max(b)) FROM %s"), row(null, null));
|
||||
|
||||
assertColumnNames(execute("SELECT max(" + copySign + "(c, d)) FROM %s"), "system.max(" + copySign + "(c, d))");
|
||||
assertRows(execute("SELECT max(" + copySign + "(c, d)) FROM %s"), row((Object) null));
|
||||
|
|
@ -128,8 +128,8 @@ public class AggregationTest extends CQLTester
|
|||
Date date = format.parse("2011-02-03 04:10:00");
|
||||
date = DateUtils.truncate(date, Calendar.MILLISECOND);
|
||||
|
||||
assertRows(execute("SELECT max(a), max(unixTimestampOf(b)) FROM %s"), row(3, date.getTime()));
|
||||
assertRows(execute("SELECT max(a), unixTimestampOf(max(b)) FROM %s"), row(3, date.getTime()));
|
||||
assertRows(execute("SELECT max(a), max(toUnixTimestamp(b)) FROM %s"), row(3, date.getTime()));
|
||||
assertRows(execute("SELECT max(a), toUnixTimestamp(max(b)) FROM %s"), row(3, date.getTime()));
|
||||
|
||||
assertRows(execute("SELECT " + copySign + "(max(c), min(c)) FROM %s"), row(-1.4));
|
||||
assertRows(execute("SELECT " + copySign + "(c, d) FROM %s"), row(1.2), row(-1.3), row(1.4));
|
||||
|
|
|
|||
|
|
@ -36,8 +36,13 @@ public class TypeTest extends CQLTester
|
|||
public void testDateCompatibility() throws Throwable
|
||||
{
|
||||
createTable("CREATE TABLE %s (a int, b timestamp, c bigint, d varint, PRIMARY KEY (a, b, c, d))");
|
||||
execute("INSERT INTO %s (a, b, c, d) VALUES (0, unixTimestampOf(now()), dateOf(now()), dateOf(now()))");
|
||||
UntypedResultSet results = execute("SELECT * FROM %s WHERE a=0 AND b < unixTimestampOf(now())");
|
||||
|
||||
execute("INSERT INTO %s (a, b, c, d) VALUES (0, toUnixTimestamp(now()), toTimestamp(now()), toTimestamp(now()))");
|
||||
UntypedResultSet results = execute("SELECT * FROM %s WHERE a=0 AND b < toUnixTimestamp(now())");
|
||||
assertEquals(1, results.size());
|
||||
|
||||
execute("INSERT INTO %s (a, b, c, d) VALUES (1, unixTimestampOf(now()), dateOf(now()), dateOf(now()))");
|
||||
results = execute("SELECT * FROM %s WHERE a=1 AND b < toUnixTimestamp(now())");
|
||||
assertEquals(1, results.size());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ public class UFTest extends CQLTester
|
|||
execute("DROP FUNCTION IF EXISTS " + fSin);
|
||||
|
||||
// can't drop native functions
|
||||
assertInvalidMessage("system keyspace is not user-modifiable", "DROP FUNCTION dateof");
|
||||
assertInvalidMessage("system keyspace is not user-modifiable", "DROP FUNCTION totimestamp");
|
||||
assertInvalidMessage("system keyspace is not user-modifiable", "DROP FUNCTION uuid");
|
||||
|
||||
// sin() no longer exists
|
||||
|
|
@ -732,10 +732,11 @@ public class UFTest extends CQLTester
|
|||
@Test
|
||||
public void testFunctionInSystemKS() throws Throwable
|
||||
{
|
||||
execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".dateof(val timeuuid) " +
|
||||
execute("CREATE OR REPLACE FUNCTION " + KEYSPACE + ".totimestamp(val timeuuid) " +
|
||||
"RETURNS NULL ON NULL INPUT " +
|
||||
"RETURNS timestamp " +
|
||||
"LANGUAGE JAVA\n" +
|
||||
|
||||
"AS 'return null;';");
|
||||
|
||||
assertInvalidMessage("system keyspace is not user-modifiable",
|
||||
|
|
@ -745,10 +746,11 @@ public class UFTest extends CQLTester
|
|||
"LANGUAGE JAVA\n" +
|
||||
"AS 'return null;';");
|
||||
assertInvalidMessage("system keyspace is not user-modifiable",
|
||||
"CREATE OR REPLACE FUNCTION system.dateof(val timeuuid) " +
|
||||
"CREATE OR REPLACE FUNCTION system.totimestamp(val timeuuid) " +
|
||||
"RETURNS NULL ON NULL INPUT " +
|
||||
"RETURNS timestamp " +
|
||||
"LANGUAGE JAVA\n" +
|
||||
|
||||
"AS 'return null;';");
|
||||
assertInvalidMessage("system keyspace is not user-modifiable",
|
||||
"DROP FUNCTION system.now");
|
||||
|
|
@ -761,7 +763,7 @@ public class UFTest extends CQLTester
|
|||
"LANGUAGE JAVA\n" +
|
||||
"AS 'return null;';");
|
||||
assertInvalidMessage("system keyspace is not user-modifiable",
|
||||
"CREATE OR REPLACE FUNCTION dateof(val timeuuid) " +
|
||||
"CREATE OR REPLACE FUNCTION totimestamp(val timeuuid) " +
|
||||
"RETURNS NULL ON NULL INPUT " +
|
||||
"RETURNS timestamp " +
|
||||
"LANGUAGE JAVA\n" +
|
||||
|
|
|
|||
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* 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.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.cassandra.db.marshal.LongType;
|
||||
import org.apache.cassandra.db.marshal.SimpleDateType;
|
||||
import org.apache.cassandra.db.marshal.TimeUUIDType;
|
||||
import org.apache.cassandra.db.marshal.TimestampType;
|
||||
import org.apache.cassandra.transport.Server;
|
||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||
import org.apache.cassandra.utils.UUIDGen;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class TimeFctsTest
|
||||
{
|
||||
@Test
|
||||
public void testMinTimeUuid()
|
||||
{
|
||||
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21 11:03:02");
|
||||
|
||||
long timeInMillis = dateTime.getMillis();
|
||||
ByteBuffer input = TimestampType.instance.fromString("2015-05-21 11:03:02+00");
|
||||
ByteBuffer output = executeFunction(TimeFcts.minTimeuuidFct, input);
|
||||
assertEquals(UUIDGen.minTimeUUID(timeInMillis), TimeUUIDType.instance.compose(output));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxTimeUuid()
|
||||
{
|
||||
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21 11:03:02");
|
||||
|
||||
long timeInMillis = dateTime.getMillis();
|
||||
ByteBuffer input = TimestampType.instance.fromString("2015-05-21 11:03:02+00");
|
||||
ByteBuffer output = executeFunction(TimeFcts.maxTimeuuidFct, input);
|
||||
assertEquals(UUIDGen.maxTimeUUID(timeInMillis), TimeUUIDType.instance.compose(output));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDateOf()
|
||||
{
|
||||
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21 11:03:02");
|
||||
|
||||
long timeInMillis = dateTime.getMillis();
|
||||
ByteBuffer input = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timeInMillis, 0));
|
||||
ByteBuffer output = executeFunction(TimeFcts.dateOfFct, input);
|
||||
assertEquals(dateTime.toDate(), TimestampType.instance.compose(output));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeUuidToTimestamp()
|
||||
{
|
||||
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21 11:03:02");
|
||||
|
||||
long timeInMillis = dateTime.getMillis();
|
||||
ByteBuffer input = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timeInMillis, 0));
|
||||
ByteBuffer output = executeFunction(TimeFcts.timeUuidToTimestamp, input);
|
||||
assertEquals(dateTime.toDate(), TimestampType.instance.compose(output));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnixTimestampOfFct()
|
||||
{
|
||||
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21 11:03:02");
|
||||
|
||||
long timeInMillis = dateTime.getMillis();
|
||||
ByteBuffer input = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timeInMillis, 0));
|
||||
ByteBuffer output = executeFunction(TimeFcts.unixTimestampOfFct, input);
|
||||
assertEquals(timeInMillis, LongType.instance.compose(output).longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeUuidToUnixTimestamp()
|
||||
{
|
||||
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21 11:03:02");
|
||||
|
||||
long timeInMillis = dateTime.getMillis();
|
||||
ByteBuffer input = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timeInMillis, 0));
|
||||
ByteBuffer output = executeFunction(TimeFcts.timeUuidToUnixTimestamp, input);
|
||||
assertEquals(timeInMillis, LongType.instance.compose(output).longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeUuidToDate()
|
||||
{
|
||||
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21 11:03:02");
|
||||
|
||||
long timeInMillis = dateTime.getMillis();
|
||||
ByteBuffer input = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timeInMillis, 0));
|
||||
ByteBuffer output = executeFunction(TimeFcts.timeUuidtoDate, input);
|
||||
|
||||
long expectedTime = DateTimeFormat.forPattern("yyyy-MM-dd")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21")
|
||||
.getMillis();
|
||||
|
||||
assertEquals(expectedTime, SimpleDateType.instance.toTimeInMillis(output));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDateToTimestamp()
|
||||
{
|
||||
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21");
|
||||
|
||||
ByteBuffer input = SimpleDateType.instance.fromString("2015-05-21");
|
||||
ByteBuffer output = executeFunction(TimeFcts.dateToTimestamp, input);
|
||||
assertEquals(dateTime.toDate(), TimestampType.instance.compose(output));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDateToUnixTimestamp()
|
||||
{
|
||||
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21");
|
||||
|
||||
ByteBuffer input = SimpleDateType.instance.fromString("2015-05-21");
|
||||
ByteBuffer output = executeFunction(TimeFcts.dateToUnixTimestamp, input);
|
||||
assertEquals(dateTime.getMillis(), LongType.instance.compose(output).longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimestampToDate()
|
||||
{
|
||||
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21");
|
||||
|
||||
ByteBuffer input = TimestampType.instance.fromString("2015-05-21 11:03:02+00");
|
||||
ByteBuffer output = executeFunction(TimeFcts.timestampToDate, input);
|
||||
assertEquals(dateTime.getMillis(), SimpleDateType.instance.toTimeInMillis(output));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimestampToDateWithEmptyInput()
|
||||
{
|
||||
ByteBuffer output = executeFunction(TimeFcts.timestampToDate, ByteBufferUtil.EMPTY_BYTE_BUFFER);
|
||||
assertNull(output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimestampToUnixTimestamp()
|
||||
{
|
||||
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
|
||||
.withZone(DateTimeZone.UTC)
|
||||
.parseDateTime("2015-05-21 11:03:02");
|
||||
|
||||
ByteBuffer input = TimestampType.instance.decompose(dateTime.toDate());
|
||||
ByteBuffer output = executeFunction(TimeFcts.timestampToUnixTimestamp, input);
|
||||
assertEquals(dateTime.getMillis(), LongType.instance.compose(output).longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimestampToUnixTimestampWithEmptyInput()
|
||||
{
|
||||
ByteBuffer output = executeFunction(TimeFcts.timestampToUnixTimestamp, ByteBufferUtil.EMPTY_BYTE_BUFFER);
|
||||
assertNull(output);
|
||||
}
|
||||
|
||||
private static ByteBuffer executeFunction(Function function, ByteBuffer input)
|
||||
{
|
||||
List<ByteBuffer> params = Arrays.asList(input);
|
||||
return ((ScalarFunction) function).execute(Server.CURRENT_VERSION, params);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue