1+ // Licensed to the Apache Software Foundation (ASF) under one
2+ // or more contributor license agreements. See the NOTICE file
3+ // distributed with this work for additional information
4+ // regarding copyright ownership. The ASF licenses this file
5+ // to you under the Apache License, Version 2.0 (the
6+ // "License"); you may not use this file except in compliance
7+ // with the License. You may obtain a copy of the License at
8+ //
9+ // http://www.apache.org/licenses/LICENSE-2.0
10+ //
11+ // Unless required by applicable law or agreed to in writing,
12+ // software distributed under the License is distributed on an
13+ // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+ // KIND, either express or implied. See the License for the
15+ // specific language governing permissions and limitations
16+ // under the License.
17+
18+ #include < mysql/binary_log_types.h>
19+
20+ #include < string>
21+
22+ #include " common/status.h"
23+ #include " runtime/define_primitive_type.h"
24+ #include " runtime/descriptors.h"
25+ #include " runtime/primitive_type.h"
26+ #include " runtime/runtime_state.h"
27+ #include " util/binary_cast.hpp"
28+ #include " vec/columns/column_const.h"
29+ #include " vec/columns/column_nullable.h"
30+ #include " vec/core/column_with_type_and_name.h"
31+ #include " vec/data_types/data_type_nullable.h"
32+ #include " vec/data_types/serde/data_type_serde.h"
33+ #include " vec/functions/function.h"
34+ #include " vec/functions/simple_function_factory.h"
35+ #include " vec/runtime/vdatetime_value.h"
36+
37+ namespace doris ::vectorized {
38+ #include " common/compile_check_begin.h"
39+
40+ class FunctionDefault : public IFunction {
41+ public:
42+ static constexpr auto name = " default" ;
43+ static FunctionPtr create () { return std::make_shared<FunctionDefault>(); }
44+ String get_name () const override { return name; }
45+ size_t get_number_of_arguments () const override { return 1 ; }
46+
47+ DataTypePtr get_return_type_impl (const DataTypes& arguments) const override {
48+ return make_nullable (arguments[0 ]);
49+ }
50+
51+ bool use_default_implementation_for_nulls () const override { return false ; }
52+
53+ Status execute_impl (FunctionContext* context, Block& block, const ColumnNumbers& arguments,
54+ uint32_t result, size_t input_rows_count) const override {
55+ ColumnWithTypeAndName& result_info = block.get_by_position (result);
56+ auto res_nested_type = remove_nullable (result_info.type );
57+ PrimitiveType res_primitive_type = res_nested_type->get_primitive_type ();
58+
59+ ColumnWithTypeAndName& input_column_info = block.get_by_position (arguments[0 ]);
60+ const std::string& col_name = input_column_info.name ;
61+
62+ std::string default_value;
63+ bool has_default_value = false ;
64+ bool is_nullable = true ;
65+ get_default_value_and_nullable_for_col (context, col_name, default_value, has_default_value,
66+ is_nullable);
67+
68+ // For date types, if the default value is `CURRENT_TIMESTAMP` or `CURRENT_DATE`.
69+ // Reference the behavior in MySQL:
70+ // if column is NULLABLE, return all NULLs
71+ // else return zero datetime values like `0000-00-00 00:00:00` or `0000-00-00`
72+ if (is_date_type (res_primitive_type) && has_default_value &&
73+ (default_value == " CURRENT_TIMESTAMP" || default_value == " CURRENT_DATE" )) {
74+ if (is_nullable) {
75+ return return_with_all_null (block, result, res_nested_type, input_rows_count);
76+ } else {
77+ return return_with_zero_datetime (block, result, res_nested_type, res_primitive_type,
78+ input_rows_count);
79+ }
80+ }
81+
82+ // For some complex types, only accept NULL as default value
83+ if (is_complex_type (res_primitive_type) || res_primitive_type == TYPE_JSONB ||
84+ res_primitive_type == TYPE_VARIANT) {
85+ if (is_nullable) {
86+ return return_with_all_null (block, result, res_nested_type, input_rows_count);
87+ } else {
88+ return Status::InvalidArgument (
89+ " Column '{}' of type '{}' must be nullable to use DEFAULT" , col_name,
90+ res_nested_type->get_name ());
91+ }
92+ }
93+
94+ // 1. specified default value when creating table -> default_value
95+ // 2. no specified default value && column is NOT NULL -> error
96+ // 3. no specified default value && column is NULLABLE -> NULL
97+ if (has_default_value) {
98+ MutableColumnPtr res_col = res_nested_type->create_column ();
99+ auto null_map = ColumnUInt8::create (input_rows_count, 0 );
100+ Field default_field;
101+
102+ auto temp_column = res_nested_type->create_column ();
103+ auto serde = res_nested_type->get_serde ();
104+ StringRef default_str_ref (default_value.data (), default_value.size ());
105+ DataTypeSerDe::FormatOptions options;
106+ Status parse_status = serde->from_string (default_str_ref, *temp_column, options);
107+
108+ if (parse_status.ok () && temp_column->size () > 0 ) {
109+ temp_column->get (0 , default_field);
110+ }
111+
112+ for (size_t i = 0 ; i < input_rows_count; ++i) {
113+ res_col->insert (default_field);
114+ }
115+ block.replace_by_position (
116+ result, ColumnNullable::create (std::move (res_col), std::move (null_map)));
117+ return Status::OK ();
118+ } else {
119+ if (is_nullable) {
120+ return return_with_all_null (block, result, res_nested_type, input_rows_count);
121+ } else {
122+ return Status::InvalidArgument (" Column '{}' is NOT NULL but has no default value" ,
123+ col_name);
124+ }
125+ }
126+ return Status::OK ();
127+ }
128+
129+ private:
130+ void get_default_value_and_nullable_for_col (FunctionContext* context,
131+ const std::string& column_name,
132+ std::string& default_value, bool & has_default_value,
133+ bool & is_nullable) const {
134+ RuntimeState* state = context->state ();
135+ const DescriptorTbl& desc_tbl = state->desc_tbl ();
136+
137+ SlotDescriptor* target_slot = nullptr ;
138+ for (auto * tuple_desc : desc_tbl.get_tuple_descs ()) {
139+ for (auto * slot : tuple_desc->slots ()) {
140+ if (slot->col_name () == column_name) {
141+ target_slot = slot;
142+ break ;
143+ }
144+ }
145+ if (target_slot) {
146+ break ;
147+ }
148+ }
149+
150+ if (target_slot) {
151+ is_nullable = target_slot->is_nullable ();
152+ default_value = target_slot->col_default_value ();
153+ has_default_value = target_slot->has_default_value ();
154+ }
155+ }
156+
157+ static Status return_with_all_null (Block& block, uint32_t result,
158+ const DataTypePtr& nested_type, size_t input_rows_count) {
159+ MutableColumnPtr res_col = nested_type->create_column ();
160+ res_col->insert_many_defaults (input_rows_count);
161+ auto null_map = ColumnUInt8::create (input_rows_count, 1 );
162+ block.replace_by_position (result,
163+ ColumnNullable::create (std::move (res_col), std::move (null_map)));
164+ return Status::OK ();
165+ }
166+
167+ static Status return_with_zero_datetime (Block& block, uint32_t result,
168+ const DataTypePtr& nested_type,
169+ PrimitiveType primitive_type, size_t input_rows_count) {
170+ MutableColumnPtr res_col = nested_type->create_column ();
171+
172+ switch (primitive_type) {
173+ case TYPE_DATE:
174+ case TYPE_DATETIME:
175+ insert_min_datetime_values<TYPE_DATETIME>(res_col, input_rows_count);
176+ break ;
177+ case TYPE_DATEV2:
178+ insert_min_datetime_values<TYPE_DATEV2>(res_col, input_rows_count);
179+ break ;
180+ case TYPE_DATETIMEV2:
181+ insert_min_datetime_values<TYPE_DATETIMEV2>(res_col, input_rows_count);
182+ break ;
183+ default :
184+ return Status::InternalError (" Unsupported date/time type for zero datetime: {}" ,
185+ nested_type->get_name ());
186+ }
187+
188+ auto null_map = ColumnUInt8::create (input_rows_count, 0 );
189+ block.replace_by_position (result,
190+ ColumnNullable::create (std::move (res_col), std::move (null_map)));
191+ return Status::OK ();
192+ }
193+
194+ template <PrimitiveType Type>
195+ static void insert_min_datetime_values (MutableColumnPtr& res_col, size_t count) {
196+ using ItemType = typename PrimitiveTypeTraits<Type>::ColumnItemType;
197+ ItemType min_value;
198+
199+ if constexpr (Type == TYPE_DATE || Type == TYPE_DATETIME) {
200+ min_value =
201+ binary_cast<VecDateTimeValue, ItemType>(VecDateTimeValue::datetime_min_value ());
202+ } else if constexpr (Type == TYPE_DATEV2) {
203+ min_value = MIN_DATE_V2;
204+ } else if constexpr (Type == TYPE_DATETIMEV2) {
205+ min_value = MIN_DATETIME_V2;
206+ }
207+
208+ for (size_t i = 0 ; i < count; ++i) {
209+ res_col->insert_data (reinterpret_cast <const char *>(&min_value), sizeof (ItemType));
210+ }
211+ }
212+ };
213+ #include " common/compile_check_end.h"
214+
215+ void register_function_default (SimpleFunctionFactory& factory) {
216+ factory.register_function <FunctionDefault>();
217+ }
218+ } // namespace doris::vectorized
0 commit comments