Skip to content

Commit a97962c

Browse files
committed
[test]
1 parent b4e78ba commit a97962c

File tree

12 files changed

+114
-16
lines changed

12 files changed

+114
-16
lines changed

be/src/vec/data_types/data_type_timestamptz.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,7 @@ class DataTypeTimeStampTz final : public DataTypeNumberBase<PrimitiveType::TYPE_
5151
return std::make_shared<DataTypeTimeStampTzSerDe>(_scale, nesting_level);
5252
};
5353
PrimitiveType get_primitive_type() const override { return PrimitiveType::TYPE_TIMESTAMPTZ; }
54-
const std::string get_family_name() const override {
55-
return "TimeStampTz(" + std::to_string(_scale) + ")";
56-
}
54+
const std::string get_family_name() const override { return "TimeStampTz"; }
5755
std::string do_get_name() const override {
5856
return "TimeStampTz(" + std::to_string(_scale) + ")";
5957
}

be/src/vec/functions/function_date_or_datetime_computation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,10 @@ using FunctionDatetimeSubYears =
121121

122122
using FunctionAddTimeDatetime = FunctionAddTime<TYPE_DATETIMEV2, AddTimeImpl>;
123123
using FunctionAddTimeTime = FunctionAddTime<TYPE_TIMEV2, AddTimeImpl>;
124+
using FunctionAddTimeTimestampTz = FunctionAddTime<TYPE_TIMESTAMPTZ, AddTimeImpl>;
124125
using FunctionSubTimeDatetime = FunctionAddTime<TYPE_DATETIMEV2, SubTimeImpl>;
125126
using FunctionSubTimeTime = FunctionAddTime<TYPE_TIMEV2, SubTimeImpl>;
127+
using FunctionSubTimeTimestampTz = FunctionAddTime<TYPE_TIMESTAMPTZ, SubTimeImpl>;
126128

127129
#define FUNCTION_TIME_DIFF(NAME, IMPL, TYPE) using NAME##_##TYPE = FunctionTimeDiff<IMPL<TYPE>>;
128130

@@ -221,8 +223,10 @@ void register_function_date_time_computation(SimpleFunctionFactory& factory) {
221223

222224
factory.register_function<FunctionAddTimeDatetime>();
223225
factory.register_function<FunctionAddTimeTime>();
226+
factory.register_function<FunctionAddTimeTimestampTz>();
224227
factory.register_function<FunctionSubTimeDatetime>();
225228
factory.register_function<FunctionSubTimeTime>();
229+
factory.register_function<FunctionSubTimeTimestampTz>();
226230

227231
#define REGISTER_DATEV2_FUNCTIONS_DIFF(NAME, TYPE) factory.register_function<NAME##_##TYPE>();
228232

be/src/vec/functions/function_date_or_datetime_computation.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,17 @@ class FunctionAddTime : public IFunction {
18701870
auto tv2 = static_cast<TimeValue::TimeType>(arg2);
18711871
double res = TimeValue::limit_with_bound(Impl::is_negative() ? tv1 - tv2 : tv1 + tv2);
18721872
return res;
1873+
} else if constexpr (PType == TYPE_TIMESTAMPTZ) {
1874+
DateV2Value<DateTimeV2ValueType> dtv1 =
1875+
binary_cast<InputType1, DateV2Value<DateTimeV2ValueType>>(arg1);
1876+
auto tv2 = static_cast<TimeValue::TimeType>(arg2);
1877+
TimeInterval interval(TimeUnit::MICROSECOND, tv2, Impl::is_negative());
1878+
bool out_range = dtv1.template date_add_interval<TimeUnit::MICROSECOND>(interval);
1879+
if (UNLIKELY(!out_range)) {
1880+
throw Exception(ErrorCode::INVALID_ARGUMENT,
1881+
"timestamptz value is out of range in function {}", name);
1882+
}
1883+
return binary_cast<DateV2Value<DateTimeV2ValueType>, ReturnNativeType>(dtv1);
18731884
} else {
18741885
throw Exception(ErrorCode::FATAL_ERROR, "not support type for function {}", name);
18751886
}

be/test/vec/data_types/data_type_timestamptz_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class DataTypeTimeStampTzTest : public ::testing::Test {
5353
};
5454

5555
TEST_F(DataTypeTimeStampTzTest, test_normal) {
56-
EXPECT_EQ(type->get_family_name(), "TimeStampTz(6)");
56+
EXPECT_EQ(type->get_family_name(), "TimeStampTz");
5757
EXPECT_EQ(type->get_primitive_type(), PrimitiveType::TYPE_TIMESTAMPTZ);
5858
EXPECT_EQ(type->get_scale(), 6);
5959

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ComputeSignatureHelper.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.apache.doris.nereids.types.MapType;
3333
import org.apache.doris.nereids.types.NullType;
3434
import org.apache.doris.nereids.types.StructType;
35+
import org.apache.doris.nereids.types.TimeStampTzType;
3536
import org.apache.doris.nereids.types.TimeV2Type;
3637
import org.apache.doris.nereids.types.VariantType;
3738
import org.apache.doris.nereids.types.coercion.AnyDataType;
@@ -457,14 +458,16 @@ public static FunctionSignature computePrecision(
457458

458459
boolean hasDateTimeV2Type = false;
459460
boolean hasTimeV2Type = false;
461+
boolean hasTimestampTzType = false;
460462
boolean hasDecimalV3Type = false;
461463
for (DataType argumentsType : signature.argumentsTypes) {
462464
hasDateTimeV2Type |= TypeCoercionUtils.hasDateTimeV2Type(argumentsType);
463465
hasTimeV2Type |= TypeCoercionUtils.hasTimeV2Type(argumentsType);
464466
hasDecimalV3Type |= TypeCoercionUtils.hasDecimalV3Type(argumentsType);
467+
hasTimestampTzType |= TypeCoercionUtils.hasTimestampTzType(argumentsType);
465468
}
466469

467-
if (hasDateTimeV2Type || hasTimeV2Type) {
470+
if (hasDateTimeV2Type || hasTimeV2Type || hasTimestampTzType) {
468471
signature = defaultTimePrecisionPromotion(signature, arguments);
469472
}
470473
if (hasDecimalV3Type) {
@@ -504,11 +507,14 @@ private static FunctionSignature defaultTimePrecisionPromotion(FunctionSignature
504507
arguments.get(i).getDataType()))
505508
.addAll(extractArgumentTypeBySignature(TimeV2Type.class, targetType,
506509
arguments.get(i).getDataType()))
510+
.addAll(extractArgumentTypeBySignature(TimeStampTzType.class, targetType,
511+
arguments.get(i).getDataType()))
507512
.build();
508513
// there's DateTimeV2 and TimeV2 at same time, so we need get exact target type when we promote any slot.
509514
List<DataType> nestedTargetTypes = ImmutableList.<DataType>builder()
510515
.addAll(extractSignatureTypes(DateTimeV2Type.class, targetType, arguments.get(i).getDataType()))
511516
.addAll(extractSignatureTypes(TimeV2Type.class, targetType, arguments.get(i).getDataType()))
517+
.addAll(extractSignatureTypes(TimeStampTzType.class, targetType, arguments.get(i).getDataType()))
512518
.build();
513519
if (nestedInputTypes.isEmpty()) {
514520
// if no DateTimeV2Type or TimeV2Type in the argument[i], no precision promotion
@@ -552,6 +558,7 @@ private static FunctionSignature defaultTimePrecisionPromotion(FunctionSignature
552558
List<DataType> newArgTypes = newArgTypesBuilder.build();
553559
signature = signature.withArgumentTypes(signature.hasVarArgs, newArgTypes);
554560
if (signature.returnType instanceof DateTimeV2Type || signature.returnType instanceof TimeV2Type
561+
|| signature.returnType instanceof TimeStampTzType
555562
|| signature.returnType instanceof ComplexDataType) {
556563
signature = signature.withReturnType(
557564
TypeCoercionUtils.replaceTimesWithTargetPrecision(signature.returnType, finalTypeScale));

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/SearchSignature.java

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.doris.nereids.exceptions.AnalysisException;
2323
import org.apache.doris.nereids.trees.expressions.Expression;
2424
import org.apache.doris.nereids.trees.expressions.literal.Literal;
25+
import org.apache.doris.nereids.trees.expressions.literal.format.DateTimeChecker;
2526
import org.apache.doris.nereids.types.DataType;
2627
import org.apache.doris.nereids.types.DateTimeType;
2728
import org.apache.doris.nereids.types.DateTimeV2Type;
@@ -81,10 +82,12 @@ public Optional<FunctionSignature> result() {
8182
int candidateNonStrictMatched = Integer.MAX_VALUE;
8283
int candidateNonStrictMatchedWithoutStringLiteralCoercion = Integer.MAX_VALUE;
8384
int candidateDateToDateV2Count = Integer.MIN_VALUE;
85+
int candidateTimeZoneCoersionScore = Integer.MIN_VALUE;
8486
FunctionSignature candidate = null;
8587
for (FunctionSignature signature : signatures) {
8688
if (doMatchArity(signature, arguments)) {
87-
Pair<Boolean, Integer> matchTypesResult = doMatchTypes(signature, arguments, typePredicate);
89+
Pair<Boolean, Pair<Integer, Integer>> matchTypesResult =
90+
doMatchTypes(signature, arguments, typePredicate);
8891
if (!matchTypesResult.first) {
8992
continue;
9093
}
@@ -106,17 +109,24 @@ public Optional<FunctionSignature> result() {
106109
Pair<Integer, Integer> currentNonStrictMatched = nonStrictMatchedCount(signature, arguments);
107110
int currentNonStrictMatchedCount = currentNonStrictMatched.first;
108111
int currentNonStrictMatchedWithoutStringLiteralCoercion
109-
= currentNonStrictMatchedCount - matchTypesResult.second;
112+
= currentNonStrictMatchedCount - matchTypesResult.second.first;
113+
int currentTimeZoneCoersionScore = matchTypesResult.second.second;
110114
if (currentNonStrictMatchedWithoutStringLiteralCoercion
111115
< candidateNonStrictMatchedWithoutStringLiteralCoercion) {
112116
candidateNonStrictMatchedWithoutStringLiteralCoercion
113117
= currentNonStrictMatchedWithoutStringLiteralCoercion;
114118
candidateNonStrictMatched = currentNonStrictMatchedCount;
115119
candidateDateToDateV2Count = currentNonStrictMatched.second;
120+
candidateTimeZoneCoersionScore = currentTimeZoneCoersionScore;
116121
candidate = signature;
117122
} else if (currentNonStrictMatchedWithoutStringLiteralCoercion
118123
== candidateNonStrictMatchedWithoutStringLiteralCoercion) {
119-
if (currentNonStrictMatchedCount < candidateNonStrictMatched) {
124+
if (currentTimeZoneCoersionScore > candidateTimeZoneCoersionScore) {
125+
candidateTimeZoneCoersionScore = currentTimeZoneCoersionScore;
126+
candidateNonStrictMatched = currentNonStrictMatchedCount;
127+
candidateDateToDateV2Count = currentNonStrictMatched.second;
128+
candidate = signature;
129+
} else if (currentNonStrictMatchedCount < candidateNonStrictMatched) {
120130
candidateNonStrictMatched = currentNonStrictMatchedCount;
121131
candidateDateToDateV2Count = currentNonStrictMatched.second;
122132
candidate = signature;
@@ -226,9 +236,10 @@ private Pair<Integer, Integer> nonStrictMatchedCount(FunctionSignature sig, List
226236
return Pair.of(nonStrictMatched, dateToDateV2Count);
227237
}
228238

229-
private Pair<Boolean, Integer> doMatchTypes(FunctionSignature sig, List<Expression> arguments,
239+
private Pair<Boolean, Pair<Integer, Integer>> doMatchTypes(FunctionSignature sig, List<Expression> arguments,
230240
BiFunction<DataType, DataType, Boolean> typePredicate) {
231241
int stringLiteralCoersionCount = 0;
242+
int timeZoneCoersionScore = 0;
232243
int arity = arguments.size();
233244
for (int i = 0; i < arity; i++) {
234245
DataType sigArgType = sig.getArgType(i);
@@ -243,12 +254,22 @@ private Pair<Boolean, Integer> doMatchTypes(FunctionSignature sig, List<Expressi
243254
if (!realType.isStringLikeType()) {
244255
stringLiteralCoersionCount++;
245256
}
257+
258+
String literalValue = ((Literal) argument).getStringValue();
259+
if (sigArgType.isTimeStampTzType()) {
260+
boolean hasTimeZone = DateTimeChecker.hasTimeZone(literalValue);
261+
if (hasTimeZone) {
262+
timeZoneCoersionScore++;
263+
} else {
264+
timeZoneCoersionScore--;
265+
}
266+
}
246267
}
247268
if (!typePredicate.apply(sigArgType, realType)) {
248-
return Pair.of(false, stringLiteralCoersionCount);
269+
return Pair.of(false, Pair.of(stringLiteralCoersionCount, timeZoneCoersionScore));
249270
}
250271
}
251-
return Pair.of(true, stringLiteralCoersionCount);
272+
return Pair.of(true, Pair.of(stringLiteralCoersionCount, timeZoneCoersionScore));
252273
}
253274

254275
public static void throwCanNotFoundFunctionException(String name, List<Expression> arguments) {

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/AddTime.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression;
2626
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
2727
import org.apache.doris.nereids.types.DateTimeV2Type;
28+
import org.apache.doris.nereids.types.TimeStampTzType;
2829
import org.apache.doris.nereids.types.TimeV2Type;
2930

3031
import com.google.common.base.Preconditions;
@@ -41,7 +42,10 @@ public class AddTime extends ScalarFunction implements BinaryExpression, Explici
4142
private static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
4243
FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD,
4344
TimeV2Type.WILDCARD),
44-
FunctionSignature.ret(TimeV2Type.WILDCARD).args(TimeV2Type.WILDCARD, TimeV2Type.WILDCARD));
45+
FunctionSignature.ret(TimeV2Type.WILDCARD).args(TimeV2Type.WILDCARD, TimeV2Type.WILDCARD),
46+
FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD,
47+
TimeV2Type.WILDCARD)
48+
);
4549

4650
public AddTime(Expression arg0, Expression arg1) {
4751
super("add_time", arg0, arg1);

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/TimestampTzLiteral.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public TimestampTzLiteral(long year, long month, long day, long hour, long minut
5353
}
5454

5555
public TimestampTzLiteral(long year, long month, long day, long hour, long minute, long second, long microSecond) {
56-
super(TimeStampTzType.SYSTEM_DEFAULT, year, month, day, hour, minute, second, microSecond);
56+
super(TimeStampTzType.WILDCARD, year, month, day, hour, minute, second, microSecond);
5757
}
5858

5959
public TimestampTzLiteral(TimeStampTzType dateType,

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/format/DateTimeChecker.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,45 @@ public static boolean isValidDateTime(String str) {
9898
return INSTANCE.check(stringInspect).matched && stringInspect.eos();
9999
}
100100

101+
/** check tz or dt */
102+
public static boolean hasTimeZone(String str) {
103+
str = str.trim();
104+
105+
if (!isValidDateTime(str)) {
106+
return false;
107+
}
108+
109+
if (str.endsWith("Z")) {
110+
return true;
111+
}
112+
113+
// Find the separator between date and time parts (' ' or 'T')
114+
int timeSeparatorIndex = -1;
115+
for (int i = 0; i < str.length(); i++) {
116+
if (str.charAt(i) == ' ' || str.charAt(i) == 'T') {
117+
timeSeparatorIndex = i;
118+
break;
119+
}
120+
}
121+
122+
// no time part found
123+
if (timeSeparatorIndex == -1) {
124+
return false;
125+
}
126+
127+
// Only search for timezone after the time separator
128+
for (int i = str.length() - 1; i > timeSeparatorIndex; i--) {
129+
char c = str.charAt(i);
130+
if (c == '+' || c == '-') {
131+
if (i + 1 < str.length() && Character.isDigit(str.charAt(i + 1))) {
132+
return true;
133+
}
134+
}
135+
}
136+
137+
return false;
138+
}
139+
101140
@Override
102141
protected boolean doCheck(StringInspect stringInspect) {
103142
return checker.check(stringInspect).matched;

fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeV2Type.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ public static DateTimeV2Type forType(DataType dataType) {
7676
if (dataType instanceof DateTimeV2Type) {
7777
return (DateTimeV2Type) dataType;
7878
}
79+
if (dataType instanceof TimeStampTzType) {
80+
return DateTimeV2Type.of(((TimeStampTzType) dataType).getScale());
81+
}
7982
if (dataType instanceof IntegralType || dataType instanceof BooleanType || dataType instanceof NullType
8083
|| dataType instanceof DateTimeType || dataType instanceof DateType || dataType instanceof DateV2Type) {
8184
return SYSTEM_DEFAULT;

0 commit comments

Comments
 (0)