Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id D0C00200B8D for ; Thu, 8 Sep 2016 21:29:35 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id CF462160AAD; Thu, 8 Sep 2016 19:29:35 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 8AEF0160ABD for ; Thu, 8 Sep 2016 21:29:33 +0200 (CEST) Received: (qmail 19389 invoked by uid 500); 8 Sep 2016 19:29:32 -0000 Mailing-List: contact commits-help@phoenix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@phoenix.apache.org Delivered-To: mailing list commits@phoenix.apache.org Received: (qmail 19317 invoked by uid 99); 8 Sep 2016 19:29:32 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 08 Sep 2016 19:29:32 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 64C08E0902; Thu, 8 Sep 2016 19:29:32 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jamestaylor@apache.org To: commits@phoenix.apache.org Date: Thu, 08 Sep 2016 19:29:34 -0000 Message-Id: <8fe9ae4e660f4b749d519ad28c2f22f3@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [3/3] phoenix git commit: PHOENIX-2946 Projected comparison between date and timestamp columns always returns true archived-at: Thu, 08 Sep 2016 19:29:36 -0000 PHOENIX-2946 Projected comparison between date and timestamp columns always returns true Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/aa05da8a Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/aa05da8a Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/aa05da8a Branch: refs/heads/4.8-HBase-0.98 Commit: aa05da8aed42d9a2e45dc239ec6246c382782267 Parents: fbda580 Author: James Taylor Authored: Wed Sep 7 20:18:04 2016 -0700 Committer: James Taylor Committed: Thu Sep 8 12:29:02 2016 -0700 ---------------------------------------------------------------------- .../expression/function/CeilDateExpression.java | 3 + .../function/CeilTimestampExpression.java | 3 + .../expression/function/DateScalarFunction.java | 54 ++ .../expression/function/DayOfMonthFunction.java | 4 +- .../expression/function/HourFunction.java | 4 +- .../expression/function/MinuteFunction.java | 4 +- .../expression/function/MonthFunction.java | 4 +- .../function/RoundDateExpression.java | 3 + .../function/RoundJodaDateExpression.java | 3 + .../expression/function/SecondFunction.java | 4 +- .../expression/function/ToDateFunction.java | 10 +- .../expression/function/WeekFunction.java | 4 +- .../expression/function/YearFunction.java | 4 +- .../phoenix/jdbc/PhoenixPreparedStatement.java | 26 +- .../org/apache/phoenix/schema/SortOrder.java | 11 + .../apache/phoenix/schema/types/PDataType.java | 19 +- .../org/apache/phoenix/schema/types/PDate.java | 283 +++++----- .../apache/phoenix/schema/types/PDecimal.java | 6 +- .../org/apache/phoenix/schema/types/PLong.java | 519 ++++++++++--------- .../org/apache/phoenix/schema/types/PTime.java | 2 +- .../apache/phoenix/schema/types/PTimestamp.java | 42 +- .../phoenix/schema/types/PUnsignedDate.java | 259 +++++---- .../phoenix/schema/types/PUnsignedLong.java | 317 +++++------ .../phoenix/schema/types/PUnsignedTime.java | 2 +- .../schema/types/PUnsignedTimestamp.java | 152 ++---- .../java/org/apache/phoenix/util/DateUtil.java | 22 + .../phoenix/util/csv/CsvUpsertExecutor.java | 8 +- .../phoenix/schema/types/PDataTypeTest.java | 18 + 28 files changed, 969 insertions(+), 821 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilDateExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilDateExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilDateExpression.java index e3cd985..7629409 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilDateExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilDateExpression.java @@ -93,6 +93,9 @@ public class CeilDateExpression extends RoundDateExpression { @Override public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { if (children.get(0).evaluate(tuple, ptr)) { + if (ptr.getLength() == 0) { + return true; // child evaluated to null + } PDataType dataType = getDataType(); long time = dataType.getCodec().decodeLong(ptr, children.get(0).getSortOrder()); long value = roundTime(time); http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilTimestampExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilTimestampExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilTimestampExpression.java index f69f2f8..b3a2a97 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilTimestampExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/CeilTimestampExpression.java @@ -97,6 +97,9 @@ public class CeilTimestampExpression extends CeilDateExpression { @Override public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { if (children.get(0).evaluate(tuple, ptr)) { + if (ptr.getLength() == 0) { + return true; // child evaluated to null + } SortOrder sortOrder = children.get(0).getSortOrder(); PDataType dataType = getDataType(); int nanos = dataType.getNanos(ptr, sortOrder); http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DateScalarFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DateScalarFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DateScalarFunction.java new file mode 100644 index 0000000..aa56a0f --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DateScalarFunction.java @@ -0,0 +1,54 @@ +/* + * 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.phoenix.expression.function; + +import java.io.DataInput; +import java.io.IOException; +import java.util.List; + +import org.apache.phoenix.expression.Expression; +import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PDataType.PDataCodec; +import org.apache.phoenix.util.DateUtil; + +public abstract class DateScalarFunction extends ScalarFunction { + protected PDataCodec inputCodec; + + public DateScalarFunction() { + } + + public DateScalarFunction(List children) { + super(children); + init(); + } + + protected final PDataCodec getInputCodec() { + return inputCodec; + } + + @Override + public void readFields(DataInput input) throws IOException { + super.readFields(input); + init(); + } + + private void init() { + PDataType returnType = getChildren().get(0).getDataType(); + inputCodec = DateUtil.getCodecFor(returnType); + } +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DayOfMonthFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DayOfMonthFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DayOfMonthFunction.java index 0c328cf..fb5a68a 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DayOfMonthFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/DayOfMonthFunction.java @@ -38,7 +38,7 @@ import org.joda.time.DateTime; */ @BuiltInFunction(name=DayOfMonthFunction.NAME, args={@Argument(allowedTypes={PTimestamp.class})}) -public class DayOfMonthFunction extends ScalarFunction { +public class DayOfMonthFunction extends DateScalarFunction { public static final String NAME = "DAYOFMONTH"; public DayOfMonthFunction() { @@ -57,7 +57,7 @@ public class DayOfMonthFunction extends ScalarFunction { if ( ptr.getLength() == 0) { return true; //means null } - long dateTime = expression.getDataType().getCodec().decodeLong(ptr, expression.getSortOrder()); + long dateTime = inputCodec.decodeLong(ptr, expression.getSortOrder()); DateTime dt = new DateTime(dateTime); int day = dt.getDayOfMonth(); PDataType returnType = getDataType(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/HourFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/HourFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/HourFunction.java index 0e9efd8..7b9c8c0 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/HourFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/HourFunction.java @@ -37,7 +37,7 @@ import org.apache.phoenix.schema.types.PTimestamp; */ @BuiltInFunction(name=HourFunction.NAME, args={@Argument(allowedTypes={PTimestamp.class})}) -public class HourFunction extends ScalarFunction { +public class HourFunction extends DateScalarFunction { public static final String NAME = "HOUR"; public HourFunction() { @@ -56,7 +56,7 @@ public class HourFunction extends ScalarFunction { if ( ptr.getLength() == 0) { return true; //means null } - long dateTime = expression.getDataType().getCodec().decodeLong(ptr, expression.getSortOrder()); + long dateTime = inputCodec.decodeLong(ptr, expression.getSortOrder()); int hour = (int)(((dateTime/1000) % (24*3600))/3600); PDataType returnType = getDataType(); byte[] byteValue = new byte[returnType.getByteSize()]; http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MinuteFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MinuteFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MinuteFunction.java index fc721fc..6766e35 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MinuteFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MinuteFunction.java @@ -37,7 +37,7 @@ import org.apache.phoenix.schema.types.PTimestamp; */ @BuiltInFunction(name=MinuteFunction.NAME, args={@Argument(allowedTypes={PTimestamp.class})}) -public class MinuteFunction extends ScalarFunction { +public class MinuteFunction extends DateScalarFunction { public static final String NAME = "MINUTE"; public MinuteFunction() { @@ -56,7 +56,7 @@ public class MinuteFunction extends ScalarFunction { if ( ptr.getLength() == 0) { return true; //means null } - long dateTime = expression.getDataType().getCodec().decodeLong(ptr, expression.getSortOrder()); + long dateTime = inputCodec.decodeLong(ptr, expression.getSortOrder()); int minute = (int)(((dateTime/1000) % 3600)/60); PDataType returnType = getDataType(); byte[] byteValue = new byte[returnType.getByteSize()]; http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MonthFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MonthFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MonthFunction.java index 5ad6c34..bd6ff3e 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MonthFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/MonthFunction.java @@ -38,7 +38,7 @@ import org.joda.time.DateTime; */ @BuiltInFunction(name=MonthFunction.NAME, args={@Argument(allowedTypes={PTimestamp.class})}) -public class MonthFunction extends ScalarFunction { +public class MonthFunction extends DateScalarFunction { public static final String NAME = "MONTH"; public MonthFunction() { @@ -57,7 +57,7 @@ public class MonthFunction extends ScalarFunction { if ( ptr.getLength() == 0) { return true; //means null } - long dateTime = expression.getDataType().getCodec().decodeLong(ptr, expression.getSortOrder()); + long dateTime = inputCodec.decodeLong(ptr, expression.getSortOrder()); DateTime dt = new DateTime(dateTime); int month = dt.getMonthOfYear(); PDataType returnType = getDataType(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDateExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDateExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDateExpression.java index e2483ac..a80d745 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDateExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundDateExpression.java @@ -151,6 +151,9 @@ public class RoundDateExpression extends ScalarFunction { @Override public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { if (children.get(0).evaluate(tuple, ptr)) { + if (ptr.getLength() == 0) { + return true; // child evaluated to null + } PDataType dataType = getDataType(); long time = dataType.getCodec().decodeLong(ptr, children.get(0).getSortOrder()); long value = roundTime(time); http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundJodaDateExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundJodaDateExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundJodaDateExpression.java index 0dba80b..356c85f 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundJodaDateExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/RoundJodaDateExpression.java @@ -43,6 +43,9 @@ public abstract class RoundJodaDateExpression extends RoundDateExpression{ @Override public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { if (children.get(0).evaluate(tuple, ptr)) { + if (ptr.getLength() == 0) { + return true; // child evaluated to null + } PDataType dataType = getDataType(); long time = dataType.getCodec().decodeLong(ptr, children.get(0).getSortOrder()); DateTime dt = new DateTime(time,ISOChronology.getInstanceUTC()); http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SecondFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SecondFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SecondFunction.java index 5f39786..02bc455 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SecondFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SecondFunction.java @@ -37,7 +37,7 @@ import org.apache.phoenix.schema.types.PTimestamp; */ @BuiltInFunction(name=SecondFunction.NAME, args={@Argument(allowedTypes={PTimestamp.class})}) -public class SecondFunction extends ScalarFunction { +public class SecondFunction extends DateScalarFunction { public static final String NAME = "SECOND"; public SecondFunction() { @@ -56,7 +56,7 @@ public class SecondFunction extends ScalarFunction { if ( ptr.getLength() == 0) { return true; //means null } - long dateTime = expression.getDataType().getCodec().decodeLong(ptr, expression.getSortOrder()); + long dateTime = inputCodec.decodeLong(ptr, expression.getSortOrder()); int sec = (int)((dateTime/1000) % 60); PDataType returnType = getDataType(); byte[] byteValue = new byte[returnType.getByteSize()]; http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ToDateFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ToDateFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ToDateFunction.java index 17f6847..1930d92 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ToDateFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ToDateFunction.java @@ -32,6 +32,7 @@ import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction; import org.apache.phoenix.parse.ToDateParseNode; import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PDataType.PDataCodec; import org.apache.phoenix.schema.types.PDate; import org.apache.phoenix.schema.types.PVarchar; import org.apache.phoenix.util.DateUtil; @@ -53,6 +54,7 @@ import org.apache.phoenix.util.DateUtil; public class ToDateFunction extends ScalarFunction { public static final String NAME = "TO_DATE"; private DateUtil.DateTimeParser dateParser; + private PDataCodec codec; protected String dateFormat; protected String timeZoneId; @@ -80,6 +82,7 @@ public class ToDateFunction extends ScalarFunction { // server to evaluate using the local time zone. Instead, we want // to use the client local time zone. this.timeZoneId = this.dateParser.getTimeZone().getID(); + this.codec = DateUtil.getCodecFor(getDataType()); } @Override @@ -110,15 +113,18 @@ public class ToDateFunction extends ScalarFunction { @Override public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { Expression expression = getExpression(); - if (!expression.evaluate(tuple, ptr) || ptr.getLength() == 0) { + if (!expression.evaluate(tuple, ptr)) { return false; } + if (ptr.getLength() == 0) { + return true; + } PDataType type = expression.getDataType(); String dateStr = (String)type.toObject(ptr, expression.getSortOrder()); long epochTime = dateParser.parseDateTime(dateStr); PDataType returnType = getDataType(); byte[] byteValue = new byte[returnType.getByteSize()]; - returnType.getCodec().encodeLong(epochTime, byteValue, 0); + codec.encodeLong(epochTime, byteValue, 0); ptr.set(byteValue); return true; } http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/WeekFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/WeekFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/WeekFunction.java index 126aba8..3f6d772 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/WeekFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/WeekFunction.java @@ -38,7 +38,7 @@ import org.joda.time.DateTime; */ @BuiltInFunction(name=WeekFunction.NAME, args={@Argument(allowedTypes={PTimestamp.class})}) -public class WeekFunction extends ScalarFunction { +public class WeekFunction extends DateScalarFunction { public static final String NAME = "WEEK"; public WeekFunction() { @@ -57,7 +57,7 @@ public class WeekFunction extends ScalarFunction { if ( ptr.getLength() == 0) { return true; //means null } - long dateTime = expression.getDataType().getCodec().decodeLong(ptr, expression.getSortOrder()); + long dateTime = inputCodec.decodeLong(ptr, expression.getSortOrder()); DateTime dt = new DateTime(dateTime); int week = dt.getWeekOfWeekyear(); PDataType returnType = getDataType(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/YearFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/YearFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/YearFunction.java index f1958e1..fcab8d2 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/YearFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/YearFunction.java @@ -37,7 +37,7 @@ import org.joda.time.DateTime; */ @BuiltInFunction(name=YearFunction.NAME, args={@Argument(allowedTypes={PTimestamp.class})}) -public class YearFunction extends ScalarFunction { +public class YearFunction extends DateScalarFunction { public static final String NAME = "YEAR"; public YearFunction() { @@ -56,7 +56,7 @@ public class YearFunction extends ScalarFunction { if ( ptr.getLength() == 0) { return true; //means null } - long dateTime = expression.getDataType().getCodec().decodeLong(ptr, expression.getSortOrder()); + long dateTime = inputCodec.decodeLong(ptr, expression.getSortOrder()); DateTime dt = new DateTime(dateTime); int year = dt.getYear(); PDataType returnType = getDataType(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java index 9c6a94b..9bba3d3 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixPreparedStatement.java @@ -361,11 +361,17 @@ public class PhoenixPreparedStatement extends PhoenixStatement implements Prepar @Override public void setDate(int parameterIndex, Date x) throws SQLException { + if (x != null) { // Since Date is mutable, make a copy + x = new Date(x.getTime()); + } setParameter(parameterIndex, x); } @Override public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { + if (x != null) { // Since Date is mutable, make a copy + x = new Date(x.getTime()); + } cal.setTime(x); setParameter(parameterIndex, new Date(cal.getTimeInMillis())); } @@ -475,23 +481,39 @@ public class PhoenixPreparedStatement extends PhoenixStatement implements Prepar @Override public void setTime(int parameterIndex, Time x) throws SQLException { + if (x != null) { // Since Time is mutable, make a copy + x = new Time(x.getTime()); + } setParameter(parameterIndex, x); } @Override public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { + if (x != null) { // Since Time is mutable, make a copy + x = new Time(x.getTime()); + } cal.setTime(x); setParameter(parameterIndex, new Time(cal.getTimeInMillis())); } + private void setTimestampParameter(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { + if (x != null) { // Since Timestamp is mutable, make a copy + int nanos = x.getNanos(); + x = new Timestamp(x.getTime()); + x.setNanos(nanos); + } + // TODO: deal with Calendar + setParameter(parameterIndex, x); + } + @Override public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { - setParameter(parameterIndex, x); + setTimestampParameter(parameterIndex, x, null); } @Override public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { - setParameter(parameterIndex, x); + setTimestampParameter(parameterIndex, x, cal); } @Override http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/schema/SortOrder.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/SortOrder.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/SortOrder.java index 91b6cd0..1d32a06 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/SortOrder.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/SortOrder.java @@ -55,6 +55,11 @@ public enum SortOrder { public CompareOp transform(CompareOp op) { return op; } + + @Override + public byte normalize(byte b) { + return b; + } }, DESC(1) { @@ -71,6 +76,11 @@ public enum SortOrder { } throw new IllegalArgumentException("Add the missing case statement!"); } + + @Override + public byte normalize(byte b) { + return SortOrder.invert(b); + } }; /** @@ -137,4 +147,5 @@ public enum SortOrder { } public abstract CompareOp transform(CompareOp op); + public abstract byte normalize(byte b); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java index 0f0328a..5d611e9 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java @@ -89,8 +89,7 @@ public abstract class PDataType implements DataType, Comparable implements DataType, Comparable rhsLength) { + int minOffset = lhsOffset + rhsLength; + for (int i = lhsOffset + lhsLength - 1; i >= minOffset && lhsSortOrder.normalize(lhs[i]) == 0; i--,lhsLength--) { + } + } else { + int minOffset = rhsOffset + lhsLength; + for (int i = rhsOffset + rhsLength - 1; i >= minOffset && rhsSortOrder.normalize(rhs[i]) == 0; i--,rhsLength--) { + } + } + } return compareTo(lhs, lhsOffset, lhsLength, lhsSortOrder, rhs, rhsOffset, rhsLength, rhsSortOrder); } } @@ -196,8 +207,8 @@ public abstract class PDataType implements DataType, Comparable { - public static final PDate INSTANCE = new PDate(); - - private PDate() { - super("DATE", Types.DATE, Date.class, - new DateCodec(), 11); // After TIMESTAMP and DATE to ensure toLiteral finds those first - } - - @Override - public byte[] toBytes(Object object) { - byte[] bytes = new byte[getByteSize()]; - toBytes(object, bytes, 0); - return bytes; - } - - @Override - public int toBytes(Object object, byte[] bytes, int offset) { - if (object == null) { - getCodec().encodeLong(0l, bytes, offset); + public static final PDate INSTANCE = new PDate(); + + private PDate() { + super("DATE", Types.DATE, Date.class, + new DateCodec(), 11); // After TIMESTAMP and DATE to ensure toLiteral finds those first + } + + @Override + public byte[] toBytes(Object object) { + byte[] bytes = new byte[getByteSize()]; + toBytes(object, bytes, 0); + return bytes; + } + + @Override + public int toBytes(Object object, byte[] bytes, int offset) { + if (object == null) { + getCodec().encodeLong(0l, bytes, offset); + return this.getByteSize(); + } + getCodec().encodeLong(((java.util.Date) object).getTime(), bytes, offset); return this.getByteSize(); } - getCodec().encodeLong(((java.util.Date) object).getTime(), bytes, offset); - return this.getByteSize(); - } - - @Override - public Object toObject(Object object, PDataType actualType) { - if (object == null) { - return null; - } - if (equalsAny(actualType, PTime.INSTANCE, PUnsignedTime.INSTANCE)) { - return new Date(((java.sql.Time) object).getTime()); - } else if (equalsAny(actualType, PTimestamp.INSTANCE, PUnsignedTimestamp.INSTANCE)) { - return new Date(((java.sql.Timestamp) object).getTime()); - } else if (equalsAny(actualType, PDate.INSTANCE, PUnsignedDate.INSTANCE)) { - return object; - } else if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE)) { - return new Date((Long) object); - } else if (actualType == PDecimal.INSTANCE) { - return new Date(((BigDecimal) object).longValueExact()); - } else if (actualType == PVarchar.INSTANCE) { - return DateUtil.parseDate((String) object); - } - return throwConstraintViolationException(actualType, this); - } - - @Override - public Date toObject(byte[] b, int o, int l, PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) { - if (l == 0) { - return null; - } - if (equalsAny(actualType, PTimestamp.INSTANCE, PUnsignedTimestamp.INSTANCE, PDate.INSTANCE, - PUnsignedDate.INSTANCE, PTime.INSTANCE, PUnsignedTime.INSTANCE, PLong.INSTANCE, - PUnsignedLong.INSTANCE)) { - return new Date(actualType.getCodec().decodeLong(b, o, sortOrder)); - } else if (actualType == PDecimal.INSTANCE) { - BigDecimal bd = (BigDecimal) actualType.toObject(b, o, l, actualType, sortOrder); - return new Date(bd.longValueExact()); - } - throwConstraintViolationException(actualType, this); - return null; - } - - @Override - public boolean isCastableTo(PDataType targetType) { - return super.isCastableTo(targetType) || - equalsAny(targetType, PDecimal.INSTANCE, PLong.INSTANCE, PUnsignedLong.INSTANCE); - } - - @Override - public boolean isCoercibleTo(PDataType targetType) { - return equalsAny(targetType, PDate.INSTANCE, PTime.INSTANCE, PTimestamp.INSTANCE, PVarbinary.INSTANCE, PBinary.INSTANCE); - } - - @Override - public boolean isCoercibleTo(PDataType targetType, Object value) { - if (value != null) { - if (equalsAny(targetType, PUnsignedTimestamp.INSTANCE, PUnsignedDate.INSTANCE, - PUnsignedTime.INSTANCE)) { - return ((java.util.Date) value).getTime() >= 0; - } - } - return super.isCoercibleTo(targetType, value); - } - - @Override - public boolean isFixedWidth() { - return true; - } - - @Override - public Integer getByteSize() { - return Bytes.SIZEOF_LONG; - } - - @Override - public int compareTo(Object lhs, Object rhs, PDataType rhsType) { - if (rhsType == PTimestamp.INSTANCE || rhsType == PUnsignedTimestamp.INSTANCE) { - return -rhsType.compareTo(rhs, lhs, PTime.INSTANCE); - } - return ((java.util.Date) lhs).compareTo((java.util.Date) rhs); - } - - @Override - public Object toObject(String value) { - if (value == null || value.length() == 0) { - return null; - } - return DateUtil.parseDate(value); - } - - @Override - public boolean isBytesComparableWith(PDataType otherType) { - return super.isBytesComparableWith(otherType) || otherType == PTime.INSTANCE; - } - - @Override + + @Override + public Object toObject(Object object, PDataType actualType) { + if (object == null) { + return null; + } + if (equalsAny(actualType, PTime.INSTANCE, PUnsignedTime.INSTANCE)) { + return new Date(((java.sql.Time) object).getTime()); + } else if (equalsAny(actualType, PTimestamp.INSTANCE, PUnsignedTimestamp.INSTANCE)) { + return new Date(((java.sql.Timestamp) object).getTime()); + } else if (equalsAny(actualType, PDate.INSTANCE, PUnsignedDate.INSTANCE)) { + return object; + } else if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE)) { + return new Date((Long) object); + } else if (actualType == PDecimal.INSTANCE) { + return new Date(((BigDecimal) object).longValueExact()); + } else if (actualType == PVarchar.INSTANCE) { + return DateUtil.parseDate((String) object); + } + return throwConstraintViolationException(actualType, this); + } + + @Override + public Date toObject(byte[] b, int o, int l, PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) { + if (l == 0) { + return null; + } + if (actualType.getCodec() != null ) { + return new Date(actualType.getCodec().decodeLong(b, o, sortOrder)); + } else if (actualType == PTimestamp.INSTANCE) { + return new Date(PDate.INSTANCE.getCodec().decodeLong(b, o, sortOrder)); + } else if (actualType == PUnsignedTimestamp.INSTANCE) { + return new Date(PUnsignedDate.INSTANCE.getCodec().decodeLong(b, o, sortOrder)); + } else if (actualType == PDecimal.INSTANCE) { + BigDecimal bd = (BigDecimal) actualType.toObject(b, o, l, actualType, sortOrder); + return new Date(bd.longValueExact()); + } + throwConstraintViolationException(actualType, this); + return null; + } + + @Override + public boolean isCastableTo(PDataType targetType) { + return super.isCastableTo(targetType) || + equalsAny(targetType, PDecimal.INSTANCE, PLong.INSTANCE, PUnsignedLong.INSTANCE); + } + + @Override + public boolean isCoercibleTo(PDataType targetType) { + return equalsAny(targetType, PDate.INSTANCE, PTime.INSTANCE, PTimestamp.INSTANCE, PVarbinary.INSTANCE, PBinary.INSTANCE); + } + + @Override + public boolean isCoercibleTo(PDataType targetType, Object value) { + if (value != null) { + if (equalsAny(targetType, PUnsignedTimestamp.INSTANCE, PUnsignedDate.INSTANCE, + PUnsignedTime.INSTANCE)) { + return ((java.util.Date) value).getTime() >= 0; + } + } + return super.isCoercibleTo(targetType, value); + } + + @Override + public boolean isFixedWidth() { + return true; + } + + @Override + public Integer getByteSize() { + return Bytes.SIZEOF_LONG; + } + + @Override + public int compareTo(Object lhs, Object rhs, PDataType rhsType) { + if (rhsType == PTimestamp.INSTANCE || rhsType == PUnsignedTimestamp.INSTANCE) { + return -rhsType.compareTo(rhs, lhs, PTime.INSTANCE); + } + return ((java.util.Date) lhs).compareTo((java.util.Date) rhs); + } + + @Override + public Object toObject(String value) { + if (value == null || value.length() == 0) { + return null; + } + return DateUtil.parseDate(value); + } + + @Override + public boolean isBytesComparableWith(PDataType otherType) { + return super.isBytesComparableWith(otherType) || otherType == PTime.INSTANCE || otherType == PTimestamp.INSTANCE || otherType == PLong.INSTANCE; + } + + @Override public String toStringLiteral(Object o, Format formatter) { if (formatter == null) { // If default formatter has not been overridden, @@ -156,40 +158,39 @@ public class PDate extends PDataType { + StringUtil.escapeStringConstant(super.toStringLiteral(o, formatter)) + "'"; } - @Override - public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType, - Integer maxLength, Integer scale, SortOrder actualModifier, Integer desiredMaxLength, Integer desiredScale, - SortOrder expectedModifier) { - if (ptr.getLength() > 0 && actualType == PTimestamp.INSTANCE - && actualModifier == expectedModifier) { - ptr.set(ptr.get(), ptr.getOffset(), getByteSize()); - return; + @Override + public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType, + Integer maxLength, Integer scale, SortOrder actualModifier, Integer desiredMaxLength, Integer desiredScale, + SortOrder expectedModifier) { + // Decrease size of TIMESTAMP to size of DATE and continue coerce + if (ptr.getLength() > getByteSize()) { + ptr.set(ptr.get(), ptr.getOffset(), getByteSize()); + } + super.coerceBytes(ptr, object, actualType, maxLength, scale, actualModifier, desiredMaxLength, + desiredScale, expectedModifier); } - super.coerceBytes(ptr, object, actualType, maxLength, scale, actualModifier, desiredMaxLength, - desiredScale, expectedModifier); - } - - @Override - public Object getSampleValue(Integer maxLength, Integer arrayLength) { - return new Date((Long) PLong.INSTANCE.getSampleValue(maxLength, arrayLength)); - } - - static class DateCodec extends PLong.LongCodec { @Override - public int decodeInt(byte[] b, int o, SortOrder sortOrder) { - throw new UnsupportedOperationException(); + public Object getSampleValue(Integer maxLength, Integer arrayLength) { + return new Date((Long) PLong.INSTANCE.getSampleValue(maxLength, arrayLength)); } - @Override - public PhoenixArrayFactory getPhoenixArrayFactory() { - return new PhoenixArrayFactory() { + static class DateCodec extends PLong.LongCodec { + + @Override + public int decodeInt(byte[] b, int o, SortOrder sortOrder) { + throw new UnsupportedOperationException(); + } @Override - public PhoenixArray newArray(PDataType type, Object[] elements) { - return new PhoenixArray(type, elements); + public PhoenixArrayFactory getPhoenixArrayFactory() { + return new PhoenixArrayFactory() { + + @Override + public PhoenixArray newArray(PDataType type, Object[] elements) { + return new PhoenixArray(type, elements); + } + }; } - }; } - } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java index ff6e186..17910de 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java @@ -28,6 +28,7 @@ import org.apache.phoenix.query.QueryConstants; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.TypeMismatchException; import org.apache.phoenix.util.ByteUtil; +import org.apache.phoenix.util.DateUtil; import org.apache.phoenix.util.NumberUtil; import com.google.common.base.Preconditions; @@ -136,9 +137,8 @@ public class PDecimal extends PRealNumber { return BigDecimal.valueOf(actualType.getCodec().decodeFloat(b, o, sortOrder)); } else if (equalsAny(actualType, PDouble.INSTANCE, PUnsignedDouble.INSTANCE)) { return BigDecimal.valueOf(actualType.getCodec().decodeDouble(b, o, sortOrder)); - } else if (equalsAny(actualType, PTimestamp.INSTANCE, - PUnsignedTimestamp.INSTANCE)) { - long millisPart = actualType.getCodec().decodeLong(b, o, sortOrder); + } else if (equalsAny(actualType, PTimestamp.INSTANCE, PUnsignedTimestamp.INSTANCE)) { + long millisPart = DateUtil.getCodecFor(actualType).decodeLong(b, o, sortOrder); int nanoPart = PUnsignedInt.INSTANCE.getCodec().decodeInt(b, o + Bytes.SIZEOF_LONG, sortOrder); BigDecimal nanosPart = BigDecimal.valueOf( (nanoPart % QueryConstants.MILLIS_TO_NANOS_CONVERTOR) http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLong.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLong.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLong.java index 82fd8d3..2d6ff27 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLong.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLong.java @@ -20,6 +20,7 @@ package org.apache.phoenix.schema.types; import java.math.BigDecimal; import java.sql.Types; +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.schema.SortOrder; @@ -29,304 +30,316 @@ import com.google.common.primitives.Longs; public class PLong extends PWholeNumber { - public static final PLong INSTANCE = new PLong(); + public static final PLong INSTANCE = new PLong(); - private PLong() { - super("BIGINT", Types.BIGINT, Long.class, new LongCodec(), 2); - } - - @Override - public Integer getScale(Object o) { - return ZERO; - } - - @Override - public byte[] toBytes(Object object) { - byte[] b = new byte[Bytes.SIZEOF_LONG]; - toBytes(object, b, 0); - return b; - } - - @Override - public int toBytes(Object object, byte[] b, int o) { - if (object == null) { - throw newIllegalDataException(this + " may not be null"); + private PLong() { + super("BIGINT", Types.BIGINT, Long.class, new LongCodec(), 2); } - return this.getCodec().encodeLong(((Number) object).longValue(), b, o); - } - @Override - public Object toObject(Object object, PDataType actualType) { - if (object == null) { - return null; - } - long s; - if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE)) { - return object; - } else if (equalsAny(actualType, PUnsignedInt.INSTANCE, - PInteger.INSTANCE)) { - s = (Integer) object; - return s; - } else if (equalsAny(actualType, PTinyint.INSTANCE, PUnsignedTinyint.INSTANCE)) { - s = (Byte) object; - return s; - } else if (equalsAny(actualType, PSmallint.INSTANCE, PUnsignedSmallint.INSTANCE)) { - s = (Short) object; - return s; - } else if (equalsAny(actualType, PFloat.INSTANCE, PUnsignedFloat.INSTANCE)) { - Float f = (Float) object; - if (f > Long.MAX_VALUE || f < Long.MIN_VALUE) { - throw newIllegalDataException( - actualType + " value " + f + " cannot be cast to Long without changing its value"); - } - s = f.longValue(); - return s; - } else if (equalsAny(actualType, PDouble.INSTANCE, PUnsignedDouble.INSTANCE)) { - Double de = (Double) object; - if (de > Long.MAX_VALUE || de < Long.MIN_VALUE) { - throw newIllegalDataException( - actualType + " value " + de + " cannot be cast to Long without changing its value"); - } - s = de.longValue(); - return s; - } else if (actualType == PDecimal.INSTANCE) { - BigDecimal d = (BigDecimal) object; - return d.longValueExact(); - } else if (equalsAny(actualType, PDate.INSTANCE, PUnsignedDate.INSTANCE, PTime.INSTANCE, - PUnsignedTime.INSTANCE)) { - java.util.Date date = (java.util.Date) object; - return date.getTime(); - } - return throwConstraintViolationException(actualType, this); - } - - @Override - public Long toObject(byte[] b, int o, int l, PDataType actualType, SortOrder sortOrder, - Integer maxLength, Integer scale) { - if (l == 0) { - return null; - } - if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE, - PInteger.INSTANCE, PUnsignedInt.INSTANCE, PSmallint.INSTANCE, - PUnsignedSmallint.INSTANCE, PTinyint.INSTANCE, PUnsignedTinyint.INSTANCE, PFloat.INSTANCE, - PUnsignedFloat.INSTANCE, PDouble.INSTANCE, PUnsignedDouble.INSTANCE, PDate.INSTANCE, - PUnsignedDate.INSTANCE, PTime.INSTANCE, PUnsignedTime.INSTANCE)) { - return actualType.getCodec().decodeLong(b, o, sortOrder); - } else if (actualType == PDecimal.INSTANCE) { - BigDecimal bd = (BigDecimal) actualType.toObject(b, o, l, actualType, sortOrder); - return bd.longValueExact(); - } - throwConstraintViolationException(actualType, this); - return null; - } - - @Override - public boolean isCoercibleTo(PDataType targetType) { - // In general, don't allow conversion of LONG to INTEGER. There are times when - // we check isComparableTo for a more relaxed check and then throw a runtime - // exception if we overflow - return equalsAny(targetType, this, PDecimal.INSTANCE, PVarbinary.INSTANCE, PBinary.INSTANCE, PDouble.INSTANCE); - } - - @Override - public boolean isComparableTo(PDataType targetType) { - return PDecimal.INSTANCE.isComparableTo(targetType); - } - - @Override - public boolean isCoercibleTo(PDataType targetType, Object value) { - if (value != null) { - long l; - if (equalsAny(targetType, PUnsignedDouble.INSTANCE, PUnsignedFloat.INSTANCE, - PUnsignedLong.INSTANCE)) { - l = (Long) value; - return l >= 0; - } else if (targetType.equals(PUnsignedInt.INSTANCE)) { - l = (Long) value; - return (l >= 0 && l <= Integer.MAX_VALUE); - } else if (targetType.equals(PInteger.INSTANCE)) { - l = (Long) value; - return (l >= Integer.MIN_VALUE && l <= Integer.MAX_VALUE); - } else if (targetType.equals(PUnsignedSmallint.INSTANCE)) { - l = (Long) value; - return (l >= 0 && l <= Short.MAX_VALUE); - } else if (targetType.equals(PSmallint.INSTANCE)) { - l = (Long) value; - return (l >= Short.MIN_VALUE && l <= Short.MAX_VALUE); - } else if (targetType.equals(PTinyint.INSTANCE)) { - l = (Long) value; - return (l >= Byte.MIN_VALUE && l <= Byte.MAX_VALUE); - } else if (targetType.equals(PUnsignedTinyint.INSTANCE)) { - l = (Long) value; - return (l >= 0 && l <= Byte.MAX_VALUE); - } - } - return super.isCoercibleTo(targetType, value); - } - - @Override - public boolean isCastableTo(PDataType targetType) { - return super.isCastableTo(targetType) || targetType.isCoercibleTo(PTimestamp.INSTANCE); - } - - @Override - public boolean isFixedWidth() { - return true; - } - - @Override - public Integer getByteSize() { - return Bytes.SIZEOF_LONG; - } - - @Override - public Integer getMaxLength(Object o) { - return LONG_PRECISION; - } - - @Override - public int compareTo(Object lhs, Object rhs, PDataType rhsType) { - if (rhsType == PDecimal.INSTANCE) { - return -((BigDecimal) rhs).compareTo(BigDecimal.valueOf(((Number) lhs).longValue())); - } else if (equalsAny(rhsType, PDouble.INSTANCE, PFloat.INSTANCE, PUnsignedDouble.INSTANCE, PUnsignedFloat.INSTANCE)) { - return Doubles.compare(((Number) lhs).doubleValue(), ((Number) rhs).doubleValue()); + @Override + public Integer getScale(Object o) { + return ZERO; } - return Longs.compare(((Number) lhs).longValue(), ((Number) rhs).longValue()); - } - @Override - public Object toObject(String value) { - if (value == null || value.length() == 0) { - return null; - } - try { - return Long.parseLong(value); - } catch (NumberFormatException e) { - throw newIllegalDataException(e); + @Override + public byte[] toBytes(Object object) { + byte[] b = new byte[Bytes.SIZEOF_LONG]; + toBytes(object, b, 0); + return b; } - } - @Override - public Object getSampleValue(Integer maxLength, Integer arrayLength) { - return RANDOM.get().nextLong(); - } + @Override + public int toBytes(Object object, byte[] b, int o) { + if (object == null) { + throw newIllegalDataException(this + " may not be null"); + } + return this.getCodec().encodeLong(((Number) object).longValue(), b, o); + } - static class LongCodec extends BaseCodec { + @Override + public Object toObject(Object object, PDataType actualType) { + if (object == null) { + return null; + } + long s; + if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE)) { + return object; + } else if (equalsAny(actualType, PUnsignedInt.INSTANCE, + PInteger.INSTANCE)) { + s = (Integer) object; + return s; + } else if (equalsAny(actualType, PTinyint.INSTANCE, PUnsignedTinyint.INSTANCE)) { + s = (Byte) object; + return s; + } else if (equalsAny(actualType, PSmallint.INSTANCE, PUnsignedSmallint.INSTANCE)) { + s = (Short) object; + return s; + } else if (equalsAny(actualType, PFloat.INSTANCE, PUnsignedFloat.INSTANCE)) { + Float f = (Float) object; + if (f > Long.MAX_VALUE || f < Long.MIN_VALUE) { + throw newIllegalDataException( + actualType + " value " + f + " cannot be cast to Long without changing its value"); + } + s = f.longValue(); + return s; + } else if (equalsAny(actualType, PDouble.INSTANCE, PUnsignedDouble.INSTANCE)) { + Double de = (Double) object; + if (de > Long.MAX_VALUE || de < Long.MIN_VALUE) { + throw newIllegalDataException( + actualType + " value " + de + " cannot be cast to Long without changing its value"); + } + s = de.longValue(); + return s; + } else if (actualType == PDecimal.INSTANCE) { + BigDecimal d = (BigDecimal) object; + return d.longValueExact(); + } else if (equalsAny(actualType, PDate.INSTANCE, PUnsignedDate.INSTANCE, PTime.INSTANCE, + PUnsignedTime.INSTANCE)) { + java.util.Date date = (java.util.Date) object; + return date.getTime(); + } + return throwConstraintViolationException(actualType, this); + } @Override - public float decodeFloat(byte[] b, int o, SortOrder sortOrder) { - return decodeLong(b, o, sortOrder); + public Long toObject(byte[] b, int o, int l, PDataType actualType, SortOrder sortOrder, + Integer maxLength, Integer scale) { + if (l == 0) { + return null; + } + if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE, + PInteger.INSTANCE, PUnsignedInt.INSTANCE, PSmallint.INSTANCE, + PUnsignedSmallint.INSTANCE, PTinyint.INSTANCE, PUnsignedTinyint.INSTANCE, PFloat.INSTANCE, + PUnsignedFloat.INSTANCE, PDouble.INSTANCE, PUnsignedDouble.INSTANCE, PDate.INSTANCE, + PUnsignedDate.INSTANCE, PTime.INSTANCE, PUnsignedTime.INSTANCE)) { + return actualType.getCodec().decodeLong(b, o, sortOrder); + } else if (actualType == PDecimal.INSTANCE) { + BigDecimal bd = (BigDecimal) actualType.toObject(b, o, l, actualType, sortOrder); + return bd.longValueExact(); + } + throwConstraintViolationException(actualType, this); + return null; } @Override - public double decodeDouble(byte[] b, int o, SortOrder sortOrder) { - return decodeLong(b, o, sortOrder); + public boolean isCoercibleTo(PDataType targetType) { + // In general, don't allow conversion of LONG to INTEGER. There are times when + // we check isComparableTo for a more relaxed check and then throw a runtime + // exception if we overflow + return equalsAny(targetType, this, PDecimal.INSTANCE, PVarbinary.INSTANCE, PBinary.INSTANCE, PDouble.INSTANCE); } @Override - public long decodeLong(byte[] bytes, int o, SortOrder sortOrder) { - Preconditions.checkNotNull(sortOrder); - checkForSufficientLength(bytes, o, Bytes.SIZEOF_LONG); - long v; - byte b = bytes[o]; - if (sortOrder == SortOrder.ASC) { - v = b ^ 0x80; // Flip sign bit back - for (int i = 1; i < Bytes.SIZEOF_LONG; i++) { - b = bytes[o + i]; - v = (v << 8) + (b & 0xff); + public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType, + Integer maxLength, Integer scale, SortOrder actualModifier, Integer desiredMaxLength, Integer desiredScale, + SortOrder expectedModifier) { + // Decrease size of TIMESTAMP to size of LONG and continue coerce + if (ptr.getLength() > getByteSize()) { + ptr.set(ptr.get(), ptr.getOffset(), getByteSize()); } - } else { - b = (byte) (b ^ 0xff); - v = b ^ 0x80; // Flip sign bit back - for (int i = 1; i < Bytes.SIZEOF_LONG; i++) { - b = bytes[o + i]; - b ^= 0xff; - v = (v << 8) + (b & 0xff); - } - } - return v; + super.coerceBytes(ptr, object, actualType, maxLength, scale, actualModifier, desiredMaxLength, + desiredScale, expectedModifier); } @Override - public int decodeInt(byte[] b, int o, SortOrder sortOrder) { - long v = decodeLong(b, o, sortOrder); - if (v < Integer.MIN_VALUE || v > Integer.MAX_VALUE) { - throw newIllegalDataException( - "Value " + v + " cannot be cast to Integer without changing its value"); - } - return (int) v; + public boolean isComparableTo(PDataType targetType) { + return PDecimal.INSTANCE.isComparableTo(targetType); } @Override - public int encodeFloat(float v, byte[] b, int o) { - if (v < Long.MIN_VALUE || v > Long.MAX_VALUE) { - throw newIllegalDataException( - "Value " + v + " cannot be encoded as an Long without changing its value"); - } - return encodeLong((long) v, b, o); + public boolean isCoercibleTo(PDataType targetType, Object value) { + if (value != null) { + long l; + if (equalsAny(targetType, PUnsignedDouble.INSTANCE, PUnsignedFloat.INSTANCE, + PUnsignedLong.INSTANCE)) { + l = (Long) value; + return l >= 0; + } else if (targetType.equals(PUnsignedInt.INSTANCE)) { + l = (Long) value; + return (l >= 0 && l <= Integer.MAX_VALUE); + } else if (targetType.equals(PInteger.INSTANCE)) { + l = (Long) value; + return (l >= Integer.MIN_VALUE && l <= Integer.MAX_VALUE); + } else if (targetType.equals(PUnsignedSmallint.INSTANCE)) { + l = (Long) value; + return (l >= 0 && l <= Short.MAX_VALUE); + } else if (targetType.equals(PSmallint.INSTANCE)) { + l = (Long) value; + return (l >= Short.MIN_VALUE && l <= Short.MAX_VALUE); + } else if (targetType.equals(PTinyint.INSTANCE)) { + l = (Long) value; + return (l >= Byte.MIN_VALUE && l <= Byte.MAX_VALUE); + } else if (targetType.equals(PUnsignedTinyint.INSTANCE)) { + l = (Long) value; + return (l >= 0 && l <= Byte.MAX_VALUE); + } + } + return super.isCoercibleTo(targetType, value); } @Override - public int encodeDouble(double v, byte[] b, int o) { - if (v < Long.MIN_VALUE || v > Long.MAX_VALUE) { - throw newIllegalDataException( - "Value " + v + " cannot be encoded as an Long without changing its value"); - } - return encodeLong((long) v, b, o); + public boolean isCastableTo(PDataType targetType) { + return super.isCastableTo(targetType) || targetType.isCoercibleTo(PTimestamp.INSTANCE); } @Override - public int encodeLong(long v, byte[] b, int o) { - checkForSufficientLength(b, o, Bytes.SIZEOF_LONG); - b[o + 0] = (byte) ((v >> 56) ^ 0x80); // Flip sign bit so that INTEGER is binary comparable - b[o + 1] = (byte) (v >> 48); - b[o + 2] = (byte) (v >> 40); - b[o + 3] = (byte) (v >> 32); - b[o + 4] = (byte) (v >> 24); - b[o + 5] = (byte) (v >> 16); - b[o + 6] = (byte) (v >> 8); - b[o + 7] = (byte) v; - return Bytes.SIZEOF_LONG; + public boolean isFixedWidth() { + return true; } @Override - public byte decodeByte(byte[] b, int o, SortOrder sortOrder) { - long v = decodeLong(b, o, sortOrder); - if (v < Byte.MIN_VALUE || v > Byte.MAX_VALUE) { - throw newIllegalDataException( - "Value " + v + " cannot be cast to Byte without changing its value"); - } - return (byte) v; + public Integer getByteSize() { + return Bytes.SIZEOF_LONG; } @Override - public short decodeShort(byte[] b, int o, SortOrder sortOrder) { - long v = decodeLong(b, o, sortOrder); - if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) { - throw newIllegalDataException( - "Value " + v + " cannot be cast to Short without changing its value"); - } - return (short) v; + public Integer getMaxLength(Object o) { + return LONG_PRECISION; } @Override - public int encodeByte(byte v, byte[] b, int o) { - return encodeLong(v, b, o); + public int compareTo(Object lhs, Object rhs, PDataType rhsType) { + if (rhsType == PDecimal.INSTANCE) { + return -((BigDecimal) rhs).compareTo(BigDecimal.valueOf(((Number) lhs).longValue())); + } else if (equalsAny(rhsType, PDouble.INSTANCE, PFloat.INSTANCE, PUnsignedDouble.INSTANCE, PUnsignedFloat.INSTANCE)) { + return Doubles.compare(((Number) lhs).doubleValue(), ((Number) rhs).doubleValue()); + } + return Longs.compare(((Number) lhs).longValue(), ((Number) rhs).longValue()); } @Override - public int encodeShort(short v, byte[] b, int o) { - return encodeLong(v, b, o); + public Object toObject(String value) { + if (value == null || value.length() == 0) { + return null; + } + try { + return Long.parseLong(value); + } catch (NumberFormatException e) { + throw newIllegalDataException(e); + } } @Override - public PhoenixArrayFactory getPhoenixArrayFactory() { - return new PhoenixArrayFactory() { + public Object getSampleValue(Integer maxLength, Integer arrayLength) { + return RANDOM.get().nextLong(); + } + + static class LongCodec extends BaseCodec { + + @Override + public float decodeFloat(byte[] b, int o, SortOrder sortOrder) { + return decodeLong(b, o, sortOrder); + } + + @Override + public double decodeDouble(byte[] b, int o, SortOrder sortOrder) { + return decodeLong(b, o, sortOrder); + } + + @Override + public long decodeLong(byte[] bytes, int o, SortOrder sortOrder) { + Preconditions.checkNotNull(sortOrder); + checkForSufficientLength(bytes, o, Bytes.SIZEOF_LONG); + long v; + byte b = bytes[o]; + if (sortOrder == SortOrder.ASC) { + v = b ^ 0x80; // Flip sign bit back + for (int i = 1; i < Bytes.SIZEOF_LONG; i++) { + b = bytes[o + i]; + v = (v << 8) + (b & 0xff); + } + } else { + b = (byte) (b ^ 0xff); + v = b ^ 0x80; // Flip sign bit back + for (int i = 1; i < Bytes.SIZEOF_LONG; i++) { + b = bytes[o + i]; + b ^= 0xff; + v = (v << 8) + (b & 0xff); + } + } + return v; + } + + @Override + public int decodeInt(byte[] b, int o, SortOrder sortOrder) { + long v = decodeLong(b, o, sortOrder); + if (v < Integer.MIN_VALUE || v > Integer.MAX_VALUE) { + throw newIllegalDataException( + "Value " + v + " cannot be cast to Integer without changing its value"); + } + return (int) v; + } + + @Override + public int encodeFloat(float v, byte[] b, int o) { + if (v < Long.MIN_VALUE || v > Long.MAX_VALUE) { + throw newIllegalDataException( + "Value " + v + " cannot be encoded as an Long without changing its value"); + } + return encodeLong((long) v, b, o); + } + + @Override + public int encodeDouble(double v, byte[] b, int o) { + if (v < Long.MIN_VALUE || v > Long.MAX_VALUE) { + throw newIllegalDataException( + "Value " + v + " cannot be encoded as an Long without changing its value"); + } + return encodeLong((long) v, b, o); + } + + @Override + public int encodeLong(long v, byte[] b, int o) { + checkForSufficientLength(b, o, Bytes.SIZEOF_LONG); + b[o + 0] = (byte) ((v >> 56) ^ 0x80); // Flip sign bit so that INTEGER is binary comparable + b[o + 1] = (byte) (v >> 48); + b[o + 2] = (byte) (v >> 40); + b[o + 3] = (byte) (v >> 32); + b[o + 4] = (byte) (v >> 24); + b[o + 5] = (byte) (v >> 16); + b[o + 6] = (byte) (v >> 8); + b[o + 7] = (byte) v; + return Bytes.SIZEOF_LONG; + } + + @Override + public byte decodeByte(byte[] b, int o, SortOrder sortOrder) { + long v = decodeLong(b, o, sortOrder); + if (v < Byte.MIN_VALUE || v > Byte.MAX_VALUE) { + throw newIllegalDataException( + "Value " + v + " cannot be cast to Byte without changing its value"); + } + return (byte) v; + } + + @Override + public short decodeShort(byte[] b, int o, SortOrder sortOrder) { + long v = decodeLong(b, o, sortOrder); + if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) { + throw newIllegalDataException( + "Value " + v + " cannot be cast to Short without changing its value"); + } + return (short) v; + } + + @Override + public int encodeByte(byte v, byte[] b, int o) { + return encodeLong(v, b, o); + } + + @Override + public int encodeShort(short v, byte[] b, int o) { + return encodeLong(v, b, o); + } + @Override - public PhoenixArray newArray(PDataType type, Object[] elements) { - return new PhoenixArray.PrimitiveLongPhoenixArray(type, elements); + public PhoenixArrayFactory getPhoenixArrayFactory() { + return new PhoenixArrayFactory() { + @Override + public PhoenixArray newArray(PDataType type, Object[] elements) { + return new PhoenixArray.PrimitiveLongPhoenixArray(type, elements); + } + }; } - }; } - } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/aa05da8a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTime.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTime.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTime.java index 0cfb0e8..03afae9 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTime.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTime.java @@ -123,7 +123,7 @@ public class PTime extends PDataType