From c7f75f5ec9ed543a8f8dd954f266fb0fc7208cbb Mon Sep 17 00:00:00 2001 From: HangyuanLiu <460660596@qq.com> Date: Thu, 18 Jul 2019 11:07:30 +0800 Subject: [PATCH] add timediff function --- be/src/exec/olap_scanner.cpp | 79 ++++++---- be/src/exprs/expr.cpp | 18 +++ be/src/exprs/expr.h | 2 + be/src/exprs/expr_context.cpp | 17 ++ be/src/exprs/expr_context.h | 1 + be/src/exprs/expr_ir.cpp | 3 + be/src/exprs/literal.cpp | 9 ++ be/src/exprs/literal.h | 1 + be/src/exprs/scalar_fn_call.cpp | 13 +- be/src/exprs/scalar_fn_call.h | 1 + be/src/exprs/slot_ref.cpp | 11 ++ be/src/exprs/slot_ref.h | 1 + be/src/exprs/timestamp_functions.cpp | 12 +- be/src/exprs/timestamp_functions.h | 2 +- be/src/runtime/datetime_value.h | 4 + be/src/runtime/primitive_type.cpp | 9 ++ be/src/runtime/primitive_type.h | 6 +- be/src/runtime/raw_value.cpp | 1 + be/src/runtime/result_writer.cpp | 3 +- be/src/udf/udf.h | 29 ++++ fe/src/main/cup/sql_parser.cup | 4 +- .../apache/doris/analysis/TimeLiteral.java | 146 ++++++++++++++++++ .../org/apache/doris/catalog/Function.java | 4 + .../apache/doris/catalog/PrimitiveType.java | 9 ++ .../apache/doris/catalog/ScalarFunction.java | 3 + .../org/apache/doris/catalog/ScalarType.java | 6 + .../java/org/apache/doris/catalog/Type.java | 6 + .../apache/doris/common/util/TimeUtils.java | 10 ++ .../org/apache/doris/rewrite/FEFunctions.java | 12 ++ gensrc/script/doris_builtins_functions.py | 2 +- gensrc/script/gen_functions.py | 3 + gensrc/script/gen_opcodes.py | 1 + gensrc/thrift/Exprs.thrift | 7 + gensrc/thrift/Types.thrift | 8 +- 34 files changed, 400 insertions(+), 43 deletions(-) create mode 100644 fe/src/main/java/org/apache/doris/analysis/TimeLiteral.java diff --git a/be/src/exec/olap_scanner.cpp b/be/src/exec/olap_scanner.cpp index 97257922f3642a..e4b8f1b38c142d 100644 --- a/be/src/exec/olap_scanner.cpp +++ b/be/src/exec/olap_scanner.cpp @@ -80,39 +80,54 @@ Status OlapScanner::_prepare( strtoul(scan_range->scan_range().version_hash.c_str(), nullptr, 10); { std::string err; - _olap_table = OLAPEngine::get_instance()->get_table(tablet_id, schema_hash, true, &err); - if (_olap_table.get() == nullptr) { + _tablet = StorageEngine::instance()->tablet_manager()->get_tablet(tablet_id, schema_hash, true, &err); + if (_tablet.get() == nullptr) { std::stringstream ss; - ss << "failed to get tablet: " << tablet_id << " with schema hash: " << schema_hash - << ", reason: " << err; + ss << "failed to get tablet. tablet_id=" << tablet_id + << ", with schema_hash=" << schema_hash + << ", reason=" << err; LOG(WARNING) << ss.str(); return Status::InternalError(ss.str()); } { - ReadLock rdlock(_olap_table->get_header_lock_ptr()); - const PDelta* delta = _olap_table->lastest_version(); - if (delta == NULL) { + ReadLock rdlock(_tablet->get_header_lock_ptr()); + const RowsetSharedPtr rowset = _tablet->rowset_with_max_version(); + if (rowset == nullptr) { std::stringstream ss; ss << "fail to get latest version of tablet: " << tablet_id; - OLAP_LOG_WARNING(ss.str().c_str()); + LOG(WARNING) << ss.str(); return Status::InternalError(ss.str()); } - if (delta->end_version() == _version - && delta->version_hash() != version_hash) { - OLAP_LOG_WARNING("fail to check latest version hash. " - "[tablet_id=%ld version_hash=%ld request_version_hash=%ld]", - tablet_id, delta->version_hash(), version_hash); + if (rowset->end_version() == _version + && rowset->version_hash() != version_hash) { + LOG(WARNING) << "fail to check latest version hash. " + << " tablet_id=" << tablet_id + << " version_hash=" << rowset->version_hash() + << " request_version_hash=" << version_hash; std::stringstream ss; ss << "fail to check version hash of tablet: " << tablet_id; return Status::InternalError(ss.str()); } + + // acquire tablet rowset readers at the beginning of the scan node + // to prevent this case: when there are lots of olap scanners to run for example 10000 + // the rowsets maybe compacted when the last olap scanner starts + Version rd_version(0, _version); + OLAPStatus acquire_reader_st = _tablet->capture_rs_readers(rd_version, &_params.rs_readers); + if (acquire_reader_st != OLAP_SUCCESS) { + LOG(WARNING) << "fail to init reader.res=" << acquire_reader_st; + std::stringstream ss; + ss << "failed to initialize storage reader. tablet=" << _tablet->full_name() + << ", res=" << acquire_reader_st << ", backend=" << BackendOptions::get_localhost(); + return Status::InternalError(ss.str().c_str()); + } } } - - // Initialize _params + { + // Initialize _params RETURN_IF_ERROR(_init_params(key_ranges, filters, is_nulls)); } @@ -131,20 +146,21 @@ Status OlapScanner::open() { if (res != OLAP_SUCCESS) { OLAP_LOG_WARNING("fail to init reader.[res=%d]", res); std::stringstream ss; - ss << "failed to initialize storage reader. tablet=" << _params.olap_table->full_name() + ss << "failed to initialize storage reader. tablet=" << _params.tablet->full_name() << ", res=" << res << ", backend=" << BackendOptions::get_localhost(); return Status::InternalError(ss.str().c_str()); } return Status::OK(); } +// it will be called under tablet read lock because capture rs readers need Status OlapScanner::_init_params( const std::vector& key_ranges, const std::vector& filters, const std::vector& is_nulls) { RETURN_IF_ERROR(_init_return_columns()); - _params.olap_table = _olap_table; + _params.tablet = _tablet; _params.reader_type = READER_QUERY; _params.aggregation = _aggregation; _params.version = Version(0, _version); @@ -177,11 +193,11 @@ Status OlapScanner::_init_params( if (_aggregation) { _params.return_columns = _return_columns; } else { - for (size_t i = 0; i < _olap_table->num_key_fields(); ++i) { + for (size_t i = 0; i < _tablet->num_key_columns(); ++i) { _params.return_columns.push_back(i); } for (auto index : _return_columns) { - if (_olap_table->tablet_schema()[index].is_key) { + if (_tablet->tablet_schema().column(index).is_key()) { continue; } else { _params.return_columns.push_back(index); @@ -190,12 +206,12 @@ Status OlapScanner::_init_params( } // use _params.return_columns, because reader use this to merge sort - OLAPStatus res = _read_row_cursor.init(_olap_table->tablet_schema(), _params.return_columns); + OLAPStatus res = _read_row_cursor.init(_tablet->tablet_schema(), _params.return_columns); if (res != OLAP_SUCCESS) { OLAP_LOG_WARNING("fail to init row cursor.[res=%d]", res); return Status::InternalError("failed to initialize storage read row cursor"); } - _read_row_cursor.allocate_memory_for_string_type(_olap_table->tablet_schema()); + _read_row_cursor.allocate_memory_for_string_type(_tablet->tablet_schema()); for (auto cid : _return_columns) { _query_fields.push_back(_read_row_cursor.get_field_by_index(cid)); } @@ -208,7 +224,7 @@ Status OlapScanner::_init_return_columns() { if (!slot->is_materialized()) { continue; } - int32_t index = _olap_table->get_field_index(slot->col_name()); + int32_t index = _tablet->field_index(slot->col_name()); if (index < 0) { std::stringstream ss; ss << "field name is invalied. field=" << slot->col_name(); @@ -216,12 +232,13 @@ Status OlapScanner::_init_return_columns() { return Status::InternalError(ss.str()); } _return_columns.push_back(index); - if (_olap_table->tablet_schema()[index].type == OLAP_FIELD_TYPE_VARCHAR || - _olap_table->tablet_schema()[index].type == OLAP_FIELD_TYPE_HLL) { + const TabletColumn& column = _tablet->tablet_schema().column(index); + if (column.type() == OLAP_FIELD_TYPE_VARCHAR || + column.type() == OLAP_FIELD_TYPE_HLL) { _request_columns_size.push_back( - _olap_table->tablet_schema()[index].length - sizeof(StringLengthType)); + column.length() - sizeof(StringLengthType)); } else { - _request_columns_size.push_back(_olap_table->tablet_schema()[index].length); + _request_columns_size.push_back(column.length()); } _query_slots.push_back(slot); } @@ -397,7 +414,8 @@ void OlapScanner::_convert_row_to_tuple(Tuple* tuple) { } break; } - case TYPE_DATETIME: { + case TYPE_DATETIME: + case TYPE_TIME: { DateTimeValue *slot = tuple->get_datetime_slot(slot_desc->tuple_offset()); uint64_t value = *reinterpret_cast(ptr); if (!slot->from_olap_datetime(value)) { @@ -477,6 +495,13 @@ Status OlapScanner::close(RuntimeState* state) { if (_is_closed) { return Status::OK(); } + // olap scan node will call scanner.close() when finished + // will release resources here + // if not clear rowset readers in read_params here + // readers will be release when runtime state deconstructed but + // deconstructor in reader references runtime state + // so that it will core + _params.rs_readers.clear(); update_counter(); _reader.reset(); Expr::close(_conjunct_ctxs, state); diff --git a/be/src/exprs/expr.cpp b/be/src/exprs/expr.cpp index ee850da5be9c16..771fb78564e27a 100644 --- a/be/src/exprs/expr.cpp +++ b/be/src/exprs/expr.cpp @@ -150,6 +150,10 @@ Expr::Expr(const TypeDescriptor& type) : _node_type = (TExprNodeType::DATE_LITERAL); break; + case TYPE_TIME: + _node_type = (TExprNodeType::TIME_LITERAL); + break; + case TYPE_CHAR: case TYPE_VARCHAR: case TYPE_HLL: @@ -207,6 +211,10 @@ Expr::Expr(const TypeDescriptor& type, bool is_slotref) : _node_type = (TExprNodeType::DATE_LITERAL); break; + case TYPE_TIME: + _node_type = (TExprNodeType::TIME_LITERAL); + break; + case TYPE_CHAR: case TYPE_VARCHAR: case TYPE_HLL: @@ -331,6 +339,7 @@ Status Expr::create_expr(ObjectPool* pool, const TExprNode& texpr_node, Expr** e case TExprNodeType::DECIMAL_LITERAL: case TExprNodeType::DATE_LITERAL: case TExprNodeType::STRING_LITERAL: + case TExprNodeType::TIME_LITERAL: *expr = pool->add(new Literal(texpr_node)); return Status::OK(); case TExprNodeType::COMPOUND_PRED: @@ -758,6 +767,10 @@ doris_udf::AnyVal* Expr::get_const_val(ExprContext* context) { _constant_val.reset(new DateTimeVal(get_datetime_val(context, NULL))); break; } + case TYPE_TIME: { + _constant_val.reset(new TimeVal(get_time_val(context, NULL))); + break; + } case TYPE_DECIMAL: { _constant_val.reset(new DecimalVal(get_decimal_val(context, NULL))); break; @@ -835,6 +848,11 @@ StringVal Expr::get_string_val(ExprContext* context, TupleRow* row) { return val; } +TimeVal Expr::get_time_val(ExprContext* context, TupleRow* row) { + TimeVal val; + return val; +} + // TODO(zc) // virtual ArrayVal Expr::GetArrayVal(ExprContext* context, TupleRow*); DateTimeVal Expr::get_datetime_val(ExprContext* context, TupleRow* row) { diff --git a/be/src/exprs/expr.h b/be/src/exprs/expr.h index a32bfd3bbd4e65..e2bfe3741040d4 100644 --- a/be/src/exprs/expr.h +++ b/be/src/exprs/expr.h @@ -121,6 +121,7 @@ class Expr { virtual StringVal get_string_val(ExprContext* context, TupleRow*); // TODO(zc) // virtual ArrayVal GetArrayVal(ExprContext* context, TupleRow*); + virtual TimeVal get_time_val(ExprContext* context, TupleRow*); virtual DateTimeVal get_datetime_val(ExprContext* context, TupleRow*); virtual DecimalVal get_decimal_val(ExprContext* context, TupleRow*); virtual DecimalV2Val get_decimalv2_val(ExprContext* context, TupleRow*); @@ -517,6 +518,7 @@ class Expr { static DoubleVal get_double_val(Expr* expr, ExprContext* context, TupleRow* row); static StringVal get_string_val(Expr* expr, ExprContext* context, TupleRow* row); static DateTimeVal get_datetime_val(Expr* expr, ExprContext* context, TupleRow* row); + static TimeVal get_time_val(Expr* expr, ExprContext* context, TupleRow* row); static DecimalVal get_decimal_val(Expr* expr, ExprContext* context, TupleRow* row); static DecimalV2Val get_decimalv2_val(Expr* expr, ExprContext* context, TupleRow* row); diff --git a/be/src/exprs/expr_context.cpp b/be/src/exprs/expr_context.cpp index fb5e50a110e393..41cdce3f96b979 100644 --- a/be/src/exprs/expr_context.cpp +++ b/be/src/exprs/expr_context.cpp @@ -367,6 +367,19 @@ void* ExprContext::get_value(Expr* e, TupleRow* row) { _result.datetime_val = DateTimeValue::from_datetime_val(v); return &_result.datetime_val; } + case TYPE_TIME: { + doris_udf::TimeVal v = e->get_time_val(this, row); + if (v.is_null) { + return NULL; + } + + int64_t second = v.time % 60; + int64_t minute = v.time / 60 % 60; + int64_t hour = v.time / 60 / 60; + + _result.datetime_val.from_time_int64(hour * 10000 + minute * 100 + second); + return &_result.datetime_val; + } case TYPE_DECIMAL: { DecimalVal v = e->get_decimal_val(this, row); if (v.is_null) { @@ -464,6 +477,10 @@ DecimalV2Val ExprContext::get_decimalv2_val(TupleRow* row) { return _root->get_decimalv2_val(this, row); } +TimeVal ExprContext::get_time_val(TupleRow* row) { + return _root->get_time_val(this, row); +} + Status ExprContext::get_const_value(RuntimeState* state, Expr& expr, AnyVal** const_val) { DCHECK(_opened); diff --git a/be/src/exprs/expr_context.h b/be/src/exprs/expr_context.h index de57638857be3f..36c014fb0297da 100644 --- a/be/src/exprs/expr_context.h +++ b/be/src/exprs/expr_context.h @@ -143,6 +143,7 @@ class ExprContext { DateTimeVal get_datetime_val(TupleRow* row); DecimalVal get_decimal_val(TupleRow* row); DecimalV2Val get_decimalv2_val(TupleRow* row); + TimeVal get_time_val(TupleRow* row); /// Frees all local allocations made by fn_contexts_. This can be called when result /// data from this context is no longer needed. diff --git a/be/src/exprs/expr_ir.cpp b/be/src/exprs/expr_ir.cpp index b29b0fc3b2a054..b31808bd83ff30 100644 --- a/be/src/exprs/expr_ir.cpp +++ b/be/src/exprs/expr_ir.cpp @@ -71,6 +71,9 @@ StringVal Expr::get_string_val(Expr* expr, ExprContext* context, TupleRow* row) DateTimeVal Expr::get_datetime_val(Expr* expr, ExprContext* context, TupleRow* row) { return expr->get_datetime_val(context, row); } +TimeVal Expr::get_time_val(Expr* expr, ExprContext* context, TupleRow* row) { + return expr->get_time_val(context, row); +} DecimalVal Expr::get_decimal_val(Expr* expr, ExprContext* context, TupleRow* row) { return expr->get_decimal_val(context, row); } diff --git a/be/src/exprs/literal.cpp b/be/src/exprs/literal.cpp index bdd00f7dc948c1..977f3e0190ef92 100644 --- a/be/src/exprs/literal.cpp +++ b/be/src/exprs/literal.cpp @@ -87,6 +87,9 @@ Literal::Literal(const TExprNode& node) : _value.datetime_val.from_date_str( node.date_literal.value.c_str(), node.date_literal.value.size()); break; + case TYPE_TIME: + _value.datetime_val.from_time_int64(node.time_literal.value); + break; case TYPE_CHAR: case TYPE_VARCHAR: DCHECK_EQ(node.node_type, TExprNodeType::STRING_LITERAL); @@ -174,6 +177,12 @@ DateTimeVal Literal::get_datetime_val(ExprContext* context, TupleRow* row) { return dt_val; } +TimeVal Literal::get_time_val(ExprContext* context, TupleRow* row) { + TimeVal tm_val; + _value.datetime_val.to_time_val(&tm_val); + return tm_val; +} + StringVal Literal::get_string_val(ExprContext* context, TupleRow* row) { DCHECK(_type.is_string_type()) << _type; StringVal str_val; diff --git a/be/src/exprs/literal.h b/be/src/exprs/literal.h index cf48f26689ed20..d989b17a7ec51e 100644 --- a/be/src/exprs/literal.h +++ b/be/src/exprs/literal.h @@ -46,6 +46,7 @@ class Literal : public Expr { virtual DecimalVal get_decimal_val(ExprContext* context, TupleRow*); virtual DecimalV2Val get_decimalv2_val(ExprContext* context, TupleRow*); virtual DateTimeVal get_datetime_val(ExprContext* context, TupleRow*); + virtual TimeVal get_time_val(ExprContext* context, TupleRow*); virtual StringVal get_string_val(ExprContext* context, TupleRow* row); protected: diff --git a/be/src/exprs/scalar_fn_call.cpp b/be/src/exprs/scalar_fn_call.cpp index 9e67d793e203c1..1ea50e7f5e168e 100644 --- a/be/src/exprs/scalar_fn_call.cpp +++ b/be/src/exprs/scalar_fn_call.cpp @@ -746,6 +746,7 @@ typedef FloatVal (*FloatWrapper)(ExprContext*, TupleRow*); typedef DoubleVal (*DoubleWrapper)(ExprContext*, TupleRow*); typedef StringVal (*StringWrapper)(ExprContext*, TupleRow*); typedef DateTimeVal (*DatetimeWrapper)(ExprContext*, TupleRow*); +typedef TimeVal (*TimeWrapper)(ExprContext*, TupleRow*); typedef DecimalVal (*DecimalWrapper)(ExprContext*, TupleRow*); typedef DecimalV2Val (*DecimalV2Wrapper)(ExprContext*, TupleRow*); @@ -851,6 +852,17 @@ DateTimeVal ScalarFnCall::get_datetime_val(ExprContext* context, TupleRow* row) return fn(context, row); } +TimeVal ScalarFnCall::get_time_val(ExprContext* context, TupleRow* row) { + std::cout << "get_time_val[scalar]" << std::endl; + + DCHECK(context != NULL); + if (_scalar_fn_wrapper == NULL) { + return interpret_eval(context, row); + } + TimeWrapper fn = reinterpret_cast(_scalar_fn_wrapper); + return fn(context, row); +} + DecimalVal ScalarFnCall::get_decimal_val(ExprContext* context, TupleRow* row) { DCHECK_EQ(_type.type, TYPE_DECIMAL); DCHECK(context != NULL); @@ -871,7 +883,6 @@ DecimalV2Val ScalarFnCall::get_decimalv2_val(ExprContext* context, TupleRow* row return fn(context, row); } - std::string ScalarFnCall::debug_string() const { std::stringstream out; out << "ScalarFnCall(udf_type=" << _fn.binary_type diff --git a/be/src/exprs/scalar_fn_call.h b/be/src/exprs/scalar_fn_call.h index 4bf337723dd8b3..f69e665b893966 100644 --- a/be/src/exprs/scalar_fn_call.h +++ b/be/src/exprs/scalar_fn_call.h @@ -78,6 +78,7 @@ class ScalarFnCall : public Expr { virtual doris_udf::DoubleVal get_double_val(ExprContext* context, TupleRow*); virtual doris_udf::StringVal get_string_val(ExprContext* context, TupleRow*); virtual doris_udf::DateTimeVal get_datetime_val(ExprContext* context, TupleRow*); + virtual doris_udf::TimeVal get_time_val(ExprContext* context, TupleRow*); virtual doris_udf::DecimalVal get_decimal_val(ExprContext* context, TupleRow*); virtual doris_udf::DecimalV2Val get_decimalv2_val(ExprContext* context, TupleRow*); // virtual doris_udf::ArrayVal GetArrayVal(ExprContext* context, TupleRow*); diff --git a/be/src/exprs/slot_ref.cpp b/be/src/exprs/slot_ref.cpp index dbc0386d356eb6..99fe44628ee2f1 100644 --- a/be/src/exprs/slot_ref.cpp +++ b/be/src/exprs/slot_ref.cpp @@ -510,6 +510,17 @@ DateTimeVal SlotRef::get_datetime_val(ExprContext* context, TupleRow* row) { return result; } +TimeVal SlotRef::get_time_val(ExprContext* context, TupleRow* row) { + Tuple *t = row->get_tuple(_tuple_idx); + if (t == NULL || t->is_null(_null_indicator_offset)) { + return TimeVal::null(); + } + DateTimeValue *tv = reinterpret_cast(t->get_slot(_slot_offset)); + TimeVal tm_val; + tv->to_time_val(&tm_val); + return tm_val; +} + DecimalVal SlotRef::get_decimal_val(ExprContext* context, TupleRow* row) { DCHECK_EQ(_type.type, TYPE_DECIMAL); Tuple* t = row->get_tuple(_tuple_idx); diff --git a/be/src/exprs/slot_ref.h b/be/src/exprs/slot_ref.h index acdecca9476b18..03bcb3186abef0 100644 --- a/be/src/exprs/slot_ref.h +++ b/be/src/exprs/slot_ref.h @@ -77,6 +77,7 @@ class SlotRef : public Expr { virtual doris_udf::DoubleVal get_double_val(ExprContext* context, TupleRow*); virtual doris_udf::StringVal get_string_val(ExprContext* context, TupleRow*); virtual doris_udf::DateTimeVal get_datetime_val(ExprContext* context, TupleRow*); + virtual doris_udf::TimeVal get_time_val(ExprContext* context, TupleRow*); virtual doris_udf::DecimalVal get_decimal_val(ExprContext* context, TupleRow*); virtual doris_udf::DecimalV2Val get_decimalv2_val(ExprContext* context, TupleRow*); // virtual doris_udf::ArrayVal GetArrayVal(ExprContext* context, TupleRow*); diff --git a/be/src/exprs/timestamp_functions.cpp b/be/src/exprs/timestamp_functions.cpp index 17174d631248d4..1732480976cdff 100644 --- a/be/src/exprs/timestamp_functions.cpp +++ b/be/src/exprs/timestamp_functions.cpp @@ -463,18 +463,16 @@ IntVal TimestampFunctions::to_days( } // TODO(dhc): implement this funciton really -DateTimeVal TimestampFunctions::time_diff( +TimeVal TimestampFunctions::time_diff( FunctionContext* ctx, const DateTimeVal& ts_val1, const DateTimeVal& ts_val2) { if (ts_val1.is_null || ts_val2.is_null) { - return DateTimeVal::null(); + return TimeVal::null(); } const DateTimeValue& ts_value1 = DateTimeValue::from_datetime_val(ts_val1); const DateTimeValue& ts_value2 = DateTimeValue::from_datetime_val(ts_val2); - DateTimeValue ts = ts_value1 - ts_value2; - ts.cast_to_time(); - DateTimeVal result; - ts.to_datetime_val(&result); - return result; + int timediff = ts_value1.unix_timestamp() - ts_value2.unix_timestamp(); + + return TimeVal(timediff); } IntVal TimestampFunctions::date_diff( diff --git a/be/src/exprs/timestamp_functions.h b/be/src/exprs/timestamp_functions.h index c14edfe1e7355f..911bcd83f35316 100644 --- a/be/src/exprs/timestamp_functions.h +++ b/be/src/exprs/timestamp_functions.h @@ -84,7 +84,7 @@ class TimestampFunctions { static doris_udf::IntVal date_diff( doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val1, const doris_udf::DateTimeVal& ts_val2); - static doris_udf::DateTimeVal time_diff( + static doris_udf::TimeVal time_diff( doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val1, const doris_udf::DateTimeVal& ts_val2); diff --git a/be/src/runtime/datetime_value.h b/be/src/runtime/datetime_value.h index 3ae5c5af4ad50b..6582911d557371 100644 --- a/be/src/runtime/datetime_value.h +++ b/be/src/runtime/datetime_value.h @@ -400,6 +400,10 @@ class DateTimeValue { tv->type = _type; } + void to_time_val(doris_udf::TimeVal* tv) const { + tv->time = to_time_int64(); + } + static DateTimeValue from_datetime_val(const doris_udf::DateTimeVal& tv) { DateTimeValue value; value.from_packed_time(tv.packed_time); diff --git a/be/src/runtime/primitive_type.cpp b/be/src/runtime/primitive_type.cpp index 5ff86c23f3fbb1..8971ef11c19aea 100644 --- a/be/src/runtime/primitive_type.cpp +++ b/be/src/runtime/primitive_type.cpp @@ -68,6 +68,9 @@ PrimitiveType thrift_to_type(TPrimitiveType::type ttype) { case TPrimitiveType::DATETIME: return TYPE_DATETIME; + case TPrimitiveType::TIME: + return TYPE_TIME; + case TPrimitiveType::VARCHAR: return TYPE_VARCHAR; @@ -129,6 +132,9 @@ TPrimitiveType::type to_thrift(PrimitiveType ptype) { case TYPE_DATETIME: return TPrimitiveType::DATETIME; + case TYPE_TIME: + return TPrimitiveType::TIME; + case TYPE_VARCHAR: return TPrimitiveType::VARCHAR; @@ -190,6 +196,9 @@ std::string type_to_string(PrimitiveType t) { case TYPE_DATETIME: return "DATETIME"; + case TYPE_TIME: + return "TIME"; + case TYPE_VARCHAR: return "VARCHAR"; diff --git a/be/src/runtime/primitive_type.h b/be/src/runtime/primitive_type.h index 3477671ae93472..b17de9c035c7bd 100644 --- a/be/src/runtime/primitive_type.h +++ b/be/src/runtime/primitive_type.h @@ -53,7 +53,9 @@ enum PrimitiveType { TYPE_ARRAY, /* 17 */ TYPE_MAP, /* 18 */ TYPE_HLL, /* 19 */ - TYPE_DECIMALV2 /* 20 */ + TYPE_DECIMALV2, /* 20 */ + + TYPE_TIME, /* 21 */ }; inline bool is_enumeration_type(PrimitiveType type) { @@ -121,6 +123,7 @@ inline int get_byte_size(PrimitiveType type) { case TYPE_DATETIME: case TYPE_DATE: case TYPE_DECIMALV2: + case TYPE_TIME: return 16; case TYPE_DECIMAL: @@ -159,6 +162,7 @@ inline int get_real_byte_size(PrimitiveType type) { case TYPE_DATETIME: case TYPE_DATE: case TYPE_DECIMALV2: + case TYPE_TIME: return 16; case TYPE_DECIMAL: diff --git a/be/src/runtime/raw_value.cpp b/be/src/runtime/raw_value.cpp index 3ffa79679a4a09..803eacba9cbc25 100644 --- a/be/src/runtime/raw_value.cpp +++ b/be/src/runtime/raw_value.cpp @@ -267,6 +267,7 @@ void RawValue::write(const void* value, void* dst, const TypeDescriptor& type, M break; } + case TYPE_TIME: case TYPE_DATE: case TYPE_DATETIME: *reinterpret_cast(dst) = diff --git a/be/src/runtime/result_writer.cpp b/be/src/runtime/result_writer.cpp index 5475df56204d36..dfab17b2438242 100644 --- a/be/src/runtime/result_writer.cpp +++ b/be/src/runtime/result_writer.cpp @@ -105,7 +105,8 @@ Status ResultWriter::add_one_row(TupleRow* row) { break; case TYPE_DATE: - case TYPE_DATETIME: { + case TYPE_DATETIME: + case TYPE_TIME: { char buf[64]; const DateTimeValue* time_val = (const DateTimeValue*)(item); // TODO(zhaochun), this function has core risk diff --git a/be/src/udf/udf.h b/be/src/udf/udf.h index 3e9a42fdcb1ad8..d1ae65d5595c88 100755 --- a/be/src/udf/udf.h +++ b/be/src/udf/udf.h @@ -554,6 +554,34 @@ struct DoubleVal : public AnyVal { } }; +struct TimeVal : public AnyVal { + int64_t time; + + TimeVal() : time(0) { } + TimeVal(int time) : time(time) { } + + static TimeVal null() { + TimeVal result; + result.is_null = true; + return result; + } + + bool operator==(const TimeVal& other) const { + if (is_null && other.is_null) { + return true; + } + + if (is_null || other.is_null) { + return false; + } + + return time == other.time; + } + bool operator!=(const TimeVal& other) const { + return !(*this == other); + } +}; + // This object has a compatible storage format with boost::ptime. struct DateTimeVal : public AnyVal { // MySQL packet time @@ -791,6 +819,7 @@ using doris_udf::StringVal; using doris_udf::DecimalVal; using doris_udf::DecimalV2Val; using doris_udf::DateTimeVal; +using doris_udf::TimeVal; using doris_udf::HllVal; using doris_udf::FunctionContext; diff --git a/fe/src/main/cup/sql_parser.cup b/fe/src/main/cup/sql_parser.cup index c1704043124d40..7720bc8645537b 100644 --- a/fe/src/main/cup/sql_parser.cup +++ b/fe/src/main/cup/sql_parser.cup @@ -195,7 +195,7 @@ terminal String KW_ADD, KW_ADMIN, KW_AFTER, KW_AGGREGATE, KW_ALL, KW_ALTER, KW_A KW_CANCEL, KW_CASE, KW_CAST, KW_CHAIN, KW_CHAR, KW_CHARSET, KW_CLUSTER, KW_CLUSTERS, KW_COLLATE, KW_COLLATION, KW_COLUMN, KW_COLUMNS, KW_COMMENT, KW_COMMIT, KW_COMMITTED, KW_CONFIG, KW_CONNECTION, KW_CONNECTION_ID, KW_CONSISTENT, KW_COUNT, KW_CREATE, KW_CROSS, KW_CURRENT, KW_CURRENT_USER, - KW_DATA, KW_DATABASE, KW_DATABASES, KW_DATE, KW_DATETIME, KW_DECIMAL, KW_DECOMMISSION, KW_DEFAULT, KW_DESC, KW_DESCRIBE, + KW_DATA, KW_DATABASE, KW_DATABASES, KW_DATE, KW_DATETIME, KW_TIME, KW_DECIMAL, KW_DECOMMISSION, KW_DEFAULT, KW_DESC, KW_DESCRIBE, KW_DELETE, KW_DISTINCT, KW_DISTINCTPC, KW_DISTINCTPCSA, KW_DISTRIBUTED, KW_DISTRIBUTION, KW_BUCKETS, KW_DIV, KW_DOUBLE, KW_DROP, KW_DROPP, KW_DUPLICATE, KW_ELSE, KW_END, KW_ENGINE, KW_ENGINES, KW_ENTER, KW_ERRORS, KW_EVENTS, KW_EXISTS, KW_EXPORT, KW_EXTERNAL, KW_EXTRACT, KW_FALSE, KW_FOLLOWER, KW_FOLLOWING, KW_FREE, KW_FROM, KW_FILE, KW_FIRST, KW_FLOAT, KW_FOR, KW_FORMAT, KW_FRONTEND, KW_FRONTENDS, KW_FULL, KW_FUNCTION, @@ -3202,6 +3202,8 @@ type ::= {: RESULT = Type.DATE; :} | KW_DATETIME {: RESULT = Type.DATETIME; :} + | KW_TIME + {: RESULT = Type.TIME; :} | KW_STRING {: RESULT = ScalarType.createVarcharType(-1); :} | KW_VARCHAR LPAREN INTEGER_LITERAL:len RPAREN diff --git a/fe/src/main/java/org/apache/doris/analysis/TimeLiteral.java b/fe/src/main/java/org/apache/doris/analysis/TimeLiteral.java new file mode 100644 index 00000000000000..46f6911bf38ae1 --- /dev/null +++ b/fe/src/main/java/org/apache/doris/analysis/TimeLiteral.java @@ -0,0 +1,146 @@ +// 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.doris.analysis; + +import org.apache.doris.catalog.PrimitiveType; +import org.apache.doris.catalog.Type; +import org.apache.doris.common.util.TimeUtils; +import org.apache.doris.thrift.TTimeLiteral; +import org.apache.doris.thrift.TExprNode; +import org.apache.doris.thrift.TExprNodeType; + +import com.google.common.base.Preconditions; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.nio.ByteBuffer; + +public class TimeLiteral extends LiteralExpr { + private static final Logger LOG = LogManager.getLogger(TimeLiteral.class); + private int time; + + private TimeLiteral() { + super(); + this.type = Type.TIME; + } + + public TimeLiteral(int time) { + super(); + this.time = time; + analysisDone(); + } + + protected TimeLiteral(TimeLiteral other) { + super(other); + time = other.time; + } + + @Override + public Expr clone() { + return new TimeLiteral(this); + } + + @Override + public boolean isMinValue() { + return this.time == TimeUtils.MIN_TIME; + } + + @Override + public Object getRealValue() { + return time; + } + + @Override + public ByteBuffer getHashValue(PrimitiveType type) { + String value = ""; + ByteBuffer buffer; + try { + buffer = ByteBuffer.wrap(value.getBytes("UTF-8")); + } catch (Exception e) { + throw new RuntimeException(e); + } + return buffer; + } + + @Override + public int compareLiteral(LiteralExpr expr) { + if (expr instanceof NullLiteral) { + return 1; + } + + if (expr == MaxLiteral.MAX_VALUE) { + return -1; + } + if (time == expr.getLongValue()) { + return 0; + } else { + return time > expr.getLongValue() ? 1 : -1; + } + } + + @Override + public String toSqlImpl() { + return "'" + getStringValue() + "'"; + } + + @Override + public String getStringValue() { + return String.valueOf(time); + } + + @Override + public long getLongValue() { + return time; + } + + @Override + public double getDoubleValue() { + return time; + } + + @Override + protected void toThrift(TExprNode msg) { + msg.node_type = TExprNodeType.TIME_LITERAL; + msg.time_literal = new TTimeLiteral(time); + } + + @Override + protected Expr uncheckedCastTo(Type targetType) { + if (targetType.isStringType()) { + return new StringLiteral(getStringValue()); + } + Preconditions.checkState(false); + return this; + } + + @Override + public void write(DataOutput out) throws IOException { + super.write(out); + out.writeInt(time); + } + + @Override + public void readFields(DataInput in) throws IOException { + super.readFields(in); + time = in.readInt(); + } +} diff --git a/fe/src/main/java/org/apache/doris/catalog/Function.java b/fe/src/main/java/org/apache/doris/catalog/Function.java index 30e5e63a6753b1..52814ad21b6043 100644 --- a/fe/src/main/java/org/apache/doris/catalog/Function.java +++ b/fe/src/main/java/org/apache/doris/catalog/Function.java @@ -457,6 +457,8 @@ public static String getUdfTypeName(PrimitiveType t) { case DATE: case DATETIME: return "datetime_val"; + case TIME: + return "time_val"; case DECIMAL: return "decimal_val"; case DECIMALV2: @@ -494,6 +496,8 @@ public static String getUdfType(PrimitiveType t) { case DATE: case DATETIME: return "DateTimeVal"; + case TIME: + return "TimeVal"; case DECIMAL: return "DecimalVal"; case DECIMALV2: diff --git a/fe/src/main/java/org/apache/doris/catalog/PrimitiveType.java b/fe/src/main/java/org/apache/doris/catalog/PrimitiveType.java index 1b3f3818a54450..30cd895b6bec82 100644 --- a/fe/src/main/java/org/apache/doris/catalog/PrimitiveType.java +++ b/fe/src/main/java/org/apache/doris/catalog/PrimitiveType.java @@ -43,6 +43,7 @@ public enum PrimitiveType { DOUBLE("DOUBLE", 8, TPrimitiveType.DOUBLE), DATE("DATE", 16, TPrimitiveType.DATE), DATETIME("DATETIME", 16, TPrimitiveType.DATETIME), + TIME("TIME", 16, TPrimitiveType.TIME), // Fixed length char array. CHAR("CHAR", 16, TPrimitiveType.CHAR), // 8-byte pointer and 4-byte length indicator (12 bytes total). @@ -75,6 +76,7 @@ public enum PrimitiveType { builder.put(NULL_TYPE, DOUBLE); builder.put(NULL_TYPE, DATE); builder.put(NULL_TYPE, DATETIME); + builder.put(NULL_TYPE, TIME); builder.put(NULL_TYPE, DECIMAL); builder.put(NULL_TYPE, DECIMALV2); builder.put(NULL_TYPE, CHAR); @@ -237,6 +239,7 @@ public enum PrimitiveType { builder.put(VARCHAR, DECIMALV2); builder.put(VARCHAR, VARCHAR); builder.put(VARCHAR, HLL); + builder.put(VARCHAR, TIME); // Decimal builder.put(DECIMAL, BOOLEAN); builder.put(DECIMAL, TINYINT); @@ -266,6 +269,10 @@ public enum PrimitiveType { builder.put(HLL, HLL); builder.put(HLL, VARCHAR); + //TIME + builder.put(TIME, TIME); + builder.put(TIME, VARCHAR); + implicitCastMap = builder.build(); } @@ -480,6 +487,7 @@ public static boolean isImplicitCast(PrimitiveType type, PrimitiveType target) { compatibilityMatrix[DECIMALV2.ordinal()][DECIMAL.ordinal()] = DECIMALV2; compatibilityMatrix[HLL.ordinal()][HLL.ordinal()] = HLL; + compatibilityMatrix[TIME.ordinal()][TIME.ordinal()] = TIME; } private static PrimitiveType[][] schemaChangeCompatibilityMatrix; @@ -659,6 +667,7 @@ public PrimitiveType getResultType() { case DATETIME: case CHAR: case VARCHAR: + case TIME: return VARCHAR; case DECIMAL: return DECIMAL; diff --git a/fe/src/main/java/org/apache/doris/catalog/ScalarFunction.java b/fe/src/main/java/org/apache/doris/catalog/ScalarFunction.java index 6be2cfb0cdf2a0..f5fbf4c2757b30 100644 --- a/fe/src/main/java/org/apache/doris/catalog/ScalarFunction.java +++ b/fe/src/main/java/org/apache/doris/catalog/ScalarFunction.java @@ -171,6 +171,9 @@ public static ScalarFunction createBuiltinOperator( case DATETIME: beFn += "_datetime_val"; break; + case TIME: + beFn += "_time_val"; + break; case DECIMAL: beFn += "_decimal_val"; usesDecimal = true; diff --git a/fe/src/main/java/org/apache/doris/catalog/ScalarType.java b/fe/src/main/java/org/apache/doris/catalog/ScalarType.java index 7e9ffd9428e857..5275907ca0e823 100644 --- a/fe/src/main/java/org/apache/doris/catalog/ScalarType.java +++ b/fe/src/main/java/org/apache/doris/catalog/ScalarType.java @@ -125,6 +125,8 @@ public static ScalarType createType(PrimitiveType type) { return DATE; case DATETIME: return DATETIME; + case TIME: + return TIME; case DECIMAL: return (ScalarType) createDecimalType(); case DECIMALV2: @@ -168,6 +170,8 @@ public static ScalarType createType(String type) { return DATE; case "DATETIME": return DATETIME; + case "TIME": + return TIME; case "DECIMAL": return (ScalarType) createDecimalType(); case "DECIMALV2": @@ -732,6 +736,8 @@ public int getStorageLayoutBytes() { return 3; case DATETIME: return 8; + case TIME: + return 3; case DECIMAL: return 40; case DECIMALV2: diff --git a/fe/src/main/java/org/apache/doris/catalog/Type.java b/fe/src/main/java/org/apache/doris/catalog/Type.java index 71c728898bf068..26619db2eff57c 100644 --- a/fe/src/main/java/org/apache/doris/catalog/Type.java +++ b/fe/src/main/java/org/apache/doris/catalog/Type.java @@ -62,6 +62,7 @@ public abstract class Type { public static final ScalarType DOUBLE = new ScalarType(PrimitiveType.DOUBLE); public static final ScalarType DATE = new ScalarType(PrimitiveType.DATE); public static final ScalarType DATETIME = new ScalarType(PrimitiveType.DATETIME); + public static final ScalarType TIME = new ScalarType(PrimitiveType.TIME); public static final ScalarType DEFAULT_DECIMAL = (ScalarType) ScalarType.createDecimalType(ScalarType.DEFAULT_PRECISION, ScalarType.DEFAULT_SCALE); @@ -116,6 +117,7 @@ public abstract class Type { supportedTypes.add(DATETIME); supportedTypes.add(DECIMAL); supportedTypes.add(DECIMALV2); + supportedTypes.add(TIME); } public static ArrayList getIntegerTypes() { @@ -460,6 +462,8 @@ public static Type fromPrimitiveType(PrimitiveType type) { return Type.DATE; case DATETIME: return Type.DATETIME; + case TIME: + return Type.TIME; case DECIMAL: return Type.DECIMAL; case DECIMALV2: @@ -857,6 +861,7 @@ public Integer getNumPrecRadix() { if (t1 == PrimitiveType.NULL_TYPE || t2 == PrimitiveType.NULL_TYPE) continue; if (t1 == PrimitiveType.DECIMAL || t2 == PrimitiveType.DECIMAL) continue; if (t1 == PrimitiveType.DECIMALV2 || t2 == PrimitiveType.DECIMALV2) continue; + if (t1 == PrimitiveType.TIME || t2 == PrimitiveType.TIME) continue; Preconditions.checkNotNull(compatibilityMatrix[i][j]); } } @@ -878,6 +883,7 @@ public Type getResultType() { return DOUBLE; case DATE: case DATETIME: + case TIME: case CHAR: case VARCHAR: case HLL: diff --git a/fe/src/main/java/org/apache/doris/common/util/TimeUtils.java b/fe/src/main/java/org/apache/doris/common/util/TimeUtils.java index f43a67995ca30b..19a50e3894dd14 100644 --- a/fe/src/main/java/org/apache/doris/common/util/TimeUtils.java +++ b/fe/src/main/java/org/apache/doris/common/util/TimeUtils.java @@ -63,6 +63,9 @@ public class TimeUtils { public static Date MIN_DATETIME = null; public static Date MAX_DATETIME = null; + public static int MIN_TIME; + public static int MAX_TIME; + static { TIME_ZONE = new SimpleTimeZone(8 * 3600 * 1000, ""); @@ -81,6 +84,13 @@ public class TimeUtils { MIN_DATETIME = DATETIME_FORMAT.parse("1900-01-01 00:00:00"); MAX_DATETIME = DATETIME_FORMAT.parse("9999-12-31 23:59:59"); + + int TIME_MAX_HOUR = 838; + int TIME_MAX_MINUTE = 59; + int TIME_MAX_SECOND = 59; + MAX_TIME = 10000 * TIME_MAX_HOUR + 100 * TIME_MAX_MINUTE + TIME_MAX_SECOND; + MIN_TIME = -1 * MAX_TIME; + } catch (ParseException e) { LOG.error("invalid date format", e); System.exit(-1); diff --git a/fe/src/main/java/org/apache/doris/rewrite/FEFunctions.java b/fe/src/main/java/org/apache/doris/rewrite/FEFunctions.java index 348a47b5ab6b3a..25f307b81520db 100644 --- a/fe/src/main/java/org/apache/doris/rewrite/FEFunctions.java +++ b/fe/src/main/java/org/apache/doris/rewrite/FEFunctions.java @@ -24,12 +24,14 @@ import org.apache.doris.analysis.LargeIntLiteral; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.StringLiteral; +import org.apache.doris.analysis.TimeLiteral; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import com.google.common.base.Preconditions; import org.apache.commons.lang.time.DateFormatUtils; import org.apache.commons.lang.time.DateUtils; +import org.apache.doris.common.util.TimeUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.joda.time.format.DateTimeFormatter; @@ -53,6 +55,16 @@ public class FEFunctions { /** * date and time function */ + @FEFunction(name = "timediff", argTypes = { "DATETIME", "DATETIME" }, returnType = "TIME") + public static TimeLiteral timeDiff(LiteralExpr first, LiteralExpr second) throws AnalysisException { + long timediff = getTime(first) - getTime(second); + if(timediff < TimeUtils.MIN_TIME) { + timediff = TimeUtils.MIN_TIME; + } else if(timediff > TimeUtils.MAX_TIME) { + timediff = TimeUtils.MAX_TIME; + } + return new TimeLiteral((int) timediff); + } @FEFunction(name = "datediff", argTypes = { "DATETIME", "DATETIME" }, returnType = "INT") public static IntLiteral dateDiff(LiteralExpr first, LiteralExpr second) throws AnalysisException { diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py index df8b64176082fb..91bbf531b00510 100755 --- a/gensrc/script/doris_builtins_functions.py +++ b/gensrc/script/doris_builtins_functions.py @@ -198,7 +198,7 @@ [['datediff'], 'INT', ['DATETIME', 'DATETIME'], '_ZN5doris18TimestampFunctions9date_diffEPN9doris_udf' '15FunctionContextERKNS1_11DateTimeValES6_'], - [['timediff'], 'DATETIME', ['DATETIME', 'DATETIME'], + [['timediff'], 'TIME', ['DATETIME', 'DATETIME'], '_ZN5doris18TimestampFunctions9time_diffEPN9doris_udf' '15FunctionContextERKNS1_11DateTimeValES6_'], diff --git a/gensrc/script/gen_functions.py b/gensrc/script/gen_functions.py index fd3027c494db26..4a528e0353f8ee 100755 --- a/gensrc/script/gen_functions.py +++ b/gensrc/script/gen_functions.py @@ -520,6 +520,7 @@ 'VARCHAR': 'StringValue', 'DATE': 'Date', 'DATETIME': 'DateTime', + 'TIME': 'Time', 'DECIMAL': 'DecimalValue', 'DECIMALV2': 'DecimalV2Value', } @@ -537,6 +538,7 @@ 'VARCHAR': 'StringValue', 'DATE': 'DateTimeValue', 'DATETIME': 'DateTimeValue', + 'TIME': 'TimeValue', 'DECIMAL': 'DecimalValue', 'DECIMALV2': 'DecimalV2Value', } @@ -552,6 +554,7 @@ 'VARCHAR': 'string_val', 'DATE': 'datetime_val', 'DATETIME': 'datetime_val', + 'TIME': 'datetime_val', 'DECIMAL': 'decimal_val', 'DECIMALV2': 'decimalv2_val', } diff --git a/gensrc/script/gen_opcodes.py b/gensrc/script/gen_opcodes.py index 48bff40d9d28c2..0a4770abce0b4b 100755 --- a/gensrc/script/gen_opcodes.py +++ b/gensrc/script/gen_opcodes.py @@ -62,6 +62,7 @@ 'DATETIME': 'DateTime', 'DECIMAL': 'DecimalValue', 'DECIMALV2': 'DecimalV2Value', + 'TIME': 'Time' } thrift_preamble = '\ diff --git a/gensrc/thrift/Exprs.thrift b/gensrc/thrift/Exprs.thrift index 281e37abab7591..7b890881176c63 100644 --- a/gensrc/thrift/Exprs.thrift +++ b/gensrc/thrift/Exprs.thrift @@ -47,6 +47,7 @@ enum TExprNodeType { // TODO: old style compute functions. this will be deprecated COMPUTE_FUNCTION_CALL, LARGE_INT_LITERAL, + TIME_LITERAL, } //enum TAggregationOp { @@ -83,6 +84,10 @@ struct TDateLiteral { 1: required string value } +struct TTimeLiteral { + 1: required i32 value +} + struct TFloatLiteral { 1: required double value } @@ -178,6 +183,8 @@ struct TExprNode { // If set, child[vararg_start_idx] is the first vararg child. 27: optional i32 vararg_start_idx 28: optional Types.TPrimitiveType child_type + + 29: optional TTimeLiteral time_literal } // A flattened representation of a tree of Expr nodes, obtained by depth-first diff --git a/gensrc/thrift/Types.thrift b/gensrc/thrift/Types.thrift index 262e6416311be7..b661bad5f5591f 100644 --- a/gensrc/thrift/Types.thrift +++ b/gensrc/thrift/Types.thrift @@ -72,7 +72,8 @@ enum TPrimitiveType { LARGEINT, VARCHAR, HLL, - DECIMALV2 + DECIMALV2, + TIME } enum TTypeNodeType { @@ -145,7 +146,7 @@ enum TTaskType { STORAGE_MEDIUM_MIGRATE, ROLLUP, SCHEMA_CHANGE, - CANCEL_DELETE, + CANCEL_DELETE, // Deprecated MAKE_SNAPSHOT, RELEASE_SNAPSHOT, CHECK_CONSISTENCY, @@ -158,7 +159,8 @@ enum TTaskType { CLEAR_ALTER_TASK, CLEAR_TRANSACTION_TASK, RECOVER_TABLET, - STREAM_LOAD + STREAM_LOAD, + UPDATE_TABLET_META_INFO } enum TStmtType {