Skip to content

Commit c4c16cd

Browse files
Merge remote-tracking branch 'upstream/main' into integ-cleanupcode
Signed-off-by: Yury-Fridlyand <[email protected]>
2 parents 7cda2e4 + de40f42 commit c4c16cd

File tree

17 files changed

+554
-81
lines changed

17 files changed

+554
-81
lines changed

.github/workflows/add-untriaged.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: Apply 'untriaged' label during issue lifecycle
2+
3+
on:
4+
issues:
5+
types: [opened, reopened, transferred]
6+
7+
jobs:
8+
apply-label:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/github-script@v6
12+
with:
13+
script: |
14+
github.rest.issues.addLabels({
15+
issue_number: context.issue.number,
16+
owner: context.repo.owner,
17+
repo: context.repo.repo,
18+
labels: ['untriaged']
19+
})

core/src/main/java/org/opensearch/sql/expression/DSL.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,10 @@ public static FunctionExpression from_days(Expression... expressions) {
349349
return compile(FunctionProperties.None, BuiltinFunctionName.FROM_DAYS, expressions);
350350
}
351351

352+
public static FunctionExpression get_format(Expression... expressions) {
353+
return compile(FunctionProperties.None, BuiltinFunctionName.GET_FORMAT, expressions);
354+
}
355+
352356
public static FunctionExpression hour(Expression... expressions) {
353357
return compile(FunctionProperties.None, BuiltinFunctionName.HOUR, expressions);
354358
}
@@ -407,7 +411,12 @@ public static FunctionExpression time_to_sec(Expression... expressions) {
407411
}
408412

409413
public static FunctionExpression timestamp(Expression... expressions) {
410-
return compile(FunctionProperties.None, BuiltinFunctionName.TIMESTAMP, expressions);
414+
return timestamp(FunctionProperties.None, expressions);
415+
}
416+
417+
public static FunctionExpression timestamp(FunctionProperties functionProperties,
418+
Expression... expressions) {
419+
return compile(functionProperties, BuiltinFunctionName.TIMESTAMP, expressions);
411420
}
412421

413422
public static FunctionExpression date_format(Expression... expressions) {

core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import static org.opensearch.sql.utils.DateTimeUtils.extractDate;
3636
import static org.opensearch.sql.utils.DateTimeUtils.extractDateTime;
3737

38+
import com.google.common.collect.ImmutableTable;
39+
import com.google.common.collect.Table;
3840
import java.math.BigDecimal;
3941
import java.math.RoundingMode;
4042
import java.text.DecimalFormat;
@@ -102,6 +104,16 @@ public class DateTimeFunction {
102104
// Mode used for week/week_of_year function by default when no argument is provided
103105
private static final ExprIntegerValue DEFAULT_WEEK_OF_YEAR_MODE = new ExprIntegerValue(0);
104106

107+
// Map used to determine format output for the get_format function
108+
private static final Table<String, String, String> formats =
109+
ImmutableTable.<String, String, String>builder()
110+
//TODO: Add support for other formats
111+
.put("date", "usa", "%m.%d.%Y")
112+
.put("time", "usa", "%h:%i:%s %p")
113+
.put("datetime", "usa", "%Y-%m-%d %H.%i.%s")
114+
.put("timestamp", "usa", "%Y-%m-%d %H.%i.%s")
115+
.build();
116+
105117
/**
106118
* Register Date and Time Functions.
107119
*
@@ -132,6 +144,7 @@ public void register(BuiltinFunctionRepository repository) {
132144
repository.register(dayOfYear(BuiltinFunctionName.DAY_OF_YEAR));
133145
repository.register(from_days());
134146
repository.register(from_unixtime());
147+
repository.register(get_format());
135148
repository.register(hour(BuiltinFunctionName.HOUR));
136149
repository.register(hour(BuiltinFunctionName.HOUR_OF_DAY));
137150
repository.register(localtime());
@@ -519,6 +532,12 @@ private FunctionResolver from_unixtime() {
519532
STRING, DOUBLE, STRING));
520533
}
521534

535+
private DefaultFunctionResolver get_format() {
536+
return define(BuiltinFunctionName.GET_FORMAT.getName(),
537+
impl(nullMissingHandling(DateTimeFunction::exprGetFormat), STRING, STRING, STRING)
538+
);
539+
}
540+
522541
/**
523542
* HOUR(STRING/TIME/DATETIME/DATE/TIMESTAMP). return the hour value for time.
524543
*/
@@ -752,15 +771,19 @@ private DefaultFunctionResolver time_to_sec() {
752771

753772
/**
754773
* Extracts the timestamp of a date and time value.
755-
* Also to construct a date type. The supported signatures:
756-
* STRING/DATE/DATETIME/TIMESTAMP -> DATE
774+
* Input strings may contain a timestamp only in format 'yyyy-MM-dd HH:mm:ss[.SSSSSSSSS]'
775+
* STRING/DATE/TIME/DATETIME/TIMESTAMP -> TIMESTAMP
776+
* STRING/DATE/TIME/DATETIME/TIMESTAMP, STRING/DATE/TIME/DATETIME/TIMESTAMP -> TIMESTAMP
777+
* All types are converted to TIMESTAMP actually before the function call - it is responsibility
778+
* of the automatic cast mechanism defined in `ExprCoreType` and performed by `TypeCastOperator`.
757779
*/
758780
private DefaultFunctionResolver timestamp() {
759781
return define(BuiltinFunctionName.TIMESTAMP.getName(),
760-
impl(nullMissingHandling(DateTimeFunction::exprTimestamp), TIMESTAMP, STRING),
761-
impl(nullMissingHandling(DateTimeFunction::exprTimestamp), TIMESTAMP, DATE),
762-
impl(nullMissingHandling(DateTimeFunction::exprTimestamp), TIMESTAMP, DATETIME),
763-
impl(nullMissingHandling(DateTimeFunction::exprTimestamp), TIMESTAMP, TIMESTAMP));
782+
impl(nullMissingHandling(v -> v), TIMESTAMP, TIMESTAMP),
783+
// We can use FunctionProperties.None, because it is not used. It is required to convert
784+
// TIME to other datetime types, but arguments there are already converted.
785+
impl(nullMissingHandling((v1, v2) -> exprAddTime(FunctionProperties.None, v1, v2)),
786+
TIMESTAMP, TIMESTAMP, TIMESTAMP));
764787
}
765788

766789
/**
@@ -1188,6 +1211,23 @@ private ExprValue exprFromUnixTimeFormat(ExprValue time, ExprValue format) {
11881211
return DateTimeFormatterUtil.getFormattedDate(value, format);
11891212
}
11901213

1214+
/**
1215+
* get_format implementation for ExprValue.
1216+
*
1217+
* @param type ExprValue of the type.
1218+
* @param format ExprValue of Time/String type
1219+
* @return ExprValue..
1220+
*/
1221+
private ExprValue exprGetFormat(ExprValue type, ExprValue format) {
1222+
if (formats.contains(type.stringValue().toLowerCase(), format.stringValue().toLowerCase())) {
1223+
return new ExprStringValue(formats.get(
1224+
type.stringValue().toLowerCase(),
1225+
format.stringValue().toLowerCase()));
1226+
}
1227+
1228+
return ExprNullValue.of();
1229+
}
1230+
11911231
/**
11921232
* Hour implementation for ExprValue.
11931233
*
@@ -1439,20 +1479,6 @@ private ExprValue exprTimeDiff(ExprValue first, ExprValue second) {
14391479
Duration.between(second.timeValue(), first.timeValue())));
14401480
}
14411481

1442-
/**
1443-
* Timestamp implementation for ExprValue.
1444-
*
1445-
* @param exprValue ExprValue of Timestamp type or String type.
1446-
* @return ExprValue.
1447-
*/
1448-
private ExprValue exprTimestamp(ExprValue exprValue) {
1449-
if (exprValue instanceof ExprStringValue) {
1450-
return new ExprTimestampValue(exprValue.stringValue());
1451-
} else {
1452-
return new ExprTimestampValue(exprValue.timestampValue());
1453-
}
1454-
}
1455-
14561482
/**
14571483
* Time To Sec implementation for ExprValue.
14581484
*

core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public enum BuiltinFunctionName {
7777
DAY_OF_YEAR(FunctionName.of("day_of_year")),
7878
FROM_DAYS(FunctionName.of("from_days")),
7979
FROM_UNIXTIME(FunctionName.of("from_unixtime")),
80+
GET_FORMAT(FunctionName.of("get_format")),
8081
HOUR(FunctionName.of("hour")),
8182
HOUR_OF_DAY(FunctionName.of("hour_of_day")),
8283
MAKEDATE(FunctionName.of("makedate")),

core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ private static DefaultFunctionResolver floor() {
226226
*/
227227
private static DefaultFunctionResolver ln() {
228228
return baseMathFunction(BuiltinFunctionName.LN.getName(),
229-
v -> new ExprDoubleValue(Math.log(v.doubleValue())), DOUBLE);
229+
v -> v.doubleValue() <= 0 ? ExprNullValue.of() :
230+
new ExprDoubleValue(Math.log(v.doubleValue())), DOUBLE);
230231
}
231232

232233
/**
@@ -240,15 +241,16 @@ private static DefaultFunctionResolver log() {
240241

241242
// build unary log(x), SHORT/INTEGER/LONG/FLOAT/DOUBLE -> DOUBLE
242243
for (ExprType type : ExprCoreType.numberTypes()) {
243-
builder.add(impl(nullMissingHandling(v -> new ExprDoubleValue(Math.log(v.doubleValue()))),
244-
DOUBLE, type));
244+
builder.add(impl(nullMissingHandling(v -> v.doubleValue() <= 0 ? ExprNullValue.of() :
245+
new ExprDoubleValue(Math.log(v.doubleValue()))), DOUBLE, type));
245246
}
246247

247248
// build binary function log(b, x)
248249
for (ExprType baseType : ExprCoreType.numberTypes()) {
249250
for (ExprType numberType : ExprCoreType.numberTypes()) {
250-
builder.add(impl(nullMissingHandling((b, x) -> new ExprDoubleValue(
251-
Math.log(x.doubleValue()) / Math.log(b.doubleValue()))),
251+
builder.add(impl(nullMissingHandling((b, x) -> b.doubleValue() <= 0 || x.doubleValue() <= 0
252+
? ExprNullValue.of()
253+
: new ExprDoubleValue(Math.log(x.doubleValue()) / Math.log(b.doubleValue()))),
252254
DOUBLE, baseType, numberType));
253255
}
254256
}
@@ -262,7 +264,8 @@ private static DefaultFunctionResolver log() {
262264
*/
263265
private static DefaultFunctionResolver log10() {
264266
return baseMathFunction(BuiltinFunctionName.LOG10.getName(),
265-
v -> new ExprDoubleValue(Math.log10(v.doubleValue())), DOUBLE);
267+
v -> v.doubleValue() <= 0 ? ExprNullValue.of() :
268+
new ExprDoubleValue(Math.log10(v.doubleValue())), DOUBLE);
266269
}
267270

268271
/**
@@ -271,7 +274,8 @@ private static DefaultFunctionResolver log10() {
271274
*/
272275
private static DefaultFunctionResolver log2() {
273276
return baseMathFunction(BuiltinFunctionName.LOG2.getName(),
274-
v -> new ExprDoubleValue(Math.log(v.doubleValue()) / Math.log(2)), DOUBLE);
277+
v -> v.doubleValue() <= 0 ? ExprNullValue.of() :
278+
new ExprDoubleValue(Math.log(v.doubleValue()) / Math.log(2)), DOUBLE);
275279
}
276280

277281
/**

core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import org.opensearch.sql.data.model.ExprDateValue;
3636
import org.opensearch.sql.data.model.ExprDatetimeValue;
3737
import org.opensearch.sql.data.model.ExprLongValue;
38+
import org.opensearch.sql.data.model.ExprNullValue;
39+
import org.opensearch.sql.data.model.ExprStringValue;
3840
import org.opensearch.sql.data.model.ExprTimeValue;
3941
import org.opensearch.sql.data.model.ExprTimestampValue;
4042
import org.opensearch.sql.data.model.ExprValue;
@@ -564,6 +566,42 @@ public void from_days() {
564566
assertEquals(new ExprDateValue("2000-07-03"), expression.valueOf());
565567
}
566568

569+
private static Stream<Arguments> getTestDataForGetFormat() {
570+
return Stream.of(
571+
Arguments.of("DATE", "USA", "%m.%d.%Y"),
572+
Arguments.of("DATETIME", "USA", "%Y-%m-%d %H.%i.%s"),
573+
Arguments.of("TIMESTAMP", "USA", "%Y-%m-%d %H.%i.%s"),
574+
Arguments.of("TIME", "USA", "%h:%i:%s %p")
575+
);
576+
}
577+
578+
private void getFormatQuery(LiteralExpression argType,
579+
LiteralExpression namedFormat,
580+
String expectedResult) {
581+
FunctionExpression expr = DSL.get_format(argType, namedFormat);
582+
assertEquals(STRING, expr.type());
583+
assertEquals(expectedResult, eval(expr).stringValue());
584+
}
585+
586+
@ParameterizedTest(name = "{0}{1}")
587+
@MethodSource("getTestDataForGetFormat")
588+
public void testGetFormat(String arg,
589+
String format,
590+
String expectedResult) {
591+
getFormatQuery(
592+
DSL.literal(arg),
593+
DSL.literal(new ExprStringValue(format)),
594+
expectedResult);
595+
}
596+
597+
@Test
598+
public void testGetFormatInvalidFormat() {
599+
FunctionExpression expr = DSL.get_format(
600+
DSL.literal("DATE"),
601+
DSL.literal("1SA"));
602+
assertEquals(ExprNullValue.of(), eval(expr));
603+
}
604+
567605
@Test
568606
public void hour() {
569607
FunctionExpression expression = DSL.hour(DSL.literal(new ExprTimeValue("01:02:03")));
@@ -1127,19 +1165,6 @@ public void time() {
11271165
assertEquals(new ExprTimeValue("00:00:00"), expr.valueOf());
11281166
}
11291167

1130-
@Test
1131-
public void timestamp() {
1132-
FunctionExpression expr = DSL.timestamp(DSL.literal("2020-08-17 01:01:01"));
1133-
assertEquals(TIMESTAMP, expr.type());
1134-
assertEquals(new ExprTimestampValue("2020-08-17 01:01:01"), expr.valueOf());
1135-
assertEquals("timestamp(\"2020-08-17 01:01:01\")", expr.toString());
1136-
1137-
expr = DSL.timestamp(DSL.literal(new ExprTimestampValue("2020-08-17 01:01:01")));
1138-
assertEquals(TIMESTAMP, expr.type());
1139-
assertEquals(new ExprTimestampValue("2020-08-17 01:01:01"), expr.valueOf());
1140-
assertEquals("timestamp(TIMESTAMP '2020-08-17 01:01:01')", expr.toString());
1141-
}
1142-
11431168
private void weekQuery(String date, int mode, int expectedResult) {
11441169
FunctionExpression expression = DSL
11451170
.week(functionProperties, DSL.literal(new ExprDateValue(date)), DSL.literal(mode));

0 commit comments

Comments
 (0)