Skip to content

Commit c086dad

Browse files
More fixes for god of fixes.
Signed-off-by: Yury-Fridlyand <[email protected]>
1 parent 6d214a5 commit c086dad

File tree

3 files changed

+52
-36
lines changed

3 files changed

+52
-36
lines changed

opensearch/src/main/java/org/opensearch/sql/opensearch/data/type/OpenSearchDateType.java

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,11 @@ public class OpenSearchDateType extends OpenSearchDataType {
137137
private static final String CUSTOM_FORMAT_DATE_SYMBOLS = "FecEWwYqQgdMLDyuG";
138138

139139
@EqualsAndHashCode.Exclude
140-
String formatString;
140+
private final List<String> formats;
141141

142142
private OpenSearchDateType() {
143143
super(MappingType.Date);
144-
this.formatString = "";
144+
this.formats = List.of();
145145
}
146146

147147
private OpenSearchDateType(ExprCoreType exprCoreType) {
@@ -156,16 +156,20 @@ private OpenSearchDateType(ExprType exprType) {
156156

157157
private OpenSearchDateType(String format) {
158158
super(MappingType.Date);
159-
this.formatString = format;
159+
this.formats = getFormatList(format);
160160
this.exprCoreType = getExprTypeFromFormatString(format);
161161
}
162162

163+
public boolean hasFormats() {
164+
return !formats.isEmpty();
165+
}
166+
163167
/**
164168
* Retrieves and splits a user defined format string from the mapping into a list of formats.
165169
* @return A list of format names and user defined formats.
166170
*/
167-
private List<String> getFormatList() {
168-
String format = strip8Prefix(formatString);
171+
private List<String> getFormatList(String format) {
172+
format = strip8Prefix(format);
169173
return splitCombinedPatterns(format).stream().map(String::trim).collect(Collectors.toList());
170174
}
171175

@@ -174,7 +178,7 @@ private List<String> getFormatList() {
174178
* @return a list of DateFormatters that can be used to parse a Date/Time/Timestamp.
175179
*/
176180
public List<DateFormatter> getAllNamedFormatters() {
177-
return getFormatList().stream()
181+
return formats.stream()
178182
.filter(formatString -> FormatNames.forName(formatString) != null)
179183
.map(DateFormatter::forPattern).collect(Collectors.toList());
180184
}
@@ -184,7 +188,7 @@ public List<DateFormatter> getAllNamedFormatters() {
184188
* @return a list of DateFormatters that can be used to parse a Date.
185189
*/
186190
public List<DateFormatter> getNumericNamedFormatters() {
187-
return getFormatList().stream()
191+
return formats.stream()
188192
.filter(formatString -> {
189193
FormatNames namedFormat = FormatNames.forName(formatString);
190194
return namedFormat != null && SUPPORTED_NAMED_NUMERIC_FORMATS.contains(namedFormat);
@@ -197,7 +201,7 @@ public List<DateFormatter> getNumericNamedFormatters() {
197201
* @return a list of formats as strings that can be used to parse a Date/Time/Timestamp.
198202
*/
199203
public List<String> getAllCustomFormats() {
200-
return getFormatList().stream()
204+
return formats.stream()
201205
.filter(format -> FormatNames.forName(format) == null)
202206
.map(format -> {
203207
try {
@@ -217,17 +221,8 @@ public List<String> getAllCustomFormats() {
217221
* @return a list of DateFormatters that can be used to parse a Date/Time/Timestamp.
218222
*/
219223
public List<DateFormatter> getAllCustomFormatters() {
220-
return getFormatList().stream()
221-
.filter(format -> FormatNames.forName(format) == null)
222-
.map(format -> {
223-
try {
224-
return DateFormatter.forPattern(format);
225-
} catch (Exception ignored) {
226-
// parsing failed
227-
return null;
228-
}
229-
})
230-
.filter(Objects::nonNull)
224+
return getAllCustomFormats().stream()
225+
.map(DateFormatter::forPattern)
231226
.collect(Collectors.toList());
232227
}
233228

@@ -236,7 +231,7 @@ public List<DateFormatter> getAllCustomFormatters() {
236231
* @return a list of DateFormatters that can be used to parse a Date.
237232
*/
238233
public List<DateFormatter> getDateNamedFormatters() {
239-
return getFormatList().stream()
234+
return formats.stream()
240235
.filter(formatString -> {
241236
FormatNames namedFormat = FormatNames.forName(formatString);
242237
return namedFormat != null && SUPPORTED_NAMED_DATE_FORMATS.contains(namedFormat);
@@ -249,7 +244,7 @@ public List<DateFormatter> getDateNamedFormatters() {
249244
* @return a list of DateFormatters that can be used to parse a Time.
250245
*/
251246
public List<DateFormatter> getTimeNamedFormatters() {
252-
return getFormatList().stream()
247+
return formats.stream()
253248
.filter(formatString -> {
254249
FormatNames namedFormat = FormatNames.forName(formatString);
255250
return namedFormat != null && SUPPORTED_NAMED_TIME_FORMATS.contains(namedFormat);
@@ -262,7 +257,7 @@ public List<DateFormatter> getTimeNamedFormatters() {
262257
* @return a list of DateFormatters that can be used to parse a DateTime.
263258
*/
264259
public List<DateFormatter> getDateTimeNamedFormatters() {
265-
return getFormatList().stream()
260+
return formats.stream()
266261
.filter(formatString -> {
267262
FormatNames namedFormat = FormatNames.forName(formatString);
268263
return namedFormat != null && SUPPORTED_NAMED_DATETIME_FORMATS.contains(namedFormat);
@@ -274,17 +269,17 @@ private ExprCoreType getExprTypeFromCustomFormats(List<String> formats) {
274269
boolean isDate = false;
275270
boolean isTime = false;
276271

277-
for (var format : formats) {
272+
for (String format : formats) {
278273
if (!isTime) {
279-
for (var symbol : CUSTOM_FORMAT_TIME_SYMBOLS.toCharArray()) {
274+
for (char symbol : CUSTOM_FORMAT_TIME_SYMBOLS.toCharArray()) {
280275
if (format.contains(String.valueOf(symbol))) {
281276
isTime = true;
282277
break;
283278
}
284279
}
285280
}
286281
if (!isDate) {
287-
for (var symbol : CUSTOM_FORMAT_DATE_SYMBOLS.toCharArray()) {
282+
for (char symbol : CUSTOM_FORMAT_DATE_SYMBOLS.toCharArray()) {
288283
if (format.contains(String.valueOf(symbol))) {
289284
isDate = true;
290285
break;
@@ -393,7 +388,7 @@ public static OpenSearchDateType of() {
393388

394389
@Override
395390
public List<ExprType> getParent() {
396-
return List.of(this.exprCoreType);
391+
return List.of(exprCoreType);
397392
}
398393

399394
@Override
@@ -403,9 +398,9 @@ public boolean shouldCast(ExprType other) {
403398

404399
@Override
405400
protected OpenSearchDataType cloneEmpty() {
406-
if (this.formatString.isEmpty()) {
407-
return OpenSearchDateType.of(this.exprCoreType);
401+
if (formats.isEmpty()) {
402+
return OpenSearchDateType.of(exprCoreType);
408403
}
409-
return OpenSearchDateType.of(this.formatString);
404+
return OpenSearchDateType.of(String.join(" || ", formats));
410405
}
411406
}

opensearch/src/main/java/org/opensearch/sql/opensearch/data/value/OpenSearchExprValueFactory.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ private ExprValue parseTimestampString(String value, OpenSearchDateType dateType
243243
parsed = DateFormatters.from(DATE_TIME_FORMATTER.parse(value)).toInstant();
244244
return new ExprTimestampValue(parsed);
245245
} catch (DateTimeParseException ignored) {
246+
// ignored
246247
}
247248

248249
// otherwise, throw an error that no formatters worked
@@ -279,6 +280,7 @@ private ExprValue parseTimeString(String value, OpenSearchDateType dateType) {
279280
return new ExprTimeValue(
280281
DateFormatters.from(STRICT_HOUR_MINUTE_SECOND_FORMATTER.parse(value)).toLocalTime());
281282
} catch (DateTimeParseException ignored) {
283+
// ignored
282284
}
283285

284286
throw new IllegalArgumentException("Construct ExprTimeValue from \"" + value
@@ -313,6 +315,7 @@ private ExprValue parseDateString(String value, OpenSearchDateType dateType) {
313315
return new ExprDateValue(
314316
DateFormatters.from(STRICT_YEAR_MONTH_DAY_FORMATTER.parse(value)).toLocalDate());
315317
} catch (DateTimeParseException ignored) {
318+
// ignored
316319
}
317320

318321
throw new IllegalArgumentException("Construct ExprDateValue from \"" + value
@@ -325,19 +328,24 @@ private ExprValue createOpenSearchDateType(Content value, ExprType type) {
325328

326329
if (value.isNumber()) { // isNumber
327330
var numFormatters = dt.getNumericNamedFormatters();
328-
if (numFormatters.size() > 0) {
331+
if (numFormatters.size() > 0 || !dt.hasFormats()) {
329332
long epochMillis = 0;
330333
if (numFormatters.contains(DateFormatter.forPattern(
331-
FormatNames.EPOCH_MILLIS.getSnakeCaseName()))) {
334+
FormatNames.EPOCH_SECOND.getSnakeCaseName()))) {
332335
// no CamelCase for `EPOCH_*` formats
333-
epochMillis = value.longValue();
334-
} else /* EPOCH_SECOND */ {
335336
epochMillis = value.longValue() * 1000;
337+
} else /* EPOCH_MILLIS */ {
338+
epochMillis = value.longValue();
339+
}
340+
Instant instant = Instant.ofEpochMilli(epochMillis);
341+
switch ((ExprCoreType) returnFormat) {
342+
case TIME: return new ExprTimeValue(LocalTime.from(instant.atZone(UTC_ZONE_ID)));
343+
case DATE: return new ExprDateValue(LocalDate.ofInstant(instant, UTC_ZONE_ID));
344+
default: return new ExprTimestampValue(instant);
336345
}
337-
return new ExprTimestampValue(Instant.ofEpochMilli(epochMillis));
338346
} else {
339347
// custom format
340-
switch ((ExprCoreType) dt.getExprType()) {
348+
switch ((ExprCoreType) returnFormat) {
341349
case TIME: return parseTimeString(value.stringValue(), dt);
342350
case DATE: return parseDateString(value.stringValue(), dt);
343351
default: return parseTimestampString(value.stringValue(), dt);

opensearch/src/test/java/org/opensearch/sql/opensearch/data/value/OpenSearchExprValueFactoryTest.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@
3535
import static org.opensearch.sql.data.type.ExprCoreType.STRUCT;
3636
import static org.opensearch.sql.data.type.ExprCoreType.TIME;
3737
import static org.opensearch.sql.data.type.ExprCoreType.TIMESTAMP;
38+
import static org.opensearch.sql.utils.DateTimeUtils.UTC_ZONE_ID;
3839

3940
import com.fasterxml.jackson.core.JsonProcessingException;
4041
import com.fasterxml.jackson.databind.ObjectMapper;
4142
import com.google.common.collect.ImmutableMap;
4243
import java.time.Instant;
44+
import java.time.LocalDate;
45+
import java.time.LocalTime;
4346
import java.util.LinkedHashMap;
4447
import java.util.List;
4548
import java.util.Map;
@@ -212,7 +215,8 @@ public void constructDouble() {
212215
@Test
213216
public void constructString() {
214217
assertAll(
215-
() -> assertEquals(stringValue("text"), tupleValue("{\"stringV\":\"text\"}").get("stringV")),
218+
() -> assertEquals(stringValue("text"),
219+
tupleValue("{\"stringV\":\"text\"}").get("stringV")),
216220
() -> assertEquals(stringValue("text"), constructFromObject("stringV", "text"))
217221
);
218222
}
@@ -248,6 +252,9 @@ public void constructDates() {
248252
ExprValue dateStringV = constructFromObject("dateStringV", "1984-04-12");
249253
assertAll(
250254
() -> assertEquals(new ExprDateValue("1984-04-12"), dateStringV),
255+
() -> assertEquals(new ExprDateValue(
256+
LocalDate.ofInstant(Instant.ofEpochMilli(450576000000L), UTC_ZONE_ID)),
257+
constructFromObject("dateV", 450576000000L)),
251258
() -> assertEquals(new ExprDateValue("1984-04-12"),
252259
constructFromObject("dateOrOrdinalDateV", "1984-103")),
253260
() -> assertEquals(new ExprDateValue("2015-01-01"),
@@ -262,6 +269,9 @@ public void constructTimes() {
262269
() -> assertTrue(timeStringV.isDateTime()),
263270
() -> assertTrue(timeStringV instanceof ExprTimeValue),
264271
() -> assertEquals(new ExprTimeValue("12:10:30"), timeStringV),
272+
() -> assertEquals(new ExprTimeValue(LocalTime.from(
273+
Instant.ofEpochMilli(1420070400001L).atZone(UTC_ZONE_ID))),
274+
constructFromObject("timeV", 1420070400001L)),
265275
() -> assertEquals(new ExprTimeValue("09:07:42.000"),
266276
constructFromObject("timeNoMillisOrTimeV", "09:07:42.000Z")),
267277
() -> assertEquals(new ExprTimeValue("09:07:42"),
@@ -284,6 +294,9 @@ public void constructDatetime() {
284294
() -> assertEquals(
285295
new ExprTimestampValue("2015-01-01 12:10:30"),
286296
tupleValue("{\"timestampV\":\"2015-01-01 12:10:30\"}").get("timestampV")),
297+
() -> assertEquals(
298+
new ExprTimestampValue(Instant.ofEpochMilli(1420070400001L)),
299+
constructFromObject("timestampV", 1420070400001L)),
287300
() -> assertEquals(
288301
new ExprTimestampValue(Instant.ofEpochMilli(1420070400001L)),
289302
constructFromObject("timestampV", Instant.ofEpochMilli(1420070400001L))),

0 commit comments

Comments
 (0)