diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java index 6c1c5fb0113b..93a61e51950f 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java @@ -452,6 +452,7 @@ public final class FunctionRegistry { system.registerGenericUDF("current_schema", GenericUDFCurrentSchema.class); system.registerGenericUDF("current_catalog", GenericUDFCurrentCatalog.class); system.registerGenericUDF("current_date", GenericUDFCurrentDate.class); + system.registerGenericUDF("yesterday", GenericUDFYesterday.class); system.registerGenericUDF("current_timestamp", GenericUDFCurrentTimestamp.class); system.registerGenericUDF("current_user", GenericUDFCurrentUser.class); system.registerGenericUDF("current_groups", GenericUDFCurrentGroups.class); diff --git a/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFYesterday.java b/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFYesterday.java new file mode 100644 index 000000000000..f3e8e8501bbd --- /dev/null +++ b/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFYesterday.java @@ -0,0 +1,92 @@ +/* + * 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.hadoop.hive.ql.udf.generic; + +import org.apache.hadoop.hive.common.type.Date; +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.session.SessionState; +import org.apache.hadoop.hive.ql.udf.UDFType; +import org.apache.hadoop.hive.serde2.io.DateWritableV2; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; + +import java.time.ZonedDateTime; + +// This function is not a deterministic function, but a runtime constant. +// The return value is constant within a query but can be different between queries. +@UDFType(deterministic = false, runtimeConstant = true) +@Description(name = "yesterday", + value = "_FUNC_() - Returns yesterday's date at the start of query evaluation. The same as 'date_sub(current_date, 1)'" + + " All calls of yesterday within the same query return the same value.") +@NDV(maxNdv = 1) +public class GenericUDFYesterday extends GenericUDF { + + protected DateWritableV2 yesterday; + + + public DateWritableV2 getYesterday() { + return yesterday; + } + + public void setYesterday(DateWritableV2 yesterday) { + this.yesterday = yesterday; + } + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) + throws UDFArgumentException { + if (arguments.length != 0) { + throw new UDFArgumentLengthException( + "The function YESTERDAY does not take any arguments, but found " + + arguments.length); + } + + if (yesterday == null) { + SessionState ss = SessionState.get(); + ZonedDateTime dateTime = ss.getQueryCurrentTimestamp().atZone( + ss.getConf().getLocalTimeZone()).minusDays(1L); + Date dateVal = Date.of(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth()); + yesterday = new DateWritableV2(dateVal); + } + + return PrimitiveObjectInspectorFactory.writableDateObjectInspector; + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + return this.yesterday; + } + + @Override + public String getDisplayString(String[] children) { + return "YESTERDAY()"; + } + + @Override + public void copyToNewInstance(Object newInstance) throws UDFArgumentException { + super.copyToNewInstance(newInstance); + + GenericUDFYesterday other = (GenericUDFYesterday) newInstance; + if (this.yesterday != null) { + other.yesterday = new DateWritableV2(this.yesterday); + } + } +} diff --git a/ql/src/test/queries/clientpositive/udf_yesterday.q b/ql/src/test/queries/clientpositive/udf_yesterday.q new file mode 100644 index 000000000000..a0b5c3cbb463 --- /dev/null +++ b/ql/src/test/queries/clientpositive/udf_yesterday.q @@ -0,0 +1,50 @@ +--! qt:dataset:alltypesorc + +set hive.test.currenttimestamp =2024-01-18 01:02:03; + +-- desc +desc function yesterday; +desc function extended yesterday; + +-- query +select + yesterday() - yesterday(), + yesterday() +from alltypesorc limit 5; + +select yesterday(); + +-- as argument for various date udfs +select + to_date(yesterday()), + year(yesterday()), + month(yesterday()), + day(yesterday()), + weekofyear(yesterday()), + datediff(yesterday(), yesterday()), + to_date(date_add(yesterday(), 31)), + to_date(date_sub(yesterday(), 31)), + last_day(yesterday()), + next_day(yesterday(),'FRIDAY') +from alltypesorc limit 5; + +-- insert +drop table if exists tmp_runtimeconstant; +create temporary table tmp_runtimeconstant(d date); +insert into table tmp_runtimeconstant +select yesterday() from alltypesorc limit 5; +select + d = date_sub(current_date, 1), + d = date_add(current_date, -1), + d = date_sub(from_unixtime(unix_timestamp()), 1), + d = date_add(from_unixtime(unix_timestamp()), -1), + d = from_unixtime(unix_timestamp() - 1 * 24 * 60 * 60, 'yyyy-MM-dd'), + d = date_sub(current_timestamp, 1), + d = date_add(current_timestamp, -1) +from tmp_runtimeconstant; + +-- where +select + count(*) as cnt +from tmp_runtimeconstant +where yesterday() != d; diff --git a/ql/src/test/results/clientpositive/llap/show_functions.q.out b/ql/src/test/results/clientpositive/llap/show_functions.q.out index 9642bfbd8b0e..153398f688ea 100644 --- a/ql/src/test/results/clientpositive/llap/show_functions.q.out +++ b/ql/src/test/results/clientpositive/llap/show_functions.q.out @@ -493,6 +493,7 @@ xpath_number xpath_short xpath_string year +yesterday | ~ PREHOOK: query: EXPLAIN SHOW FUNCTIONS LIKE 'c%' @@ -1121,6 +1122,7 @@ xpath_number xpath_short xpath_string year +yesterday | ~ PREHOOK: query: EXPLAIN SHOW FUNCTIONS LIKE 'When' diff --git a/ql/src/test/results/clientpositive/udf_yesterday.q.out b/ql/src/test/results/clientpositive/udf_yesterday.q.out new file mode 100644 index 000000000000..3ce1a98278eb --- /dev/null +++ b/ql/src/test/results/clientpositive/udf_yesterday.q.out @@ -0,0 +1,150 @@ +PREHOOK: query: desc function yesterday +PREHOOK: type: DESCFUNCTION +POSTHOOK: query: desc function yesterday +POSTHOOK: type: DESCFUNCTION +yesterday() - Returns yesterday's date at the start of query evaluation. The same as 'date_sub(current_date, 1)' All calls of yesterday within the same query return the same value. +PREHOOK: query: desc function extended yesterday +PREHOOK: type: DESCFUNCTION +POSTHOOK: query: desc function extended yesterday +POSTHOOK: type: DESCFUNCTION +yesterday() - Returns yesterday's date at the start of query evaluation. The same as 'date_sub(current_date, 1)' All calls of yesterday within the same query return the same value. +Function class:org.apache.hadoop.hive.ql.udf.generic.GenericUDFYesterday +Function type:BUILTIN +PREHOOK: query: select + yesterday() - yesterday(), + yesterday() +from alltypesorc limit 5 +PREHOOK: type: QUERY +PREHOOK: Input: default@alltypesorc +#### A masked pattern was here #### +POSTHOOK: query: select + yesterday() - yesterday(), + yesterday() +from alltypesorc limit 5 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@alltypesorc +#### A masked pattern was here #### +0 00:00:00.000000000 2024-01-17 +0 00:00:00.000000000 2024-01-17 +0 00:00:00.000000000 2024-01-17 +0 00:00:00.000000000 2024-01-17 +0 00:00:00.000000000 2024-01-17 +PREHOOK: query: select yesterday() +PREHOOK: type: QUERY +PREHOOK: Input: _dummy_database@_dummy_table +#### A masked pattern was here #### +POSTHOOK: query: select yesterday() +POSTHOOK: type: QUERY +POSTHOOK: Input: _dummy_database@_dummy_table +#### A masked pattern was here #### +2024-01-17 +PREHOOK: query: select + to_date(yesterday()), + year(yesterday()), + month(yesterday()), + day(yesterday()), + weekofyear(yesterday()), + datediff(yesterday(), yesterday()), + to_date(date_add(yesterday(), 31)), + to_date(date_sub(yesterday(), 31)), + last_day(yesterday()), + next_day(yesterday(),'FRIDAY') +from alltypesorc limit 5 +PREHOOK: type: QUERY +PREHOOK: Input: default@alltypesorc +#### A masked pattern was here #### +POSTHOOK: query: select + to_date(yesterday()), + year(yesterday()), + month(yesterday()), + day(yesterday()), + weekofyear(yesterday()), + datediff(yesterday(), yesterday()), + to_date(date_add(yesterday(), 31)), + to_date(date_sub(yesterday(), 31)), + last_day(yesterday()), + next_day(yesterday(),'FRIDAY') +from alltypesorc limit 5 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@alltypesorc +#### A masked pattern was here #### +2024-01-17 2024 1 17 3 0 2024-02-17 2023-12-17 2024-01-31 2024-01-19 +2024-01-17 2024 1 17 3 0 2024-02-17 2023-12-17 2024-01-31 2024-01-19 +2024-01-17 2024 1 17 3 0 2024-02-17 2023-12-17 2024-01-31 2024-01-19 +2024-01-17 2024 1 17 3 0 2024-02-17 2023-12-17 2024-01-31 2024-01-19 +2024-01-17 2024 1 17 3 0 2024-02-17 2023-12-17 2024-01-31 2024-01-19 +PREHOOK: query: drop table if exists tmp_runtimeconstant +PREHOOK: type: DROPTABLE +PREHOOK: Output: database:default +POSTHOOK: query: drop table if exists tmp_runtimeconstant +POSTHOOK: type: DROPTABLE +POSTHOOK: Output: database:default +PREHOOK: query: create temporary table tmp_runtimeconstant(d date) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@tmp_runtimeconstant +POSTHOOK: query: create temporary table tmp_runtimeconstant(d date) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@tmp_runtimeconstant +PREHOOK: query: insert into table tmp_runtimeconstant +select yesterday() from alltypesorc limit 5 +PREHOOK: type: QUERY +PREHOOK: Input: default@alltypesorc +PREHOOK: Output: default@tmp_runtimeconstant +POSTHOOK: query: insert into table tmp_runtimeconstant +select yesterday() from alltypesorc limit 5 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@alltypesorc +POSTHOOK: Output: default@tmp_runtimeconstant +POSTHOOK: Lineage: tmp_runtimeconstant.d SIMPLE [] +unix_timestamp(void) is deprecated. Use current_timestamp instead. +unix_timestamp(void) is deprecated. Use current_timestamp instead. +unix_timestamp(void) is deprecated. Use current_timestamp instead. +unix_timestamp(void) is deprecated. Use current_timestamp instead. +unix_timestamp(void) is deprecated. Use current_timestamp instead. +unix_timestamp(void) is deprecated. Use current_timestamp instead. +PREHOOK: query: select + d = date_sub(current_date, 1), + d = date_add(current_date, -1), + d = date_sub(from_unixtime(unix_timestamp()), 1), + d = date_add(from_unixtime(unix_timestamp()), -1), + d = from_unixtime(unix_timestamp() - 1 * 24 * 60 * 60, 'yyyy-MM-dd'), + d = date_sub(current_timestamp, 1), + d = date_add(current_timestamp, -1) +from tmp_runtimeconstant +PREHOOK: type: QUERY +PREHOOK: Input: default@tmp_runtimeconstant +#### A masked pattern was here #### +POSTHOOK: query: select + d = date_sub(current_date, 1), + d = date_add(current_date, -1), + d = date_sub(from_unixtime(unix_timestamp()), 1), + d = date_add(from_unixtime(unix_timestamp()), -1), + d = from_unixtime(unix_timestamp() - 1 * 24 * 60 * 60, 'yyyy-MM-dd'), + d = date_sub(current_timestamp, 1), + d = date_add(current_timestamp, -1) +from tmp_runtimeconstant +POSTHOOK: type: QUERY +POSTHOOK: Input: default@tmp_runtimeconstant +#### A masked pattern was here #### +true true true true true true true +true true true true true true true +true true true true true true true +true true true true true true true +true true true true true true true +PREHOOK: query: select + count(*) as cnt +from tmp_runtimeconstant +where yesterday() != d +PREHOOK: type: QUERY +PREHOOK: Input: default@tmp_runtimeconstant +#### A masked pattern was here #### +POSTHOOK: query: select + count(*) as cnt +from tmp_runtimeconstant +where yesterday() != d +POSTHOOK: type: QUERY +POSTHOOK: Input: default@tmp_runtimeconstant +#### A masked pattern was here #### +0