blob: 4260954e3d71517852918d350b4cf2b45e29e680 [file] [log] [blame]
// 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.impala.analysis;
import java.util.Arrays;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.LocalDate;
import com.google.common.base.Preconditions;
import org.apache.impala.catalog.Type;
import org.apache.impala.common.AnalysisException;
import org.apache.impala.common.InternalException;
import org.apache.impala.service.FeSupport;
import org.apache.impala.thrift.TExprNode;
import org.apache.impala.thrift.TExprNodeType;
import org.apache.impala.thrift.TDateLiteral;
import org.apache.impala.thrift.TParseDateStringResult;
/**
* Represents a literal date as a string formatted as yyyy-MM-dd.
* Impala supports the same DATE literal syntax as Hive. For example: DATE '2019-02-15'.
*/
public class DateLiteral extends LiteralExpr {
// Days since 1970-01-01. Class DateValue in the backend uses the same representation.
private final int daysSinceEpoch_;
// String representation of date
private final String strDate_;
public DateLiteral(int daysSinceEpoch, String strDate) {
daysSinceEpoch_ = daysSinceEpoch;
strDate_ = strDate;
type_ = Type.DATE;
}
public DateLiteral(String strDate) throws AnalysisException {
type_ = Type.DATE;
// Parse date string.
// Accept different variations. E.g.: '2011-01-01', '2011-1-01', '2011-01-1',
// '2011-1-1'.
TParseDateStringResult result;
try {
result = FeSupport.parseDateString(strDate);
} catch (InternalException e) {
throw new AnalysisException("Error parsing date literal: " + e.getMessage(), e);
}
if (!result.valid || !result.isSetDays_since_epoch()) {
throw new AnalysisException("Invalid date literal: '" + strDate + "'");
}
daysSinceEpoch_ = result.getDays_since_epoch();
if (result.isSetCanonical_date_string()) {
strDate_ = result.getCanonical_date_string();
} else {
strDate_ = strDate;
}
}
/**
* Copy c'tor used in clone.
*/
protected DateLiteral(DateLiteral other) {
super(other);
daysSinceEpoch_ = other.daysSinceEpoch_;
strDate_ = other.strDate_;
}
@Override
public boolean localEquals(Expr that) {
return super.localEquals(that)
&& daysSinceEpoch_ == ((DateLiteral) that).daysSinceEpoch_;
}
@Override
public int hashCode() { return daysSinceEpoch_; }
@Override
public String toSqlImpl(ToSqlOptions options) {
// ANSI Date Literal format.
return "DATE '" + getStringValue() + "'";
}
@Override
public String getStringValue() { return strDate_; }
public int getValue() { return daysSinceEpoch_; }
@Override
protected void toThrift(TExprNode msg) {
msg.node_type = TExprNodeType.DATE_LITERAL;
msg.date_literal = new TDateLiteral();
msg.date_literal.setDays_since_epoch(daysSinceEpoch_);
msg.date_literal.setDate_string(strDate_);
}
@Override
protected Expr uncheckedCastTo(Type targetType) throws AnalysisException {
if (targetType.equals(type_)) {
return this;
} else {
return new CastExpr(targetType, this);
}
}
@Override
public int compareTo(LiteralExpr o) {
int ret = super.compareTo(o);
if (ret != 0) return ret;
DateLiteral other = (DateLiteral) o;
return daysSinceEpoch_ - other.daysSinceEpoch_;
}
@Override
public Expr clone() { return new DateLiteral(this); }
}