Skip to content

Add datetime functions #3473

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 224 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
224 commits
Select commit Hold shift + click to select a range
7f1eba4
add condition and string func
xinyual Feb 21, 2025
86f1b9c
add atan
xinyual Feb 24, 2025
7d46cbc
[WIP] map opensearch math functions to calcite implementations
yuancu Feb 24, 2025
ce264dd
add transfer for log
xinyual Feb 24, 2025
06a7b65
Merge branch 'mapToCalciteBuiltIn' into map2calcite
xinyual Feb 24, 2025
25d7d51
Merge pull request #1 from yaunchun/map2calcite
xinyual Feb 24, 2025
6cc2452
fix log and atan
xinyual Feb 24, 2025
7ff8a1c
add udf and udaf percentile and Mod
xinyual Feb 24, 2025
19e11d6
add condition udf and take agg
xinyual Feb 25, 2025
25867df
add unified test framework
xinyual Feb 25, 2025
65fd487
Merge remote-tracking branch 'origin/feature/calcite-engine' into add…
xinyual Feb 26, 2025
7274a05
fix UT/IT
xinyual Feb 27, 2025
6ccfd97
merge
xinyual Feb 27, 2025
f6120dc
fix UT/IT
xinyual Feb 27, 2025
4fa915d
remove useless code change
xinyual Feb 27, 2025
99b33cd
apply spotless
xinyual Feb 27, 2025
0b28fab
add license and move it
xinyual Feb 28, 2025
651db98
remove useless change
xinyual Feb 28, 2025
706f9b0
add time functions
xinyual Mar 3, 2025
8c0dd3b
fix date/utc_data/timestamp
xinyual Mar 3, 2025
d0f4f38
add unix_timestamp(half)
xinyual Mar 4, 2025
2f29ab7
continue to fix unixtimestamp
xinyual Mar 4, 2025
8fc4b39
fix unixtimestamp
xinyual Mar 4, 2025
6eb9204
add timestamp
xinyual Mar 13, 2025
5b75398
fix timestamp
xinyual Mar 14, 2025
61deedf
Implement DATEADD function
yuancu Mar 6, 2025
60a2807
Implement DATE_SUB function
yuancu Mar 6, 2025
85798af
WIP: Implement TIMEADD
yuancu Mar 12, 2025
f4c08cf
Implement ADDTIME
yuancu Mar 12, 2025
02be4c4
Implement DAY_OF_WEEK and DAY_OF_YEAR
yuancu Mar 12, 2025
6ca160d
Implement DATEDIFF
yuancu Mar 13, 2025
a359112
Leverage org.opensearch.sql.utils.DateTimeFormatters for datetime par…
yuancu Mar 13, 2025
0e8e5be
Make datetime utils interface
yuancu Mar 13, 2025
8338a58
Implement DATE_FORMAT (can't handle nanoseconds yet)
yuancu Mar 14, 2025
6849035
Merge pull request #4 from yuancu/addTimeFunctions
xinyual Mar 14, 2025
cbd95d6
Fix rebase
yuancu Mar 14, 2025
345de93
Fix TIME function
yuancu Mar 14, 2025
e5a347d
Merge remote-tracking branch 'xinyuan/addTimeFunctions' into addTimeF…
yuancu Mar 14, 2025
03e0726
Merge pull request #5 from yuancu/addTimeFunctions
xinyual Mar 14, 2025
b8a8667
Implement EXTRACT by reusing OS PPL
yuancu Mar 14, 2025
c78f6ca
Implement CONVERT_TZ. Cannot handle null return at the moment.
yuancu Mar 14, 2025
d8201da
merge from main
xinyual Mar 14, 2025
5f72f21
apply spotless
xinyual Mar 14, 2025
40d4caa
Merge branch 'addTimeFunctions' into cleanDateTime
yuancu Mar 14, 2025
2962942
Implement DATETIME
yuancu Mar 14, 2025
c94657c
Implement FROM_DAYS
yuancu Mar 14, 2025
6711b82
Implement GET_FORMAT
yuancu Mar 14, 2025
b8509d2
Implement MAKETIME
yuancu Mar 14, 2025
6379d34
add to days
xinyual Mar 15, 2025
c3eb8ff
Fix null returns for CONVERT_TZ and DATETIME by manually casting retu…
yuancu Mar 17, 2025
4b32722
add time functions
xinyual Mar 17, 2025
ee9f704
Implement PERIOD_ADD and PERIOD_DIFF
yuancu Mar 17, 2025
7a8674d
Implement STR_TO_DATE
yuancu Mar 17, 2025
40b166c
Add license information to datetime UDFs
yuancu Mar 17, 2025
6f3545a
Implement SUBTIME
yuancu Mar 17, 2025
272afbb
add date functions
xinyual Mar 17, 2025
ae42653
Reimplement WEEK and WEEK_OF_YEAR
yuancu Mar 17, 2025
8e04bde
Map CURRENT_TIME to SqlStdOperatorTable.CURRENT_TIME
yuancu Mar 17, 2025
8a45c36
Implement MINUTE_OF_DAY
yuancu Mar 17, 2025
9db5a08
Fix String.format locale to US for exprMakeTime
yuancu Mar 17, 2025
1d136e0
finish all datetime functions
xinyual Mar 18, 2025
f076847
Merge pull request #8 from yuancu/cleanDateTime
xinyual Mar 18, 2025
a162bb0
merge
xinyual Mar 18, 2025
e5e5124
fix implementation
xinyual Mar 18, 2025
bfff6b3
add it for time/timestamp/date
xinyual Mar 18, 2025
0ecdc06
add relative time
xinyual Mar 18, 2025
1224781
add relative
xinyual Mar 18, 2025
4c523c8
fix year bug
xinyual Mar 18, 2025
efb83bb
fix config
xinyual Mar 19, 2025
d1d2c4a
add several IT
xinyual Mar 19, 2025
7931b3d
Correct DATE_ADD and DATE_SUB implementations
yuancu Mar 18, 2025
4727402
Fix date and time fields reading
yuancu Mar 19, 2025
752b634
fix from unix timestamp
xinyual Mar 19, 2025
e7c36f3
add to_days
xinyual Mar 19, 2025
91a51ce
Add date manipulation ITs
yuancu Mar 19, 2025
b520503
Merge pull request #12 from yuancu/cleanDateTime
xinyual Mar 19, 2025
b16d8e1
Merge remote-tracking branch 'mine/cleanDateTime' into cleanDateTime
xinyual Mar 19, 2025
776e408
fix sec to time
xinyual Mar 19, 2025
d73f510
fix millisecond
xinyual Mar 20, 2025
73d2727
fix time expression
xinyual Mar 20, 2025
9b229d9
fix nullable problem
xinyual Mar 20, 2025
0cd7d58
merge from main
xinyual Mar 20, 2025
6cfe963
merge from main
xinyual Mar 20, 2025
f9073ad
Correct DATE_PART related functions (HOUR, MINUTE, etc) to correctly …
yuancu Mar 19, 2025
4724128
Implement MAKEDATE
yuancu Mar 20, 2025
725b595
Correct periodNameFunction to correctly parse datetime string and to …
yuancu Mar 20, 2025
20415db
add IT
xinyual Mar 20, 2025
1bf217c
Support QUARTER function and add ITs
songkant-aws Mar 21, 2025
b40435a
Add SECOND function ITs
songkant-aws Mar 21, 2025
f8c7501
Add SECOND_OF_MINUTE function ITs
songkant-aws Mar 21, 2025
2c2d0d3
[Calcite engine] TimeStamp UDT
qianheng-aws Mar 21, 2025
e7e3cf4
Add convert_tz ITs
songkant-aws Mar 21, 2025
3eb36b7
Minor fix of get_format function and add ITs
songkant-aws Mar 21, 2025
7eb540a
Correct DATETIME function to accept timestamp argument
yuancu Mar 21, 2025
72ca8a2
Add extract function with supported ITs
songkant-aws Mar 21, 2025
d3e05aa
Correct DATEDIFF to align with V2's behavior
yuancu Mar 23, 2025
774891b
Merge pull request #14 from songkant-aws/songkant/cleanDateTime
xinyual Mar 24, 2025
6d91bd8
Correct date part return types & Fix date format locale to English
yuancu Mar 24, 2025
ce6b691
Add date time ITs
yuancu Mar 24, 2025
ea9fc40
Add ITs for SYSDATE and TIMEDIFF
yuancu Mar 24, 2025
c72a975
Merge xinyual:cleanDateTime to cleanDateTime
yuancu Mar 24, 2025
d5aa8fd
Revert fixing locale to allow local representation of date time
yuancu Mar 24, 2025
4750729
Merge remote-tracking branch 'mine/cleanDateTime' into cleanDateTime
xinyual Mar 24, 2025
0d6995c
fix sec to time
xinyual Mar 24, 2025
0021744
Merge pull request #15 from yuancu/cleanDateTime
xinyual Mar 24, 2025
09406ef
add license
xinyual Mar 24, 2025
748e1e2
finish useless code
xinyual Mar 24, 2025
a8a924f
add IT for percentile
xinyual Mar 24, 2025
cf12ef8
rename files
xinyual Mar 24, 2025
dfa600e
fix to days
xinyual Mar 24, 2025
aad9d0e
fix
xinyual Mar 25, 2025
99489b4
apply spotless
xinyual Mar 25, 2025
98ef3ca
Merge remote-tracking branch 'refs/remotes/origin/main' into feature/…
qianheng-aws Mar 25, 2025
ec6eeed
fix null for yearweek
xinyual Mar 25, 2025
7b720bf
add null IT
xinyual Mar 25, 2025
b79b3d9
Add ITs for ADDTIME, ADDDATE, DATESUB, DATEADD, DATE
yuancu Mar 25, 2025
04064d6
Parse date / time exclusively for YEAR, QUARTER, MONTH, DAY, HOUR, MI…
yuancu Mar 25, 2025
a04f729
add IT
xinyual Mar 25, 2025
227be36
Support timestamp udt
qianheng-aws Mar 26, 2025
9a5eeb6
Merge remote-tracking branch 'refs/remotes/origin/main' into feature/…
qianheng-aws Mar 26, 2025
a4f477b
Support timestamp udt
qianheng-aws Mar 26, 2025
59b4817
Add date time null input ITs
yuancu Mar 26, 2025
c89b38b
deal invalid cases
xinyual Mar 26, 2025
86f1538
Make all udf return types nullable
yuancu Mar 26, 2025
238d375
merge
xinyual Mar 26, 2025
a9dc42b
Remove nullable argument in getReturnTypeForAddOrSubDate
yuancu Mar 26, 2025
7930930
enable nonfallback datetimes
xinyual Mar 26, 2025
dd803e0
Merge xinyual/cleanDateTime to cleanDateTime
yuancu Mar 26, 2025
609c817
Support date, time udt
qianheng-aws Mar 26, 2025
c0b0c11
Fix date time null returns & Add null ITs
yuancu Mar 26, 2025
59a7b74
Allow timestamp string where date or time string is required
yuancu Mar 26, 2025
c50dbc3
Remove redundant nullify of return types
yuancu Mar 26, 2025
886b4de
fix percentile
xinyual Mar 26, 2025
16db26e
Merge pull request #16 from yuancu/cleanDateTime
xinyual Mar 26, 2025
2d53d29
Merge remote-tracking branch 'mine/cleanDateTime' into finalCleanDate
xinyual Mar 26, 2025
ec52051
merge udt
xinyual Mar 26, 2025
9d1d666
Correct makeConversionCall
yuancu Mar 26, 2025
bd7914a
Implement TIME UDF
yuancu Mar 26, 2025
ec6d5f2
Fix bug caused by cache in RelDataTypeImpl
qianheng-aws Mar 26, 2025
c5762e1
Refine code
qianheng-aws Mar 26, 2025
c13b6de
Refine code
qianheng-aws Mar 26, 2025
b12abcf
inte with udt
xinyual Mar 27, 2025
ca97938
Merge pull request #17 from yuancu/cleanDateTime
xinyual Mar 27, 2025
b37242a
Merge remote-tracking branch 'mine/cleanDateTime' into withUDT
xinyual Mar 27, 2025
5362cfe
Ignore UT with span on calcite date
qianheng-aws Mar 27, 2025
88300e8
Fix bug
qianheng-aws Mar 27, 2025
1d88fbe
fix add sub time
xinyual Mar 27, 2025
21e54f4
Fix bug
qianheng-aws Mar 27, 2025
7ac30af
fix IT
xinyual Mar 27, 2025
4a62a4f
fix IT
xinyual Mar 27, 2025
d5a64af
fix return type for str to date
xinyual Mar 27, 2025
5bf9f17
Merge remote-tracking branch 'qh/feature/calcite-engine-udt' into wit…
xinyual Mar 27, 2025
ec643d5
fix for subtime
xinyual Mar 27, 2025
366d1d7
add postprocessing for curtimes
xinyual Mar 27, 2025
41f24af
fix all IT
xinyual Mar 27, 2025
5dfbf77
fix format bug
xinyual Mar 27, 2025
a8fcf9e
fix function properties for all utc function
xinyual Mar 27, 2025
3144c00
use fixed function properties
xinyual Mar 27, 2025
878635a
fix all IT
xinyual Mar 27, 2025
8eb5776
remove all useless code
xinyual Mar 27, 2025
e392550
apply spotless
xinyual Mar 28, 2025
67ca837
Fix date / time parsing with microseconds
yuancu Mar 28, 2025
957a6a0
Test TIMESTAMPADD and TIMESTAMPDIFF with microseconds
yuancu Mar 28, 2025
04ae1d0
remove uesless
xinyual Mar 28, 2025
2d63193
add compare
xinyual Mar 28, 2025
f7a8b83
revert change
xinyual Mar 28, 2025
d6a94f8
fix IT
xinyual Mar 28, 2025
ae23433
fix comparison bug
xinyual Mar 28, 2025
b58fce5
fix spotless
xinyual Mar 28, 2025
c03c5fb
fix IT
xinyual Mar 28, 2025
c1cdbed
fix IT
xinyual Mar 28, 2025
11839a1
merge from main
xinyual Mar 28, 2025
5b6ef9e
fix IT
xinyual Mar 28, 2025
e8d4b36
Fix testMinuteOfHourAndMinuteOfDay IT
yuancu Mar 28, 2025
563ecf4
remove useless code
xinyual Mar 28, 2025
b42b671
Merge pull request #21 from yuancu/cleanDateTime
xinyual Mar 28, 2025
0ecb578
add pushdown IT
xinyual Mar 29, 2025
c1f6e05
revert useless change
xinyual Mar 29, 2025
942eb42
format code
xinyual Mar 29, 2025
519151c
modify code
xinyual Mar 29, 2025
e73529c
remove useless
xinyual Mar 29, 2025
077141f
remove useless
xinyual Mar 29, 2025
777302f
enable IT
xinyual Mar 29, 2025
2a75227
apply spotless
xinyual Mar 29, 2025
b076969
ignore failed ut
xinyual Mar 31, 2025
d488a0c
use v2 implementation
xinyual Mar 31, 2025
4c70c95
fix implementation
xinyual Mar 31, 2025
62cb0c0
use v2 implementation for timestamp and time
xinyual Mar 31, 2025
eee5d53
implement by v2
xinyual Mar 31, 2025
6bf2e4c
fix implementation
xinyual Mar 31, 2025
b8c3dda
fix date format problem
xinyual Mar 31, 2025
4cc10f6
remove useless code
xinyual Mar 31, 2025
337c2b9
fix date add/sub
xinyual Mar 31, 2025
01a2dde
remove useless code
xinyual Mar 31, 2025
38fef3b
simplify code
xinyual Mar 31, 2025
368ac70
refactor date implementation
xinyual Apr 1, 2025
8a190cd
apply spotless
xinyual Apr 1, 2025
cf30e05
add to do
xinyual Apr 1, 2025
3e1774c
add TO DO
xinyual Apr 1, 2025
0c7d247
remove test code
xinyual Apr 1, 2025
7fd66ef
refactor code
xinyual Apr 1, 2025
19d3cc8
apply spotless
xinyual Apr 1, 2025
5e46c17
fix some bugs
xinyual Apr 1, 2025
b0eb105
fix IT
xinyual Apr 1, 2025
8607d98
ignore flaky test
xinyual Apr 1, 2025
ed105bb
reformat code to totally use v2 implementation
xinyual Apr 1, 2025
61246d8
remove useless code
xinyual Apr 1, 2025
f1d1453
remove useless code
xinyual Apr 1, 2025
8a88ef9
revert change
xinyual Apr 1, 2025
720b0e7
add copy right
xinyual Apr 1, 2025
a82dc58
change compare to local date time
xinyual Apr 2, 2025
b922857
Merge remote-tracking branch 'origin/main' into withUDT
xinyual Apr 2, 2025
3469557
change name after merge
xinyual Apr 2, 2025
e9165fd
remove useless code
xinyual Apr 2, 2025
d413bdb
fix bug
xinyual Apr 2, 2025
b80ea40
ignore flaky test
xinyual Apr 2, 2025
8ae7d16
modify IT message information
xinyual Apr 2, 2025
30941ee
Fix date / time formatting (always prefer Arabic digits instead of lo…
yuancu Apr 2, 2025
a1e20ad
Merge pull request #23 from yuancu/fix-date-format
xinyual Apr 2, 2025
c686197
apply spot
xinyual Apr 2, 2025
d510c84
Reuse PlanUtils.intervalUnitToSpanUnit
yuancu Apr 3, 2025
9d8e849
Merge pull request #24 from yuancu/fix-datetime
xinyual Apr 3, 2025
508fef8
revert useless code
xinyual Apr 3, 2025
345beca
apply spotless and revert useless change
xinyual Apr 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
import org.opensearch.sql.ast.expression.UnresolvedExpression;
import org.opensearch.sql.calcite.utils.CalciteToolsHelper;
import org.opensearch.sql.executor.QueryType;
import org.opensearch.sql.expression.function.FunctionProperties;

public class CalcitePlanContext {

public FrameworkConfig config;
public final Connection connection;
public final RelBuilder relBuilder;
public final ExtendedRexBuilder rexBuilder;
public final FunctionProperties functionProperties;
public final QueryType queryType;

@Getter @Setter private boolean isResolvingJoinCondition = false;
Expand All @@ -39,6 +41,7 @@ private CalcitePlanContext(FrameworkConfig config, QueryType queryType) {
this.connection = CalciteToolsHelper.connect(config, TYPE_FACTORY);
this.relBuilder = CalciteToolsHelper.create(config, TYPE_FACTORY, connection);
this.rexBuilder = new ExtendedRexBuilder(relBuilder.getRexBuilder());
this.functionProperties = new FunctionProperties(QueryType.PPL);
}

public RexNode resolveJoinCondition(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

import static org.opensearch.sql.ast.expression.SpanUnit.NONE;
import static org.opensearch.sql.ast.expression.SpanUnit.UNKNOWN;
import static org.opensearch.sql.calcite.utils.BuiltinFunctionUtils.translateArgument;
import static org.opensearch.sql.calcite.utils.PlanUtils.intervalUnitToSpanUnit;
import static org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils.TransferUserDefinedFunction;

import java.math.BigDecimal;
import java.util.List;
Expand All @@ -22,6 +21,7 @@
import org.apache.calcite.sql.SqlIntervalQualifier;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.type.ReturnTypes;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.util.DateString;
import org.apache.calcite.util.TimeString;
Expand Down Expand Up @@ -52,8 +52,11 @@
import org.opensearch.sql.ast.expression.subquery.InSubquery;
import org.opensearch.sql.ast.expression.subquery.ScalarSubquery;
import org.opensearch.sql.ast.tree.UnresolvedPlan;
import org.opensearch.sql.calcite.type.ExprSqlType;
import org.opensearch.sql.calcite.udf.datetimeUDF.PostprocessDateToStringFunction;
import org.opensearch.sql.calcite.utils.BuiltinFunctionUtils;
import org.opensearch.sql.calcite.utils.OpenSearchTypeFactory;
import org.opensearch.sql.calcite.utils.PlanUtils;
import org.opensearch.sql.common.utils.StringUtils;
import org.opensearch.sql.data.type.ExprType;
import org.opensearch.sql.exception.CalciteUnsupportedException;
Expand Down Expand Up @@ -122,7 +125,7 @@ public RexNode visitLiteral(Literal node, CalcitePlanContext context) {
public RexNode visitInterval(Interval node, CalcitePlanContext context) {
RexNode value = analyze(node.getValue(), context);
SqlIntervalQualifier intervalQualifier =
context.rexBuilder.createIntervalUntil(intervalUnitToSpanUnit(node.getUnit()));
context.rexBuilder.createIntervalUntil(PlanUtils.intervalUnitToSpanUnit(node.getUnit()));
return context.rexBuilder.makeIntervalLiteral(
new BigDecimal(value.toString()), intervalQualifier);
}
Expand Down Expand Up @@ -182,11 +185,40 @@ public RexNode visitIn(In node, CalcitePlanContext context) {
@Override
public RexNode visitCompare(Compare node, CalcitePlanContext context) {
SqlOperator op = BuiltinFunctionUtils.translate(node.getOperator());
final RexNode left = analyze(node.getLeft(), context);
final RexNode right = analyze(node.getRight(), context);
RexNode leftCandidate = analyze(node.getLeft(), context);
RexNode rightCandidate = analyze(node.getRight(), context);
Boolean whetherCompareByTime =
leftCandidate.getType() instanceof ExprSqlType
|| rightCandidate.getType() instanceof ExprSqlType;

final RexNode left =
transferCompareForDateRelated(leftCandidate, context, whetherCompareByTime);
final RexNode right =
transferCompareForDateRelated(rightCandidate, context, whetherCompareByTime);
return context.relBuilder.call(op, left, right);
}

private RexNode transferCompareForDateRelated(
RexNode candidate, CalcitePlanContext context, boolean whetherCompareByTime) {
if (whetherCompareByTime) {
SqlOperator postToStringNode =
TransferUserDefinedFunction(
PostprocessDateToStringFunction.class,
"PostprocessDateToString",
ReturnTypes.CHAR_FORCE_NULLABLE);
RexNode transferredStringNode =
context.rexBuilder.makeCall(
postToStringNode,
List.of(
candidate,
context.rexBuilder.makeLiteral(
context.functionProperties.getQueryStartClock().instant().toString())));
return transferredStringNode;
} else {
return candidate;
}
}

@Override
public RexNode visitBetween(Between node, CalcitePlanContext context) {
RexNode value = analyze(node.getValue(), context);
Expand Down Expand Up @@ -322,9 +354,17 @@ public RexNode visitLet(Let node, CalcitePlanContext context) {
public RexNode visitFunction(Function node, CalcitePlanContext context) {
List<RexNode> arguments =
node.getFuncArgs().stream().map(arg -> analyze(arg, context)).collect(Collectors.toList());
return context.rexBuilder.makeCall(
BuiltinFunctionUtils.translate(node.getFuncName()),
translateArgument(node.getFuncName(), arguments, context));
SqlOperator operator = BuiltinFunctionUtils.translate(node.getFuncName());
List<RexNode> translatedArguments =
BuiltinFunctionUtils.translateArgument(
node.getFuncName(),
arguments,
context,
context.functionProperties.getQueryStartClock().instant().toString());
RelDataType returnType =
BuiltinFunctionUtils.deriveReturnType(
node.getFuncName(), context.rexBuilder, operator, translatedArguments);
return context.rexBuilder.makeCall(returnType, operator, translatedArguments);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

package org.opensearch.sql.calcite.udf;

/**
* TODO. support init with constant arguments https://github.com/opensearch-project/sql/issues/3490
*/
public interface UserDefinedAggFunction<S extends UserDefinedAggFunction.Accumulator> {
/**
* @return {@link Accumulator}
Expand Down Expand Up @@ -32,6 +35,6 @@ interface Accumulator {
/**
* @return the final aggregation value
*/
Object value();
Object value(Object... args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

package org.opensearch.sql.calcite.udf;

/**
* TODO. support init with constant arguments https://github.com/opensearch-project/sql/issues/3490
*/
public interface UserDefinedFunction {
Object eval(Object... args);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.calcite.udf.datetimeUDF;

import org.opensearch.sql.calcite.udf.UserDefinedFunction;
import org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils;
import org.opensearch.sql.data.model.ExprStringValue;
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.expression.datetime.DateTimeFunctions;

public class ConvertTZFunction implements UserDefinedFunction {
@Override
public Object eval(Object... args) {

if (UserDefinedFunctionUtils.containsNull(args)) {
return null;
}

Object argTimestamp = args[0];
Object fromTz = args[1];
Object toTz = args[2];
ExprValue datetimeExpr =
DateTimeFunctions.exprConvertTZ(
new ExprStringValue(argTimestamp.toString()),
new ExprStringValue(fromTz.toString()),
new ExprStringValue(toTz.toString()));

return datetimeExpr.valueForCalcite();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.calcite.udf.datetimeUDF;

import static org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils.*;
import static org.opensearch.sql.calcite.utils.datetime.DateTimeApplyUtils.convertToTemporalAmount;
import static org.opensearch.sql.calcite.utils.datetime.DateTimeApplyUtils.transferInputToExprValue;

import org.apache.calcite.avatica.util.TimeUnit;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.sql.type.SqlReturnTypeInference;
import org.apache.calcite.sql.type.SqlTypeName;
import org.opensearch.sql.calcite.udf.UserDefinedFunction;
import org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils;
import org.opensearch.sql.data.model.ExprDateValue;
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.expression.datetime.DateTimeFunctions;
import org.opensearch.sql.expression.function.FunctionProperties;

public class DateAddSubFunction implements UserDefinedFunction {
@Override
public Object eval(Object... args) {

if (UserDefinedFunctionUtils.containsNull(args)) {
return null;
}

TimeUnit unit = (TimeUnit) args[0];
long interval = ((Number) args[1]).longValue();
Object argBase = args[2];
SqlTypeName sqlTypeName = (SqlTypeName) args[3];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why using SqlTypeName here? I think sql type is a subset of all types we use and date, time, timestamp of Sql type is no longer used by us after introducing UDT

Copy link
Contributor Author

@xinyual xinyual Apr 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For our current UDF, all time/timestamp/time input would be the UDT. So we directly transfer the type to corresponding sqltypetime that we can call fromObjectValue easily. See function transferDateRelatedTimeName

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These UDT's real SqlType is VARCHAR, the more appropriate way is pass in the RelDataType here and get the correct exprtype by using ExprUDT.getExprCoreType.

It works here because we have a incorrect mapping in convertSqlTypeNameToExprType(the mapping of time,timestamp,date will never be used since they are blocked now by the previous logic of handling UDT), and you pass in SqlTypeName.TIMESTAMP directly from the place where you call this funciton.

boolean isAdd = (Boolean) args[4];
SqlTypeName returnSqlType = (SqlTypeName) args[5];
ExprValue base = transferInputToExprValue(argBase, sqlTypeName);
FunctionProperties restored = restoreFunctionProperties(args[args.length - 1]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This properties should be set when constructing the function and I think it supports pass in FunctionProperties directly, please add a TODO here to make change in the future.

Copy link
Contributor Author

@xinyual xinyual Apr 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Add in function restoreFunctionProperties

ExprValue resultDatetime =
DateTimeFunctions.exprDateApplyInterval(
restored, base, convertToTemporalAmount(interval, unit), isAdd);
if (returnSqlType == SqlTypeName.TIMESTAMP) {
return resultDatetime.valueForCalcite();
} else {
return new ExprDateValue(resultDatetime.dateValue()).valueForCalcite();
}
}

public static SqlReturnTypeInference getReturnTypeForAddOrSubDate() {
return opBinding -> {
RelDataType operandType0 = opBinding.getOperandType(6);
SqlTypeName typeName = operandType0.getSqlTypeName();
if (typeName == SqlTypeName.TIMESTAMP) {
Copy link
Collaborator

@qianheng-aws qianheng-aws Apr 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which case will we use SqlTypeName.TIMESTAMP?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

return nullableTimestampUDT;
} else if (typeName == SqlTypeName.DATE) {
return nullableDateUDT;
}
return opBinding.getTypeFactory().createSqlType(typeName);
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.calcite.udf.datetimeUDF;

import static org.opensearch.sql.calcite.utils.OpenSearchTypeFactory.convertSqlTypeNameToExprType;
import static org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils.restoreFunctionProperties;
import static org.opensearch.sql.data.model.ExprValueUtils.fromObjectValue;

import org.apache.calcite.sql.type.SqlTypeName;
import org.opensearch.sql.calcite.udf.UserDefinedFunction;
import org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils;
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.expression.datetime.DateTimeFunctions;
import org.opensearch.sql.expression.function.FunctionProperties;

/**
* Calculates the difference of date parts of given values. If the first argument is time, today's
* date is used.
*
* <p>(DATE/TIMESTAMP/TIME, DATE/TIMESTAMP/TIME) -> LONG
*/
public class DateDiffFunction implements UserDefinedFunction {
@Override
public Object eval(Object... args) {
if (UserDefinedFunctionUtils.containsNull(args)) {
return null;
}
FunctionProperties restored = restoreFunctionProperties(args[args.length - 1]);
SqlTypeName sqlTypeName1 = (SqlTypeName) args[1];
SqlTypeName sqlTypeName2 = (SqlTypeName) args[3];
ExprValue diffResult =
DateTimeFunctions.exprDateDiff(
restored,
fromObjectValue(args[0], convertSqlTypeNameToExprType(sqlTypeName1)),
fromObjectValue(args[2], convertSqlTypeNameToExprType(sqlTypeName2)));
return diffResult.longValue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.calcite.udf.datetimeUDF;

import static org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils.restoreFunctionProperties;
import static org.opensearch.sql.calcite.utils.datetime.DateTimeApplyUtils.transferInputToExprValue;
import static org.opensearch.sql.expression.datetime.DateTimeFormatterUtil.getFormattedDate;
import static org.opensearch.sql.expression.datetime.DateTimeFormatterUtil.getFormattedDateOfToday;

import org.apache.calcite.sql.type.SqlTypeName;
import org.opensearch.sql.calcite.udf.UserDefinedFunction;
import org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils;
import org.opensearch.sql.data.model.ExprStringValue;
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.expression.function.FunctionProperties;

public class DateFormatFunction implements UserDefinedFunction {
@Override
public Object eval(Object... args) {
if (UserDefinedFunctionUtils.containsNull(args)) {
return null;
}
Object argDatetime = args[0];
Object argDatetimeType = args[1];
Object argFormat = args[2];
FunctionProperties restored = restoreFunctionProperties(args[args.length - 1]);
ExprValue candidateValue = transferInputToExprValue(argDatetime, (SqlTypeName) argDatetimeType);
if (argDatetimeType == SqlTypeName.TIME) {
return getFormattedDateOfToday(
new ExprStringValue(argFormat.toString()),
candidateValue,
restored.getQueryStartClock())
.stringValue();
}
return getFormattedDate(candidateValue, new ExprStringValue(argFormat.toString()))
.stringValue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.calcite.udf.datetimeUDF;

import static org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils.restoreFunctionProperties;
import static org.opensearch.sql.calcite.utils.datetime.DateTimeApplyUtils.transferInputToExprValue;
import static org.opensearch.sql.expression.datetime.DateTimeFunctions.exprDate;

import org.apache.calcite.sql.type.SqlTypeName;
import org.opensearch.sql.calcite.udf.UserDefinedFunction;
import org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils;
import org.opensearch.sql.data.model.ExprDateValue;
import org.opensearch.sql.data.model.ExprTimeValue;
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.expression.function.FunctionProperties;

public class DateFunction implements UserDefinedFunction {

@Override
public Object eval(Object... args) {
if (UserDefinedFunctionUtils.containsNull(args)) {
return null;
}
FunctionProperties restored = restoreFunctionProperties(args[args.length - 1]);
ExprValue candidate = transferInputToExprValue(args[0], (SqlTypeName) args[1]);
if ((SqlTypeName) args[1] == SqlTypeName.TIME) {
return new ExprDateValue(((ExprTimeValue) candidate).dateValue(restored)).valueForCalcite();
}
return exprDate(candidate).valueForCalcite();
}
}
Loading
Loading