Skip to content

Commit

Permalink
Drill-specific changes: added a general class for Date/Time/Timestamp…
Browse files Browse the repository at this point in the history
… literals (TimestampString, DateString, TimeString) to avoid class cast exceptions.

In case of "date + interval" situation, for example:

where
  o.o_orderdate >= date '1996-10-01'
  and o.o_orderdate < date '1996-10-01' + interval '3' month

Drill will cast DATE to TIMESTAMP and we can face with ClassCastException like "ClassCastException: org.apache.calcite.util.DateString cannot be cast to org.apache.calcite.util.TimestampString" when Calcite will compare DATE ('1996-10-01') with TIMESTAMP ('1996-10-01' + interval '3'). To avoid this situation added a general class for Date/Time/Timestamp literals to make them comparable to each other.

Also added comparing NlsString with Date/Time/Timestamp strings to avoid ClassCastExceptoin in queries like:

WHERE birth_date BETWEEN '1920-01-01' AND cast('1931-01-01' AS DATE)

In this case, '1920-01-01' is NlsString and we got ClassCastExceptoin when we tried to compare it with Date '1931-01-01'.

(cherry picked from commit afd4fc6)

(cherry picked from commit 6e793d4)
  • Loading branch information
KulykRoman authored and ihuzenko committed Dec 24, 2019
1 parent b912229 commit 029d02d
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 30 deletions.
38 changes: 38 additions & 0 deletions core/src/main/java/org/apache/calcite/util/AbstractDateTime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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.calcite.util;

/**
* General class for Date/Time/Timestamp literals (TimestampString, DateString, TimeString)
* to make them comparable to each other
*/
public abstract class AbstractDateTime implements Comparable {
protected final String v;

public AbstractDateTime(String v) {
this.v = v;
}

@Override public int compareTo(Object o) {
if (o instanceof NlsString) {
return v.compareTo(((NlsString) o).getValue());
}
return v.compareTo(((AbstractDateTime) o).v);
}
}

// End AbstractDateTime.java
11 changes: 2 additions & 9 deletions core/src/main/java/org/apache/calcite/util/DateString.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,19 @@

import java.util.Calendar;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;

/**
* Date literal.
*
* <p>Immutable, internally represented as a string (in ISO format).
*/
public class DateString implements Comparable<DateString> {
public class DateString extends AbstractDateTime {
private static final Pattern PATTERN =
Pattern.compile("[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]");

final String v;

/** Internal constructor, no validation. */
private DateString(String v, @SuppressWarnings("unused") boolean ignore) {
this.v = v;
super(v);
}

/** Creates a DateString. */
Expand Down Expand Up @@ -86,10 +83,6 @@ private static String ymd(int year, int month, int day) {
return v.hashCode();
}

@Override public int compareTo(@Nonnull DateString o) {
return v.compareTo(o.v);
}

/** Creates a DateString from a Calendar. */
public static DateString fromCalendarFields(Calendar calendar) {
return new DateString(calendar.get(Calendar.YEAR),
Expand Down
9 changes: 6 additions & 3 deletions core/src/main/java/org/apache/calcite/util/NlsString.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
* A string, optionally with {@link Charset character set} and
* {@link SqlCollation}. It is immutable.
*/
public class NlsString implements Comparable<NlsString>, Cloneable {
public class NlsString implements Comparable, Cloneable {
//~ Instance fields --------------------------------------------------------

private static final LoadingCache<Pair<ByteString, Charset>, String>
Expand Down Expand Up @@ -170,10 +170,13 @@ public boolean equals(Object obj) {
&& Objects.equals(collation, ((NlsString) obj).collation);
}

@Override public int compareTo(NlsString other) {
// implement Comparable
public int compareTo(Object other) {
// TODO jvs 18-Jan-2006: Actual collation support. This just uses
// the default collation.
return getValue().compareTo(other.getValue());
return other instanceof AbstractDateTime
? getValue().compareTo(((AbstractDateTime) other).v)
: getValue().compareTo(((NlsString) other).getValue());
}

public String getCharsetName() {
Expand Down
11 changes: 2 additions & 9 deletions core/src/main/java/org/apache/calcite/util/TimeString.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,20 @@

import java.util.Calendar;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;

/**
* Time literal.
*
* <p>Immutable, internally represented as a string (in ISO format),
* and can support unlimited precision (milliseconds, nanoseconds).
*/
public class TimeString implements Comparable<TimeString> {
public class TimeString extends AbstractDateTime {
private static final Pattern PATTERN =
Pattern.compile("[0-9][0-9]:[0-9][0-9]:[0-9][0-9](\\.[0-9]*[1-9])?");

final String v;

/** Internal constructor, no validation. */
private TimeString(String v, @SuppressWarnings("unused") boolean ignore) {
this.v = v;
super(v);
}

/** Creates a TimeString. */
Expand Down Expand Up @@ -129,10 +126,6 @@ public TimeString withFraction(String fraction) {
return v.hashCode();
}

@Override public int compareTo(@Nonnull TimeString o) {
return v.compareTo(o.v);
}

/** Creates a TimeString from a Calendar. */
public static TimeString fromCalendarFields(Calendar calendar) {
return new TimeString(
Expand Down
12 changes: 3 additions & 9 deletions core/src/main/java/org/apache/calcite/util/TimestampString.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,22 @@
* <p>Immutable, internally represented as a string (in ISO format),
* and can support unlimited precision (milliseconds, nanoseconds).
*/
public class TimestampString implements Comparable<TimestampString> {
public class TimestampString extends AbstractDateTime {
private static final Pattern PATTERN =
Pattern.compile("[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]"
+ " "
+ "[0-9][0-9]:[0-9][0-9]:[0-9][0-9](\\.[0-9]*[1-9])?");

final String v;

/** Creates a TimeString. */
public TimestampString(String v) {
this.v = v;
super(v);
Preconditions.checkArgument(PATTERN.matcher(v).matches(), v);
}

/** Creates a TimestampString for year, month, day, hour, minute, second,
* millisecond values. */
public TimestampString(int year, int month, int day, int h, int m, int s) {
this(DateTimeStringUtils.ymdhms(new StringBuilder(), year, month, day, h, m, s).toString());
super(DateTimeStringUtils.ymdhms(new StringBuilder(), year, month, day, h, m, s).toString());
}

/** Sets the fraction field of a {@code TimestampString} to a given number
Expand Down Expand Up @@ -109,10 +107,6 @@ public TimestampString withFraction(String fraction) {
return v.hashCode();
}

@Override public int compareTo(TimestampString o) {
return v.compareTo(o.v);
}

/** Creates a TimestampString from a Calendar. */
public static TimestampString fromCalendarFields(Calendar calendar) {
return new TimestampString(
Expand Down

0 comments on commit 029d02d

Please sign in to comment.