Line | Count | Source |
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 <glog/logging.h> |
19 | | |
20 | | #include <algorithm> |
21 | | #include <cstdlib> |
22 | | #include <memory> |
23 | | #include <string> |
24 | | #include <string_view> |
25 | | #include <tuple> |
26 | | #include <type_traits> |
27 | | #include <utility> |
28 | | #include <variant> |
29 | | |
30 | | #include "common/compiler_util.h" // IWYU pragma: keep |
31 | | #include "common/status.h" |
32 | | #include "core/assert_cast.h" |
33 | | #include "core/block/block.h" |
34 | | #include "core/block/column_numbers.h" |
35 | | #include "core/block/column_with_type_and_name.h" |
36 | | #include "core/column/column.h" |
37 | | #include "core/column/column_array.h" |
38 | | #include "core/column/column_const.h" |
39 | | #include "core/column/column_nullable.h" |
40 | | #include "core/column/column_string.h" |
41 | | #include "core/column/column_vector.h" |
42 | | #include "core/custom_allocator.h" |
43 | | #include "core/data_type/data_type.h" |
44 | | #include "core/data_type/data_type_array.h" |
45 | | #include "core/data_type/data_type_jsonb.h" |
46 | | #include "core/data_type/data_type_nullable.h" |
47 | | #include "core/data_type/data_type_string.h" |
48 | | #include "core/data_type/define_primitive_type.h" |
49 | | #include "core/data_type/primitive_type.h" |
50 | | #include "core/string_ref.h" |
51 | | #include "core/types.h" |
52 | | #include "core/value/jsonb_value.h" |
53 | | #include "exec/common/stringop_substring.h" |
54 | | #include "exec/common/template_helpers.hpp" |
55 | | #include "exec/common/util.hpp" |
56 | | #include "exprs/aggregate/aggregate_function.h" |
57 | | #include "exprs/function/function.h" |
58 | | #include "exprs/function/like.h" |
59 | | #include "exprs/function/simple_function_factory.h" |
60 | | #include "exprs/function_context.h" |
61 | | #include "util/jsonb_document.h" |
62 | | #include "util/jsonb_stream.h" |
63 | | #include "util/jsonb_utils.h" |
64 | | #include "util/jsonb_writer.h" |
65 | | #include "util/simd/bits.h" |
66 | | |
67 | | namespace doris { |
68 | | |
69 | | enum class NullalbeMode { NULLABLE = 0, FOLLOW_INPUT }; |
70 | | |
71 | | enum class JsonbParseErrorMode { FAIL = 0, RETURN_NULL, RETURN_VALUE }; |
72 | | |
73 | | // func(string,string) -> json |
74 | | template <NullalbeMode nullable_mode, JsonbParseErrorMode parse_error_handle_mode> |
75 | | class FunctionJsonbParseBase : public IFunction { |
76 | | private: |
77 | | struct FunctionJsonbParseState { |
78 | | StringRef default_value; |
79 | | JsonBinaryValue default_value_parser; |
80 | | bool has_const_default_value = false; |
81 | | bool default_is_null = false; |
82 | | }; |
83 | | |
84 | | public: |
85 | | static constexpr auto name = "json_parse"; |
86 | | static constexpr auto alias = "jsonb_parse"; |
87 | 17 | static FunctionPtr create() { return std::make_shared<FunctionJsonbParseBase>(); }_ZN5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE0EE6createEv Line | Count | Source | 87 | 9 | static FunctionPtr create() { return std::make_shared<FunctionJsonbParseBase>(); } |
_ZN5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE0ELNS_19JsonbParseErrorModeE1EE6createEv Line | Count | Source | 87 | 3 | static FunctionPtr create() { return std::make_shared<FunctionJsonbParseBase>(); } |
_ZN5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE2EE6createEv Line | Count | Source | 87 | 5 | static FunctionPtr create() { return std::make_shared<FunctionJsonbParseBase>(); } |
|
88 | | |
89 | 4 | String get_name() const override { |
90 | 4 | String error_mode; |
91 | 4 | switch (parse_error_handle_mode) { |
92 | 1 | case JsonbParseErrorMode::FAIL: |
93 | 1 | break; |
94 | 1 | case JsonbParseErrorMode::RETURN_NULL: |
95 | 1 | error_mode = "_error_to_null"; |
96 | 1 | break; |
97 | 2 | case JsonbParseErrorMode::RETURN_VALUE: |
98 | 2 | error_mode = "_error_to_value"; |
99 | 2 | break; |
100 | 4 | } |
101 | | |
102 | 4 | return name + error_mode; |
103 | 4 | } _ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE0EE8get_nameB5cxx11Ev Line | Count | Source | 89 | 1 | String get_name() const override { | 90 | 1 | String error_mode; | 91 | 1 | switch (parse_error_handle_mode) { | 92 | 1 | case JsonbParseErrorMode::FAIL: | 93 | 1 | break; | 94 | 0 | case JsonbParseErrorMode::RETURN_NULL: | 95 | 0 | error_mode = "_error_to_null"; | 96 | 0 | break; | 97 | 0 | case JsonbParseErrorMode::RETURN_VALUE: | 98 | 0 | error_mode = "_error_to_value"; | 99 | 0 | break; | 100 | 1 | } | 101 | | | 102 | 1 | return name + error_mode; | 103 | 1 | } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE0ELNS_19JsonbParseErrorModeE1EE8get_nameB5cxx11Ev Line | Count | Source | 89 | 1 | String get_name() const override { | 90 | 1 | String error_mode; | 91 | 1 | switch (parse_error_handle_mode) { | 92 | 0 | case JsonbParseErrorMode::FAIL: | 93 | 0 | break; | 94 | 1 | case JsonbParseErrorMode::RETURN_NULL: | 95 | 1 | error_mode = "_error_to_null"; | 96 | 1 | break; | 97 | 0 | case JsonbParseErrorMode::RETURN_VALUE: | 98 | 0 | error_mode = "_error_to_value"; | 99 | 0 | break; | 100 | 1 | } | 101 | | | 102 | 1 | return name + error_mode; | 103 | 1 | } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE2EE8get_nameB5cxx11Ev Line | Count | Source | 89 | 2 | String get_name() const override { | 90 | 2 | String error_mode; | 91 | 2 | switch (parse_error_handle_mode) { | 92 | 0 | case JsonbParseErrorMode::FAIL: | 93 | 0 | break; | 94 | 0 | case JsonbParseErrorMode::RETURN_NULL: | 95 | 0 | error_mode = "_error_to_null"; | 96 | 0 | break; | 97 | 2 | case JsonbParseErrorMode::RETURN_VALUE: | 98 | 2 | error_mode = "_error_to_value"; | 99 | 2 | break; | 100 | 2 | } | 101 | | | 102 | 2 | return name + error_mode; | 103 | 2 | } |
|
104 | | |
105 | 15 | bool is_variadic() const override { |
106 | 15 | return parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE; |
107 | 15 | } _ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE0EE11is_variadicEv Line | Count | Source | 105 | 8 | bool is_variadic() const override { | 106 | 8 | return parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE; | 107 | 8 | } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE0ELNS_19JsonbParseErrorModeE1EE11is_variadicEv Line | Count | Source | 105 | 2 | bool is_variadic() const override { | 106 | 2 | return parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE; | 107 | 2 | } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE2EE11is_variadicEv Line | Count | Source | 105 | 5 | bool is_variadic() const override { | 106 | 5 | return parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE; | 107 | 5 | } |
|
108 | | |
109 | 9 | size_t get_number_of_arguments() const override { |
110 | 9 | switch (parse_error_handle_mode) { |
111 | 7 | case JsonbParseErrorMode::FAIL: |
112 | 7 | return 1; |
113 | 1 | case JsonbParseErrorMode::RETURN_NULL: |
114 | 1 | return 1; |
115 | 1 | case JsonbParseErrorMode::RETURN_VALUE: |
116 | 1 | return 0; |
117 | 9 | } |
118 | 9 | } _ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE0EE23get_number_of_argumentsEv Line | Count | Source | 109 | 7 | size_t get_number_of_arguments() const override { | 110 | 7 | switch (parse_error_handle_mode) { | 111 | 7 | case JsonbParseErrorMode::FAIL: | 112 | 7 | return 1; | 113 | 0 | case JsonbParseErrorMode::RETURN_NULL: | 114 | 0 | return 1; | 115 | 0 | case JsonbParseErrorMode::RETURN_VALUE: | 116 | 0 | return 0; | 117 | 7 | } | 118 | 7 | } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE0ELNS_19JsonbParseErrorModeE1EE23get_number_of_argumentsEv Line | Count | Source | 109 | 1 | size_t get_number_of_arguments() const override { | 110 | 1 | switch (parse_error_handle_mode) { | 111 | 0 | case JsonbParseErrorMode::FAIL: | 112 | 0 | return 1; | 113 | 1 | case JsonbParseErrorMode::RETURN_NULL: | 114 | 1 | return 1; | 115 | 0 | case JsonbParseErrorMode::RETURN_VALUE: | 116 | 0 | return 0; | 117 | 1 | } | 118 | 1 | } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE2EE23get_number_of_argumentsEv Line | Count | Source | 109 | 1 | size_t get_number_of_arguments() const override { | 110 | 1 | switch (parse_error_handle_mode) { | 111 | 0 | case JsonbParseErrorMode::FAIL: | 112 | 0 | return 1; | 113 | 0 | case JsonbParseErrorMode::RETURN_NULL: | 114 | 0 | return 1; | 115 | 1 | case JsonbParseErrorMode::RETURN_VALUE: | 116 | 1 | return 0; | 117 | 1 | } | 118 | 1 | } |
|
119 | | |
120 | 11 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
121 | 11 | bool is_nullable = false; |
122 | 11 | switch (nullable_mode) { |
123 | 1 | case NullalbeMode::NULLABLE: |
124 | 1 | is_nullable = true; |
125 | 1 | break; |
126 | 10 | case NullalbeMode::FOLLOW_INPUT: { |
127 | 14 | for (auto arg : arguments) { |
128 | 14 | is_nullable |= arg->is_nullable(); |
129 | 14 | } |
130 | 10 | break; |
131 | 0 | } |
132 | 11 | } |
133 | | |
134 | 11 | return is_nullable ? make_nullable(std::make_shared<DataTypeJsonb>()) |
135 | 11 | : std::make_shared<DataTypeJsonb>(); |
136 | 11 | } _ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE0EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS8_EE Line | Count | Source | 120 | 7 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { | 121 | 7 | bool is_nullable = false; | 122 | 7 | switch (nullable_mode) { | 123 | 0 | case NullalbeMode::NULLABLE: | 124 | 0 | is_nullable = true; | 125 | 0 | break; | 126 | 7 | case NullalbeMode::FOLLOW_INPUT: { | 127 | 7 | for (auto arg : arguments) { | 128 | 7 | is_nullable |= arg->is_nullable(); | 129 | 7 | } | 130 | 7 | break; | 131 | 0 | } | 132 | 7 | } | 133 | | | 134 | 7 | return is_nullable ? make_nullable(std::make_shared<DataTypeJsonb>()) | 135 | 7 | : std::make_shared<DataTypeJsonb>(); | 136 | 7 | } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE0ELNS_19JsonbParseErrorModeE1EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS8_EE Line | Count | Source | 120 | 1 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { | 121 | 1 | bool is_nullable = false; | 122 | 1 | switch (nullable_mode) { | 123 | 1 | case NullalbeMode::NULLABLE: | 124 | 1 | is_nullable = true; | 125 | 1 | break; | 126 | 0 | case NullalbeMode::FOLLOW_INPUT: { | 127 | 0 | for (auto arg : arguments) { | 128 | 0 | is_nullable |= arg->is_nullable(); | 129 | 0 | } | 130 | 0 | break; | 131 | 0 | } | 132 | 1 | } | 133 | | | 134 | 1 | return is_nullable ? make_nullable(std::make_shared<DataTypeJsonb>()) | 135 | 1 | : std::make_shared<DataTypeJsonb>(); | 136 | 1 | } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE2EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS8_EE Line | Count | Source | 120 | 3 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { | 121 | 3 | bool is_nullable = false; | 122 | 3 | switch (nullable_mode) { | 123 | 0 | case NullalbeMode::NULLABLE: | 124 | 0 | is_nullable = true; | 125 | 0 | break; | 126 | 3 | case NullalbeMode::FOLLOW_INPUT: { | 127 | 7 | for (auto arg : arguments) { | 128 | 7 | is_nullable |= arg->is_nullable(); | 129 | 7 | } | 130 | 3 | break; | 131 | 0 | } | 132 | 3 | } | 133 | | | 134 | 3 | return is_nullable ? make_nullable(std::make_shared<DataTypeJsonb>()) | 135 | 3 | : std::make_shared<DataTypeJsonb>(); | 136 | 3 | } |
|
137 | | |
138 | 21 | bool use_default_implementation_for_nulls() const override { return false; }_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE0EE36use_default_implementation_for_nullsEv Line | Count | Source | 138 | 14 | bool use_default_implementation_for_nulls() const override { return false; } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE0ELNS_19JsonbParseErrorModeE1EE36use_default_implementation_for_nullsEv Line | Count | Source | 138 | 2 | bool use_default_implementation_for_nulls() const override { return false; } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE2EE36use_default_implementation_for_nullsEv Line | Count | Source | 138 | 5 | bool use_default_implementation_for_nulls() const override { return false; } |
|
139 | | |
140 | 20 | Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override { |
141 | 20 | if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) { |
142 | 10 | std::shared_ptr<FunctionJsonbParseState> state = |
143 | 10 | std::make_shared<FunctionJsonbParseState>(); |
144 | 10 | context->set_function_state(FunctionContext::FRAGMENT_LOCAL, state); |
145 | 10 | } |
146 | 20 | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE) { |
147 | 4 | if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) { |
148 | 2 | auto* state = reinterpret_cast<FunctionJsonbParseState*>( |
149 | 2 | context->get_function_state(FunctionContext::FRAGMENT_LOCAL)); |
150 | 2 | if (state) { |
151 | 2 | if (context->get_num_args() == 2) { |
152 | 1 | if (context->is_col_constant(1)) { |
153 | 0 | const auto default_value_col = context->get_constant_col(1)->column_ptr; |
154 | 0 | if (default_value_col->is_null_at(0)) { |
155 | 0 | state->default_is_null = true; |
156 | 0 | } else { |
157 | 0 | const auto& default_value = default_value_col->get_data_at(0); |
158 | |
|
159 | 0 | state->default_value = default_value; |
160 | 0 | state->has_const_default_value = true; |
161 | 0 | } |
162 | 0 | } |
163 | 1 | } else if (context->get_num_args() == 1) { |
164 | 0 | RETURN_IF_ERROR( |
165 | 0 | state->default_value_parser.from_json_string(std::string("{}"))); |
166 | 0 | state->default_value = StringRef(state->default_value_parser.value(), |
167 | 0 | state->default_value_parser.size()); |
168 | 0 | state->has_const_default_value = true; |
169 | 0 | } |
170 | 2 | } |
171 | 2 | } |
172 | | |
173 | 4 | if (context->get_num_args() != 1 && context->get_num_args() != 2) { |
174 | 1 | return Status::InvalidArgument( |
175 | 1 | "{} function should have 1 or 2 arguments, " |
176 | 1 | "but got {}", |
177 | 1 | get_name(), context->get_num_args()); |
178 | 1 | } |
179 | 4 | } |
180 | 3 | return Status::OK(); |
181 | 20 | } _ZN5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE0EE4openEPNS_15FunctionContextENS4_18FunctionStateScopeE Line | Count | Source | 140 | 14 | Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override { | 141 | 14 | if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) { | 142 | 7 | std::shared_ptr<FunctionJsonbParseState> state = | 143 | 7 | std::make_shared<FunctionJsonbParseState>(); | 144 | 7 | context->set_function_state(FunctionContext::FRAGMENT_LOCAL, state); | 145 | 7 | } | 146 | | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE) { | 147 | | if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) { | 148 | | auto* state = reinterpret_cast<FunctionJsonbParseState*>( | 149 | | context->get_function_state(FunctionContext::FRAGMENT_LOCAL)); | 150 | | if (state) { | 151 | | if (context->get_num_args() == 2) { | 152 | | if (context->is_col_constant(1)) { | 153 | | const auto default_value_col = context->get_constant_col(1)->column_ptr; | 154 | | if (default_value_col->is_null_at(0)) { | 155 | | state->default_is_null = true; | 156 | | } else { | 157 | | const auto& default_value = default_value_col->get_data_at(0); | 158 | | | 159 | | state->default_value = default_value; | 160 | | state->has_const_default_value = true; | 161 | | } | 162 | | } | 163 | | } else if (context->get_num_args() == 1) { | 164 | | RETURN_IF_ERROR( | 165 | | state->default_value_parser.from_json_string(std::string("{}"))); | 166 | | state->default_value = StringRef(state->default_value_parser.value(), | 167 | | state->default_value_parser.size()); | 168 | | state->has_const_default_value = true; | 169 | | } | 170 | | } | 171 | | } | 172 | | | 173 | | if (context->get_num_args() != 1 && context->get_num_args() != 2) { | 174 | | return Status::InvalidArgument( | 175 | | "{} function should have 1 or 2 arguments, " | 176 | | "but got {}", | 177 | | get_name(), context->get_num_args()); | 178 | | } | 179 | | } | 180 | 14 | return Status::OK(); | 181 | 14 | } |
_ZN5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE0ELNS_19JsonbParseErrorModeE1EE4openEPNS_15FunctionContextENS4_18FunctionStateScopeE Line | Count | Source | 140 | 2 | Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override { | 141 | 2 | if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) { | 142 | 1 | std::shared_ptr<FunctionJsonbParseState> state = | 143 | 1 | std::make_shared<FunctionJsonbParseState>(); | 144 | 1 | context->set_function_state(FunctionContext::FRAGMENT_LOCAL, state); | 145 | 1 | } | 146 | | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE) { | 147 | | if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) { | 148 | | auto* state = reinterpret_cast<FunctionJsonbParseState*>( | 149 | | context->get_function_state(FunctionContext::FRAGMENT_LOCAL)); | 150 | | if (state) { | 151 | | if (context->get_num_args() == 2) { | 152 | | if (context->is_col_constant(1)) { | 153 | | const auto default_value_col = context->get_constant_col(1)->column_ptr; | 154 | | if (default_value_col->is_null_at(0)) { | 155 | | state->default_is_null = true; | 156 | | } else { | 157 | | const auto& default_value = default_value_col->get_data_at(0); | 158 | | | 159 | | state->default_value = default_value; | 160 | | state->has_const_default_value = true; | 161 | | } | 162 | | } | 163 | | } else if (context->get_num_args() == 1) { | 164 | | RETURN_IF_ERROR( | 165 | | state->default_value_parser.from_json_string(std::string("{}"))); | 166 | | state->default_value = StringRef(state->default_value_parser.value(), | 167 | | state->default_value_parser.size()); | 168 | | state->has_const_default_value = true; | 169 | | } | 170 | | } | 171 | | } | 172 | | | 173 | | if (context->get_num_args() != 1 && context->get_num_args() != 2) { | 174 | | return Status::InvalidArgument( | 175 | | "{} function should have 1 or 2 arguments, " | 176 | | "but got {}", | 177 | | get_name(), context->get_num_args()); | 178 | | } | 179 | | } | 180 | 2 | return Status::OK(); | 181 | 2 | } |
_ZN5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE2EE4openEPNS_15FunctionContextENS4_18FunctionStateScopeE Line | Count | Source | 140 | 4 | Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override { | 141 | 4 | if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) { | 142 | 2 | std::shared_ptr<FunctionJsonbParseState> state = | 143 | 2 | std::make_shared<FunctionJsonbParseState>(); | 144 | 2 | context->set_function_state(FunctionContext::FRAGMENT_LOCAL, state); | 145 | 2 | } | 146 | 4 | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE) { | 147 | 4 | if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) { | 148 | 2 | auto* state = reinterpret_cast<FunctionJsonbParseState*>( | 149 | 2 | context->get_function_state(FunctionContext::FRAGMENT_LOCAL)); | 150 | 2 | if (state) { | 151 | 2 | if (context->get_num_args() == 2) { | 152 | 1 | if (context->is_col_constant(1)) { | 153 | 0 | const auto default_value_col = context->get_constant_col(1)->column_ptr; | 154 | 0 | if (default_value_col->is_null_at(0)) { | 155 | 0 | state->default_is_null = true; | 156 | 0 | } else { | 157 | 0 | const auto& default_value = default_value_col->get_data_at(0); | 158 | |
| 159 | 0 | state->default_value = default_value; | 160 | 0 | state->has_const_default_value = true; | 161 | 0 | } | 162 | 0 | } | 163 | 1 | } else if (context->get_num_args() == 1) { | 164 | 0 | RETURN_IF_ERROR( | 165 | 0 | state->default_value_parser.from_json_string(std::string("{}"))); | 166 | 0 | state->default_value = StringRef(state->default_value_parser.value(), | 167 | 0 | state->default_value_parser.size()); | 168 | 0 | state->has_const_default_value = true; | 169 | 0 | } | 170 | 2 | } | 171 | 2 | } | 172 | | | 173 | 4 | if (context->get_num_args() != 1 && context->get_num_args() != 2) { | 174 | 1 | return Status::InvalidArgument( | 175 | 1 | "{} function should have 1 or 2 arguments, " | 176 | 1 | "but got {}", | 177 | 1 | get_name(), context->get_num_args()); | 178 | 1 | } | 179 | 4 | } | 180 | 3 | return Status::OK(); | 181 | 4 | } |
|
182 | | |
183 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
184 | 10 | uint32_t result, size_t input_rows_count) const override { |
185 | 10 | auto&& [col_from, col_from_is_const] = |
186 | 10 | unpack_if_const(block.get_by_position(arguments[0]).column); |
187 | | |
188 | 10 | if (col_from_is_const && col_from->is_null_at(0)) { |
189 | 0 | auto col_str = ColumnString::create(); |
190 | 0 | col_str->insert_default(); |
191 | 0 | auto null_map = ColumnUInt8::create(1, 1); |
192 | 0 | auto nullable_col = ColumnNullable::create(std::move(col_str), std::move(null_map)); |
193 | 0 | block.get_by_position(result).column = |
194 | 0 | ColumnConst::create(std::move(nullable_col), input_rows_count); |
195 | 0 | return Status::OK(); |
196 | 0 | } |
197 | | |
198 | 10 | auto null_map = ColumnUInt8::create(0, 0); |
199 | 10 | bool is_nullable = false; |
200 | | |
201 | 10 | switch (nullable_mode) { |
202 | 1 | case NullalbeMode::NULLABLE: { |
203 | 1 | is_nullable = true; |
204 | 1 | break; |
205 | 0 | } |
206 | 9 | case NullalbeMode::FOLLOW_INPUT: { |
207 | 11 | for (auto arg : arguments) { |
208 | 11 | is_nullable |= block.get_by_position(arg).type->is_nullable(); |
209 | 11 | } |
210 | 9 | break; |
211 | 0 | } |
212 | 10 | } |
213 | | |
214 | 10 | if (is_nullable) { |
215 | 9 | null_map = ColumnUInt8::create(input_rows_count, 0); |
216 | 9 | } |
217 | | |
218 | 8 | const ColumnString* col_from_string = nullptr; |
219 | 10 | if (const auto* nullable_col = check_and_get_column<ColumnNullable>(col_from.get())) { |
220 | 9 | VectorizedUtils::update_null_map(null_map->get_data(), |
221 | 9 | nullable_col->get_null_map_data()); |
222 | 9 | col_from_string = |
223 | 9 | assert_cast<const ColumnString*>(nullable_col->get_nested_column_ptr().get()); |
224 | 9 | } else { |
225 | 1 | col_from_string = assert_cast<const ColumnString*>(col_from.get()); |
226 | 1 | } |
227 | | |
228 | 8 | StringRef constant_default_value; |
229 | 8 | bool default_value_const = false; |
230 | 8 | bool default_value_null_const = false; |
231 | 8 | ColumnPtr default_value_col; |
232 | 8 | JsonBinaryValue default_jsonb_value_parser; |
233 | 8 | const ColumnString* default_value_str_col = nullptr; |
234 | 8 | const NullMap* default_value_nullmap = nullptr; |
235 | 8 | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE) { |
236 | 2 | auto* state = reinterpret_cast<FunctionJsonbParseState*>( |
237 | 2 | context->get_function_state(FunctionContext::FRAGMENT_LOCAL)); |
238 | 2 | if (state && state->has_const_default_value) { |
239 | 0 | constant_default_value = state->default_value; |
240 | 0 | default_value_null_const = state->default_is_null; |
241 | 0 | default_value_const = true; |
242 | 2 | } else if (arguments.size() > 1) { |
243 | 2 | if (block.get_by_position(arguments[1]).type->get_primitive_type() != |
244 | 2 | PrimitiveType::TYPE_JSONB) { |
245 | 1 | return Status::InvalidArgument( |
246 | 1 | "{} second argument should be jsonb type, but got {}", get_name(), |
247 | 1 | block.get_by_position(arguments[1]).type->get_name()); |
248 | 1 | } |
249 | 1 | std::tie(default_value_col, default_value_const) = |
250 | 1 | unpack_if_const(block.get_by_position(arguments[1]).column); |
251 | 1 | if (default_value_const) { |
252 | 0 | const JsonbDocument* default_value_doc = nullptr; |
253 | 0 | if (default_value_col->is_null_at(0)) { |
254 | 0 | default_value_null_const = true; |
255 | 0 | } else { |
256 | 0 | auto data = default_value_col->get_data_at(0); |
257 | 0 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(data.data, data.size, |
258 | 0 | &default_value_doc)); |
259 | 0 | constant_default_value = data; |
260 | 0 | } |
261 | 1 | } else { |
262 | 1 | if (const auto* nullable_col = |
263 | 1 | check_and_get_column<ColumnNullable>(default_value_col.get())) { |
264 | 1 | default_value_str_col = assert_cast<const ColumnString*>( |
265 | 1 | nullable_col->get_nested_column_ptr().get()); |
266 | 1 | default_value_nullmap = &(nullable_col->get_null_map_data()); |
267 | 1 | } else { |
268 | 0 | default_value_str_col = |
269 | 0 | assert_cast<const ColumnString*>(default_value_col.get()); |
270 | 0 | } |
271 | 1 | } |
272 | 1 | } else if (arguments.size() == 1) { |
273 | | // parse default value '{}' should always success. |
274 | 0 | RETURN_IF_ERROR(default_jsonb_value_parser.from_json_string(std::string("{}"))); |
275 | 0 | default_value_const = true; |
276 | 0 | constant_default_value.data = default_jsonb_value_parser.value(); |
277 | 0 | constant_default_value.size = default_jsonb_value_parser.size(); |
278 | 0 | } |
279 | 2 | } |
280 | | |
281 | 1 | auto col_to = ColumnString::create(); |
282 | | |
283 | 8 | col_to->reserve(input_rows_count); |
284 | | |
285 | 8 | auto& null_map_data = null_map->get_data(); |
286 | | |
287 | | // parser can be reused for performance |
288 | 8 | JsonBinaryValue jsonb_value; |
289 | | |
290 | 79 | for (size_t i = 0; i < input_rows_count; ++i) { |
291 | 69 | if (is_nullable && null_map_data[i]) { |
292 | 3 | col_to->insert_default(); |
293 | 3 | continue; |
294 | 3 | } |
295 | | |
296 | 66 | auto index = index_check_const(i, col_from_is_const); |
297 | 66 | const auto& val = col_from_string->get_data_at(index); |
298 | 66 | auto st = jsonb_value.from_json_string(val.data, val.size); |
299 | 66 | if (st.ok()) { |
300 | | // insert jsonb format data |
301 | 48 | col_to->insert_data(jsonb_value.value(), jsonb_value.size()); |
302 | 48 | } else { |
303 | 18 | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::FAIL) { |
304 | 6 | return Status::InvalidArgument( |
305 | 6 | "Parse json document failed at row {}, error: {}", i, st.to_string()); |
306 | 6 | } else if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_NULL) { |
307 | 6 | null_map_data[i] = 1; |
308 | 6 | col_to->insert_default(); |
309 | 6 | } else { |
310 | 6 | if (default_value_const) { |
311 | 0 | if (default_value_null_const) { |
312 | 0 | null_map_data[i] = 1; |
313 | 0 | col_to->insert_default(); |
314 | 0 | } else { |
315 | 0 | col_to->insert_data(constant_default_value.data, |
316 | 0 | constant_default_value.size); |
317 | 0 | } |
318 | 6 | } else { |
319 | 6 | if (default_value_nullmap && (*default_value_nullmap)[i]) { |
320 | 0 | null_map_data[i] = 1; |
321 | 0 | col_to->insert_default(); |
322 | 0 | continue; |
323 | 0 | } |
324 | 6 | auto value = default_value_str_col->get_data_at(i); |
325 | 6 | col_to->insert_data(value.data, value.size); |
326 | 6 | } |
327 | 6 | } |
328 | 18 | } |
329 | 66 | } |
330 | | |
331 | 10 | if (is_nullable) { |
332 | 3 | block.replace_by_position( |
333 | 3 | result, ColumnNullable::create(std::move(col_to), std::move(null_map))); |
334 | 7 | } else { |
335 | 7 | block.replace_by_position(result, std::move(col_to)); |
336 | 7 | } |
337 | | |
338 | 2 | return Status::OK(); |
339 | 2 | } _ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE0EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm Line | Count | Source | 184 | 7 | uint32_t result, size_t input_rows_count) const override { | 185 | 7 | auto&& [col_from, col_from_is_const] = | 186 | 7 | unpack_if_const(block.get_by_position(arguments[0]).column); | 187 | | | 188 | 7 | if (col_from_is_const && col_from->is_null_at(0)) { | 189 | 0 | auto col_str = ColumnString::create(); | 190 | 0 | col_str->insert_default(); | 191 | 0 | auto null_map = ColumnUInt8::create(1, 1); | 192 | 0 | auto nullable_col = ColumnNullable::create(std::move(col_str), std::move(null_map)); | 193 | 0 | block.get_by_position(result).column = | 194 | 0 | ColumnConst::create(std::move(nullable_col), input_rows_count); | 195 | 0 | return Status::OK(); | 196 | 0 | } | 197 | | | 198 | 7 | auto null_map = ColumnUInt8::create(0, 0); | 199 | 7 | bool is_nullable = false; | 200 | | | 201 | 7 | switch (nullable_mode) { | 202 | 0 | case NullalbeMode::NULLABLE: { | 203 | 0 | is_nullable = true; | 204 | 0 | break; | 205 | 0 | } | 206 | 7 | case NullalbeMode::FOLLOW_INPUT: { | 207 | 7 | for (auto arg : arguments) { | 208 | 7 | is_nullable |= block.get_by_position(arg).type->is_nullable(); | 209 | 7 | } | 210 | 7 | break; | 211 | 0 | } | 212 | 7 | } | 213 | | | 214 | 7 | if (is_nullable) { | 215 | 7 | null_map = ColumnUInt8::create(input_rows_count, 0); | 216 | 7 | } | 217 | | | 218 | 7 | const ColumnString* col_from_string = nullptr; | 219 | 7 | if (const auto* nullable_col = check_and_get_column<ColumnNullable>(col_from.get())) { | 220 | 7 | VectorizedUtils::update_null_map(null_map->get_data(), | 221 | 7 | nullable_col->get_null_map_data()); | 222 | 7 | col_from_string = | 223 | 7 | assert_cast<const ColumnString*>(nullable_col->get_nested_column_ptr().get()); | 224 | 7 | } else { | 225 | 0 | col_from_string = assert_cast<const ColumnString*>(col_from.get()); | 226 | 0 | } | 227 | | | 228 | 7 | StringRef constant_default_value; | 229 | 7 | bool default_value_const = false; | 230 | 7 | bool default_value_null_const = false; | 231 | 7 | ColumnPtr default_value_col; | 232 | 7 | JsonBinaryValue default_jsonb_value_parser; | 233 | 7 | const ColumnString* default_value_str_col = nullptr; | 234 | 7 | const NullMap* default_value_nullmap = nullptr; | 235 | | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE) { | 236 | | auto* state = reinterpret_cast<FunctionJsonbParseState*>( | 237 | | context->get_function_state(FunctionContext::FRAGMENT_LOCAL)); | 238 | | if (state && state->has_const_default_value) { | 239 | | constant_default_value = state->default_value; | 240 | | default_value_null_const = state->default_is_null; | 241 | | default_value_const = true; | 242 | | } else if (arguments.size() > 1) { | 243 | | if (block.get_by_position(arguments[1]).type->get_primitive_type() != | 244 | | PrimitiveType::TYPE_JSONB) { | 245 | | return Status::InvalidArgument( | 246 | | "{} second argument should be jsonb type, but got {}", get_name(), | 247 | | block.get_by_position(arguments[1]).type->get_name()); | 248 | | } | 249 | | std::tie(default_value_col, default_value_const) = | 250 | | unpack_if_const(block.get_by_position(arguments[1]).column); | 251 | | if (default_value_const) { | 252 | | const JsonbDocument* default_value_doc = nullptr; | 253 | | if (default_value_col->is_null_at(0)) { | 254 | | default_value_null_const = true; | 255 | | } else { | 256 | | auto data = default_value_col->get_data_at(0); | 257 | | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(data.data, data.size, | 258 | | &default_value_doc)); | 259 | | constant_default_value = data; | 260 | | } | 261 | | } else { | 262 | | if (const auto* nullable_col = | 263 | | check_and_get_column<ColumnNullable>(default_value_col.get())) { | 264 | | default_value_str_col = assert_cast<const ColumnString*>( | 265 | | nullable_col->get_nested_column_ptr().get()); | 266 | | default_value_nullmap = &(nullable_col->get_null_map_data()); | 267 | | } else { | 268 | | default_value_str_col = | 269 | | assert_cast<const ColumnString*>(default_value_col.get()); | 270 | | } | 271 | | } | 272 | | } else if (arguments.size() == 1) { | 273 | | // parse default value '{}' should always success. | 274 | | RETURN_IF_ERROR(default_jsonb_value_parser.from_json_string(std::string("{}"))); | 275 | | default_value_const = true; | 276 | | constant_default_value.data = default_jsonb_value_parser.value(); | 277 | | constant_default_value.size = default_jsonb_value_parser.size(); | 278 | | } | 279 | | } | 280 | | | 281 | 7 | auto col_to = ColumnString::create(); | 282 | | | 283 | 7 | col_to->reserve(input_rows_count); | 284 | | | 285 | 7 | auto& null_map_data = null_map->get_data(); | 286 | | | 287 | | // parser can be reused for performance | 288 | 7 | JsonBinaryValue jsonb_value; | 289 | | | 290 | 30 | for (size_t i = 0; i < input_rows_count; ++i) { | 291 | 23 | if (is_nullable && null_map_data[i]) { | 292 | 1 | col_to->insert_default(); | 293 | 1 | continue; | 294 | 1 | } | 295 | | | 296 | 22 | auto index = index_check_const(i, col_from_is_const); | 297 | 22 | const auto& val = col_from_string->get_data_at(index); | 298 | 22 | auto st = jsonb_value.from_json_string(val.data, val.size); | 299 | 22 | if (st.ok()) { | 300 | | // insert jsonb format data | 301 | 16 | col_to->insert_data(jsonb_value.value(), jsonb_value.size()); | 302 | 16 | } else { | 303 | 6 | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::FAIL) { | 304 | 6 | return Status::InvalidArgument( | 305 | 6 | "Parse json document failed at row {}, error: {}", i, st.to_string()); | 306 | | } else if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_NULL) { | 307 | | null_map_data[i] = 1; | 308 | | col_to->insert_default(); | 309 | | } else { | 310 | | if (default_value_const) { | 311 | | if (default_value_null_const) { | 312 | | null_map_data[i] = 1; | 313 | | col_to->insert_default(); | 314 | | } else { | 315 | | col_to->insert_data(constant_default_value.data, | 316 | | constant_default_value.size); | 317 | | } | 318 | | } else { | 319 | | if (default_value_nullmap && (*default_value_nullmap)[i]) { | 320 | | null_map_data[i] = 1; | 321 | | col_to->insert_default(); | 322 | | continue; | 323 | | } | 324 | | auto value = default_value_str_col->get_data_at(i); | 325 | | col_to->insert_data(value.data, value.size); | 326 | | } | 327 | | } | 328 | 6 | } | 329 | 22 | } | 330 | | | 331 | 7 | if (is_nullable) { | 332 | 1 | block.replace_by_position( | 333 | 1 | result, ColumnNullable::create(std::move(col_to), std::move(null_map))); | 334 | 6 | } else { | 335 | 6 | block.replace_by_position(result, std::move(col_to)); | 336 | 6 | } | 337 | | | 338 | 7 | return Status::OK(); | 339 | 7 | } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE0ELNS_19JsonbParseErrorModeE1EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm Line | Count | Source | 184 | 1 | uint32_t result, size_t input_rows_count) const override { | 185 | 1 | auto&& [col_from, col_from_is_const] = | 186 | 1 | unpack_if_const(block.get_by_position(arguments[0]).column); | 187 | | | 188 | 1 | if (col_from_is_const && col_from->is_null_at(0)) { | 189 | 0 | auto col_str = ColumnString::create(); | 190 | 0 | col_str->insert_default(); | 191 | 0 | auto null_map = ColumnUInt8::create(1, 1); | 192 | 0 | auto nullable_col = ColumnNullable::create(std::move(col_str), std::move(null_map)); | 193 | 0 | block.get_by_position(result).column = | 194 | 0 | ColumnConst::create(std::move(nullable_col), input_rows_count); | 195 | 0 | return Status::OK(); | 196 | 0 | } | 197 | | | 198 | 1 | auto null_map = ColumnUInt8::create(0, 0); | 199 | 1 | bool is_nullable = false; | 200 | | | 201 | 1 | switch (nullable_mode) { | 202 | 1 | case NullalbeMode::NULLABLE: { | 203 | 1 | is_nullable = true; | 204 | 1 | break; | 205 | 0 | } | 206 | 0 | case NullalbeMode::FOLLOW_INPUT: { | 207 | 0 | for (auto arg : arguments) { | 208 | 0 | is_nullable |= block.get_by_position(arg).type->is_nullable(); | 209 | 0 | } | 210 | 0 | break; | 211 | 0 | } | 212 | 1 | } | 213 | | | 214 | 1 | if (is_nullable) { | 215 | 1 | null_map = ColumnUInt8::create(input_rows_count, 0); | 216 | 1 | } | 217 | | | 218 | 1 | const ColumnString* col_from_string = nullptr; | 219 | 1 | if (const auto* nullable_col = check_and_get_column<ColumnNullable>(col_from.get())) { | 220 | 1 | VectorizedUtils::update_null_map(null_map->get_data(), | 221 | 1 | nullable_col->get_null_map_data()); | 222 | 1 | col_from_string = | 223 | 1 | assert_cast<const ColumnString*>(nullable_col->get_nested_column_ptr().get()); | 224 | 1 | } else { | 225 | 0 | col_from_string = assert_cast<const ColumnString*>(col_from.get()); | 226 | 0 | } | 227 | | | 228 | 1 | StringRef constant_default_value; | 229 | 1 | bool default_value_const = false; | 230 | 1 | bool default_value_null_const = false; | 231 | 1 | ColumnPtr default_value_col; | 232 | 1 | JsonBinaryValue default_jsonb_value_parser; | 233 | 1 | const ColumnString* default_value_str_col = nullptr; | 234 | 1 | const NullMap* default_value_nullmap = nullptr; | 235 | | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE) { | 236 | | auto* state = reinterpret_cast<FunctionJsonbParseState*>( | 237 | | context->get_function_state(FunctionContext::FRAGMENT_LOCAL)); | 238 | | if (state && state->has_const_default_value) { | 239 | | constant_default_value = state->default_value; | 240 | | default_value_null_const = state->default_is_null; | 241 | | default_value_const = true; | 242 | | } else if (arguments.size() > 1) { | 243 | | if (block.get_by_position(arguments[1]).type->get_primitive_type() != | 244 | | PrimitiveType::TYPE_JSONB) { | 245 | | return Status::InvalidArgument( | 246 | | "{} second argument should be jsonb type, but got {}", get_name(), | 247 | | block.get_by_position(arguments[1]).type->get_name()); | 248 | | } | 249 | | std::tie(default_value_col, default_value_const) = | 250 | | unpack_if_const(block.get_by_position(arguments[1]).column); | 251 | | if (default_value_const) { | 252 | | const JsonbDocument* default_value_doc = nullptr; | 253 | | if (default_value_col->is_null_at(0)) { | 254 | | default_value_null_const = true; | 255 | | } else { | 256 | | auto data = default_value_col->get_data_at(0); | 257 | | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(data.data, data.size, | 258 | | &default_value_doc)); | 259 | | constant_default_value = data; | 260 | | } | 261 | | } else { | 262 | | if (const auto* nullable_col = | 263 | | check_and_get_column<ColumnNullable>(default_value_col.get())) { | 264 | | default_value_str_col = assert_cast<const ColumnString*>( | 265 | | nullable_col->get_nested_column_ptr().get()); | 266 | | default_value_nullmap = &(nullable_col->get_null_map_data()); | 267 | | } else { | 268 | | default_value_str_col = | 269 | | assert_cast<const ColumnString*>(default_value_col.get()); | 270 | | } | 271 | | } | 272 | | } else if (arguments.size() == 1) { | 273 | | // parse default value '{}' should always success. | 274 | | RETURN_IF_ERROR(default_jsonb_value_parser.from_json_string(std::string("{}"))); | 275 | | default_value_const = true; | 276 | | constant_default_value.data = default_jsonb_value_parser.value(); | 277 | | constant_default_value.size = default_jsonb_value_parser.size(); | 278 | | } | 279 | | } | 280 | | | 281 | 1 | auto col_to = ColumnString::create(); | 282 | | | 283 | 1 | col_to->reserve(input_rows_count); | 284 | | | 285 | 1 | auto& null_map_data = null_map->get_data(); | 286 | | | 287 | | // parser can be reused for performance | 288 | 1 | JsonBinaryValue jsonb_value; | 289 | | | 290 | 24 | for (size_t i = 0; i < input_rows_count; ++i) { | 291 | 23 | if (is_nullable && null_map_data[i]) { | 292 | 1 | col_to->insert_default(); | 293 | 1 | continue; | 294 | 1 | } | 295 | | | 296 | 22 | auto index = index_check_const(i, col_from_is_const); | 297 | 22 | const auto& val = col_from_string->get_data_at(index); | 298 | 22 | auto st = jsonb_value.from_json_string(val.data, val.size); | 299 | 22 | if (st.ok()) { | 300 | | // insert jsonb format data | 301 | 16 | col_to->insert_data(jsonb_value.value(), jsonb_value.size()); | 302 | 16 | } else { | 303 | | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::FAIL) { | 304 | | return Status::InvalidArgument( | 305 | | "Parse json document failed at row {}, error: {}", i, st.to_string()); | 306 | 6 | } else if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_NULL) { | 307 | 6 | null_map_data[i] = 1; | 308 | 6 | col_to->insert_default(); | 309 | | } else { | 310 | | if (default_value_const) { | 311 | | if (default_value_null_const) { | 312 | | null_map_data[i] = 1; | 313 | | col_to->insert_default(); | 314 | | } else { | 315 | | col_to->insert_data(constant_default_value.data, | 316 | | constant_default_value.size); | 317 | | } | 318 | | } else { | 319 | | if (default_value_nullmap && (*default_value_nullmap)[i]) { | 320 | | null_map_data[i] = 1; | 321 | | col_to->insert_default(); | 322 | | continue; | 323 | | } | 324 | | auto value = default_value_str_col->get_data_at(i); | 325 | | col_to->insert_data(value.data, value.size); | 326 | | } | 327 | | } | 328 | 6 | } | 329 | 22 | } | 330 | | | 331 | 1 | if (is_nullable) { | 332 | 1 | block.replace_by_position( | 333 | 1 | result, ColumnNullable::create(std::move(col_to), std::move(null_map))); | 334 | 1 | } else { | 335 | 0 | block.replace_by_position(result, std::move(col_to)); | 336 | 0 | } | 337 | | | 338 | 1 | return Status::OK(); | 339 | 1 | } |
_ZNK5doris22FunctionJsonbParseBaseILNS_12NullalbeModeE1ELNS_19JsonbParseErrorModeE2EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm Line | Count | Source | 184 | 2 | uint32_t result, size_t input_rows_count) const override { | 185 | 2 | auto&& [col_from, col_from_is_const] = | 186 | 2 | unpack_if_const(block.get_by_position(arguments[0]).column); | 187 | | | 188 | 2 | if (col_from_is_const && col_from->is_null_at(0)) { | 189 | 0 | auto col_str = ColumnString::create(); | 190 | 0 | col_str->insert_default(); | 191 | 0 | auto null_map = ColumnUInt8::create(1, 1); | 192 | 0 | auto nullable_col = ColumnNullable::create(std::move(col_str), std::move(null_map)); | 193 | 0 | block.get_by_position(result).column = | 194 | 0 | ColumnConst::create(std::move(nullable_col), input_rows_count); | 195 | 0 | return Status::OK(); | 196 | 0 | } | 197 | | | 198 | 2 | auto null_map = ColumnUInt8::create(0, 0); | 199 | 2 | bool is_nullable = false; | 200 | | | 201 | 2 | switch (nullable_mode) { | 202 | 0 | case NullalbeMode::NULLABLE: { | 203 | 0 | is_nullable = true; | 204 | 0 | break; | 205 | 0 | } | 206 | 2 | case NullalbeMode::FOLLOW_INPUT: { | 207 | 4 | for (auto arg : arguments) { | 208 | 4 | is_nullable |= block.get_by_position(arg).type->is_nullable(); | 209 | 4 | } | 210 | 2 | break; | 211 | 0 | } | 212 | 2 | } | 213 | | | 214 | 2 | if (is_nullable) { | 215 | 1 | null_map = ColumnUInt8::create(input_rows_count, 0); | 216 | 1 | } | 217 | | | 218 | 2 | const ColumnString* col_from_string = nullptr; | 219 | 2 | if (const auto* nullable_col = check_and_get_column<ColumnNullable>(col_from.get())) { | 220 | 1 | VectorizedUtils::update_null_map(null_map->get_data(), | 221 | 1 | nullable_col->get_null_map_data()); | 222 | 1 | col_from_string = | 223 | 1 | assert_cast<const ColumnString*>(nullable_col->get_nested_column_ptr().get()); | 224 | 1 | } else { | 225 | 1 | col_from_string = assert_cast<const ColumnString*>(col_from.get()); | 226 | 1 | } | 227 | | | 228 | 2 | StringRef constant_default_value; | 229 | 2 | bool default_value_const = false; | 230 | 2 | bool default_value_null_const = false; | 231 | 2 | ColumnPtr default_value_col; | 232 | 2 | JsonBinaryValue default_jsonb_value_parser; | 233 | 2 | const ColumnString* default_value_str_col = nullptr; | 234 | 2 | const NullMap* default_value_nullmap = nullptr; | 235 | 2 | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE) { | 236 | 2 | auto* state = reinterpret_cast<FunctionJsonbParseState*>( | 237 | 2 | context->get_function_state(FunctionContext::FRAGMENT_LOCAL)); | 238 | 2 | if (state && state->has_const_default_value) { | 239 | 0 | constant_default_value = state->default_value; | 240 | 0 | default_value_null_const = state->default_is_null; | 241 | 0 | default_value_const = true; | 242 | 2 | } else if (arguments.size() > 1) { | 243 | 2 | if (block.get_by_position(arguments[1]).type->get_primitive_type() != | 244 | 2 | PrimitiveType::TYPE_JSONB) { | 245 | 1 | return Status::InvalidArgument( | 246 | 1 | "{} second argument should be jsonb type, but got {}", get_name(), | 247 | 1 | block.get_by_position(arguments[1]).type->get_name()); | 248 | 1 | } | 249 | 1 | std::tie(default_value_col, default_value_const) = | 250 | 1 | unpack_if_const(block.get_by_position(arguments[1]).column); | 251 | 1 | if (default_value_const) { | 252 | 0 | const JsonbDocument* default_value_doc = nullptr; | 253 | 0 | if (default_value_col->is_null_at(0)) { | 254 | 0 | default_value_null_const = true; | 255 | 0 | } else { | 256 | 0 | auto data = default_value_col->get_data_at(0); | 257 | 0 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(data.data, data.size, | 258 | 0 | &default_value_doc)); | 259 | 0 | constant_default_value = data; | 260 | 0 | } | 261 | 1 | } else { | 262 | 1 | if (const auto* nullable_col = | 263 | 1 | check_and_get_column<ColumnNullable>(default_value_col.get())) { | 264 | 1 | default_value_str_col = assert_cast<const ColumnString*>( | 265 | 1 | nullable_col->get_nested_column_ptr().get()); | 266 | 1 | default_value_nullmap = &(nullable_col->get_null_map_data()); | 267 | 1 | } else { | 268 | 0 | default_value_str_col = | 269 | 0 | assert_cast<const ColumnString*>(default_value_col.get()); | 270 | 0 | } | 271 | 1 | } | 272 | 1 | } else if (arguments.size() == 1) { | 273 | | // parse default value '{}' should always success. | 274 | 0 | RETURN_IF_ERROR(default_jsonb_value_parser.from_json_string(std::string("{}"))); | 275 | 0 | default_value_const = true; | 276 | 0 | constant_default_value.data = default_jsonb_value_parser.value(); | 277 | 0 | constant_default_value.size = default_jsonb_value_parser.size(); | 278 | 0 | } | 279 | 2 | } | 280 | | | 281 | 1 | auto col_to = ColumnString::create(); | 282 | | | 283 | 2 | col_to->reserve(input_rows_count); | 284 | | | 285 | 2 | auto& null_map_data = null_map->get_data(); | 286 | | | 287 | | // parser can be reused for performance | 288 | 2 | JsonBinaryValue jsonb_value; | 289 | | | 290 | 25 | for (size_t i = 0; i < input_rows_count; ++i) { | 291 | 23 | if (is_nullable && null_map_data[i]) { | 292 | 1 | col_to->insert_default(); | 293 | 1 | continue; | 294 | 1 | } | 295 | | | 296 | 22 | auto index = index_check_const(i, col_from_is_const); | 297 | 22 | const auto& val = col_from_string->get_data_at(index); | 298 | 22 | auto st = jsonb_value.from_json_string(val.data, val.size); | 299 | 22 | if (st.ok()) { | 300 | | // insert jsonb format data | 301 | 16 | col_to->insert_data(jsonb_value.value(), jsonb_value.size()); | 302 | 16 | } else { | 303 | | if constexpr (parse_error_handle_mode == JsonbParseErrorMode::FAIL) { | 304 | | return Status::InvalidArgument( | 305 | | "Parse json document failed at row {}, error: {}", i, st.to_string()); | 306 | | } else if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_NULL) { | 307 | | null_map_data[i] = 1; | 308 | | col_to->insert_default(); | 309 | 6 | } else { | 310 | 6 | if (default_value_const) { | 311 | 0 | if (default_value_null_const) { | 312 | 0 | null_map_data[i] = 1; | 313 | 0 | col_to->insert_default(); | 314 | 0 | } else { | 315 | 0 | col_to->insert_data(constant_default_value.data, | 316 | 0 | constant_default_value.size); | 317 | 0 | } | 318 | 6 | } else { | 319 | 6 | if (default_value_nullmap && (*default_value_nullmap)[i]) { | 320 | 0 | null_map_data[i] = 1; | 321 | 0 | col_to->insert_default(); | 322 | 0 | continue; | 323 | 0 | } | 324 | 6 | auto value = default_value_str_col->get_data_at(i); | 325 | 6 | col_to->insert_data(value.data, value.size); | 326 | 6 | } | 327 | 6 | } | 328 | 6 | } | 329 | 22 | } | 330 | | | 331 | 2 | if (is_nullable) { | 332 | 1 | block.replace_by_position( | 333 | 1 | result, ColumnNullable::create(std::move(col_to), std::move(null_map))); | 334 | 1 | } else { | 335 | 1 | block.replace_by_position(result, std::move(col_to)); | 336 | 1 | } | 337 | | | 338 | 2 | return Status::OK(); | 339 | 2 | } |
|
340 | | }; |
341 | | |
342 | | // jsonb_parse return type nullable as input |
343 | | using FunctionJsonbParse = |
344 | | FunctionJsonbParseBase<NullalbeMode::FOLLOW_INPUT, JsonbParseErrorMode::FAIL>; |
345 | | using FunctionJsonbParseErrorNull = |
346 | | FunctionJsonbParseBase<NullalbeMode::NULLABLE, JsonbParseErrorMode::RETURN_NULL>; |
347 | | using FunctionJsonbParseErrorValue = |
348 | | FunctionJsonbParseBase<NullalbeMode::FOLLOW_INPUT, JsonbParseErrorMode::RETURN_VALUE>; |
349 | | |
350 | | // func(jsonb, [varchar, varchar, ...]) -> nullable(type) |
351 | | template <typename Impl> |
352 | | class FunctionJsonbExtract : public IFunction { |
353 | | public: |
354 | | static constexpr auto name = Impl::name; |
355 | | static constexpr auto alias = Impl::alias; |
356 | 13 | static FunctionPtr create() { return std::make_shared<FunctionJsonbExtract>(); }_ZN5doris20FunctionJsonbExtractINS_13JsonbTypeImplEE6createEv Line | Count | Source | 356 | 2 | static FunctionPtr create() { return std::make_shared<FunctionJsonbExtract>(); } |
_ZN5doris20FunctionJsonbExtractINS_18JsonbExtractIsnullEE6createEv Line | Count | Source | 356 | 2 | static FunctionPtr create() { return std::make_shared<FunctionJsonbExtract>(); } |
_ZN5doris20FunctionJsonbExtractINS_17JsonbExtractJsonbEE6createEv Line | Count | Source | 356 | 7 | static FunctionPtr create() { return std::make_shared<FunctionJsonbExtract>(); } |
_ZN5doris20FunctionJsonbExtractINS_25JsonbExtractJsonbNoQuotesEE6createEv Line | Count | Source | 356 | 2 | static FunctionPtr create() { return std::make_shared<FunctionJsonbExtract>(); } |
|
357 | 0 | String get_name() const override { return name; }Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_13JsonbTypeImplEE8get_nameB5cxx11Ev Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_18JsonbExtractIsnullEE8get_nameB5cxx11Ev Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_17JsonbExtractJsonbEE8get_nameB5cxx11Ev Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_25JsonbExtractJsonbNoQuotesEE8get_nameB5cxx11Ev |
358 | 10 | bool is_variadic() const override { return true; }_ZNK5doris20FunctionJsonbExtractINS_13JsonbTypeImplEE11is_variadicEv Line | Count | Source | 358 | 1 | bool is_variadic() const override { return true; } |
_ZNK5doris20FunctionJsonbExtractINS_18JsonbExtractIsnullEE11is_variadicEv Line | Count | Source | 358 | 1 | bool is_variadic() const override { return true; } |
_ZNK5doris20FunctionJsonbExtractINS_17JsonbExtractJsonbEE11is_variadicEv Line | Count | Source | 358 | 7 | bool is_variadic() const override { return true; } |
_ZNK5doris20FunctionJsonbExtractINS_25JsonbExtractJsonbNoQuotesEE11is_variadicEv Line | Count | Source | 358 | 1 | bool is_variadic() const override { return true; } |
|
359 | 1 | size_t get_number_of_arguments() const override { return 0; }Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_13JsonbTypeImplEE23get_number_of_argumentsEv Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_18JsonbExtractIsnullEE23get_number_of_argumentsEv _ZNK5doris20FunctionJsonbExtractINS_17JsonbExtractJsonbEE23get_number_of_argumentsEv Line | Count | Source | 359 | 1 | size_t get_number_of_arguments() const override { return 0; } |
Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_25JsonbExtractJsonbNoQuotesEE23get_number_of_argumentsEv |
360 | 10 | bool use_default_implementation_for_nulls() const override { return false; }Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_13JsonbTypeImplEE36use_default_implementation_for_nullsEv Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_18JsonbExtractIsnullEE36use_default_implementation_for_nullsEv _ZNK5doris20FunctionJsonbExtractINS_17JsonbExtractJsonbEE36use_default_implementation_for_nullsEv Line | Count | Source | 360 | 10 | bool use_default_implementation_for_nulls() const override { return false; } |
Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_25JsonbExtractJsonbNoQuotesEE36use_default_implementation_for_nullsEv |
361 | 5 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
362 | 5 | return make_nullable(std::make_shared<typename Impl::ReturnType>()); |
363 | 5 | } Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_13JsonbTypeImplEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_18JsonbExtractIsnullEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE _ZNK5doris20FunctionJsonbExtractINS_17JsonbExtractJsonbEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE Line | Count | Source | 361 | 5 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { | 362 | 5 | return make_nullable(std::make_shared<typename Impl::ReturnType>()); | 363 | 5 | } |
Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_25JsonbExtractJsonbNoQuotesEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE |
364 | 4 | DataTypes get_variadic_argument_types_impl() const override { |
365 | | if constexpr (HasGetVariadicArgumentTypesImpl<Impl>) { |
366 | | return Impl::get_variadic_argument_types_impl(); |
367 | 4 | } else { |
368 | 4 | return {}; |
369 | 4 | } |
370 | 4 | } _ZNK5doris20FunctionJsonbExtractINS_13JsonbTypeImplEE32get_variadic_argument_types_implEv Line | Count | Source | 364 | 1 | DataTypes get_variadic_argument_types_impl() const override { | 365 | | if constexpr (HasGetVariadicArgumentTypesImpl<Impl>) { | 366 | | return Impl::get_variadic_argument_types_impl(); | 367 | 1 | } else { | 368 | 1 | return {}; | 369 | 1 | } | 370 | 1 | } |
_ZNK5doris20FunctionJsonbExtractINS_18JsonbExtractIsnullEE32get_variadic_argument_types_implEv Line | Count | Source | 364 | 1 | DataTypes get_variadic_argument_types_impl() const override { | 365 | | if constexpr (HasGetVariadicArgumentTypesImpl<Impl>) { | 366 | | return Impl::get_variadic_argument_types_impl(); | 367 | 1 | } else { | 368 | 1 | return {}; | 369 | 1 | } | 370 | 1 | } |
_ZNK5doris20FunctionJsonbExtractINS_17JsonbExtractJsonbEE32get_variadic_argument_types_implEv Line | Count | Source | 364 | 1 | DataTypes get_variadic_argument_types_impl() const override { | 365 | | if constexpr (HasGetVariadicArgumentTypesImpl<Impl>) { | 366 | | return Impl::get_variadic_argument_types_impl(); | 367 | 1 | } else { | 368 | 1 | return {}; | 369 | 1 | } | 370 | 1 | } |
_ZNK5doris20FunctionJsonbExtractINS_25JsonbExtractJsonbNoQuotesEE32get_variadic_argument_types_implEv Line | Count | Source | 364 | 1 | DataTypes get_variadic_argument_types_impl() const override { | 365 | | if constexpr (HasGetVariadicArgumentTypesImpl<Impl>) { | 366 | | return Impl::get_variadic_argument_types_impl(); | 367 | 1 | } else { | 368 | 1 | return {}; | 369 | 1 | } | 370 | 1 | } |
|
371 | | |
372 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
373 | 5 | uint32_t result, size_t input_rows_count) const override { |
374 | 5 | DORIS_CHECK_GE(arguments.size(), 2); |
375 | | |
376 | 5 | ColumnPtr jsonb_data_column; |
377 | 5 | bool jsonb_data_const = false; |
378 | 5 | const NullMap* data_null_map = nullptr; |
379 | | |
380 | 5 | if (block.get_by_position(arguments[0]).type->get_primitive_type() != |
381 | 5 | PrimitiveType::TYPE_JSONB) { |
382 | 1 | return Status::InvalidArgument( |
383 | 1 | "jsonb_extract first argument should be json type, but got {}", |
384 | 1 | block.get_by_position(arguments[0]).type->get_name()); |
385 | 1 | } |
386 | | |
387 | | // prepare jsonb data column |
388 | 4 | std::tie(jsonb_data_column, jsonb_data_const) = |
389 | 4 | unpack_if_const(block.get_by_position(arguments[0]).column); |
390 | 4 | if (const auto* nullable_column = |
391 | 4 | check_and_get_column<ColumnNullable>(jsonb_data_column.get())) { |
392 | 4 | jsonb_data_column = nullable_column->get_nested_column_ptr(); |
393 | 4 | data_null_map = &nullable_column->get_null_map_data(); |
394 | 4 | } |
395 | 4 | const auto& ldata = assert_cast<const ColumnString*>(jsonb_data_column.get())->get_chars(); |
396 | 4 | const auto& loffsets = |
397 | 4 | assert_cast<const ColumnString*>(jsonb_data_column.get())->get_offsets(); |
398 | | |
399 | | // prepare parse path column prepare |
400 | 4 | std::vector<const ColumnString*> jsonb_path_columns; |
401 | 4 | std::vector<bool> path_const(arguments.size() - 1); |
402 | 4 | std::vector<const NullMap*> path_null_maps(arguments.size() - 1, nullptr); |
403 | 8 | for (int i = 0; i < arguments.size() - 1; ++i) { |
404 | 4 | ColumnPtr path_column; |
405 | 4 | bool is_const = false; |
406 | 4 | std::tie(path_column, is_const) = |
407 | 4 | unpack_if_const(block.get_by_position(arguments[i + 1]).column); |
408 | 4 | path_const[i] = is_const; |
409 | 4 | if (const auto* nullable_column = |
410 | 4 | check_and_get_column<ColumnNullable>(path_column.get())) { |
411 | 4 | path_column = nullable_column->get_nested_column_ptr(); |
412 | 4 | path_null_maps[i] = &nullable_column->get_null_map_data(); |
413 | 4 | } |
414 | 4 | jsonb_path_columns.push_back(assert_cast<const ColumnString*>(path_column.get())); |
415 | 4 | } |
416 | | |
417 | 4 | auto null_map = ColumnUInt8::create(input_rows_count, 0); |
418 | 4 | auto res = Impl::ColumnType::create(); |
419 | | |
420 | | // execute Impl |
421 | | if constexpr (std::is_same_v<typename Impl::ReturnType, DataTypeString> || |
422 | 4 | std::is_same_v<typename Impl::ReturnType, DataTypeJsonb>) { |
423 | 4 | auto& res_data = res->get_chars(); |
424 | 4 | auto& res_offsets = res->get_offsets(); |
425 | 4 | RETURN_IF_ERROR(Impl::vector_vector_v2( |
426 | 4 | context, ldata, loffsets, data_null_map, jsonb_data_const, jsonb_path_columns, |
427 | 4 | path_null_maps, path_const, res_data, res_offsets, null_map->get_data())); |
428 | 4 | } else { |
429 | | // not support other extract type for now (e.g. int, double, ...) |
430 | 0 | DORIS_CHECK_EQ(jsonb_path_columns.size(), 1); |
431 | 0 | const auto& rdata = jsonb_path_columns[0]->get_chars(); |
432 | 0 | const auto& roffsets = jsonb_path_columns[0]->get_offsets(); |
433 | |
|
434 | 0 | auto create_all_null_result = [&]() { |
435 | 0 | res = Impl::ColumnType::create(); |
436 | 0 | res->insert_default(); |
437 | 0 | auto nullable_column = |
438 | 0 | ColumnNullable::create(std::move(res), ColumnUInt8::create(1, 1)); |
439 | 0 | auto const_column = |
440 | 0 | ColumnConst::create(std::move(nullable_column), input_rows_count); |
441 | 0 | block.get_by_position(result).column = std::move(const_column); |
442 | 0 | return Status::OK(); |
443 | 0 | }; |
444 | |
|
445 | 0 | if (jsonb_data_const) { |
446 | 0 | if (data_null_map && (*data_null_map)[0]) { |
447 | 0 | return create_all_null_result(); |
448 | 0 | } |
449 | | |
450 | 0 | RETURN_IF_ERROR(Impl::scalar_vector(context, jsonb_data_column->get_data_at(0), |
451 | 0 | rdata, roffsets, path_null_maps[0], |
452 | 0 | res->get_data(), null_map->get_data())); |
453 | 0 | } else if (path_const[0]) { |
454 | 0 | if (path_null_maps[0] && (*path_null_maps[0])[0]) { |
455 | 0 | return create_all_null_result(); |
456 | 0 | } |
457 | 0 | RETURN_IF_ERROR(Impl::vector_scalar(context, ldata, loffsets, data_null_map, |
458 | 0 | jsonb_path_columns[0]->get_data_at(0), |
459 | 0 | res->get_data(), null_map->get_data())); |
460 | 0 | } else { |
461 | 0 | RETURN_IF_ERROR(Impl::vector_vector(context, ldata, loffsets, data_null_map, rdata, |
462 | 0 | roffsets, path_null_maps[0], res->get_data(), |
463 | 0 | null_map->get_data())); |
464 | 0 | } |
465 | 0 | } |
466 | | |
467 | 4 | block.get_by_position(result).column = |
468 | 4 | ColumnNullable::create(std::move(res), std::move(null_map)); |
469 | 4 | return Status::OK(); |
470 | 5 | } Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_13JsonbTypeImplEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_18JsonbExtractIsnullEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm _ZNK5doris20FunctionJsonbExtractINS_17JsonbExtractJsonbEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm Line | Count | Source | 373 | 5 | uint32_t result, size_t input_rows_count) const override { | 374 | 5 | DORIS_CHECK_GE(arguments.size(), 2); | 375 | | | 376 | 5 | ColumnPtr jsonb_data_column; | 377 | 5 | bool jsonb_data_const = false; | 378 | 5 | const NullMap* data_null_map = nullptr; | 379 | | | 380 | 5 | if (block.get_by_position(arguments[0]).type->get_primitive_type() != | 381 | 5 | PrimitiveType::TYPE_JSONB) { | 382 | 1 | return Status::InvalidArgument( | 383 | 1 | "jsonb_extract first argument should be json type, but got {}", | 384 | 1 | block.get_by_position(arguments[0]).type->get_name()); | 385 | 1 | } | 386 | | | 387 | | // prepare jsonb data column | 388 | 4 | std::tie(jsonb_data_column, jsonb_data_const) = | 389 | 4 | unpack_if_const(block.get_by_position(arguments[0]).column); | 390 | 4 | if (const auto* nullable_column = | 391 | 4 | check_and_get_column<ColumnNullable>(jsonb_data_column.get())) { | 392 | 4 | jsonb_data_column = nullable_column->get_nested_column_ptr(); | 393 | 4 | data_null_map = &nullable_column->get_null_map_data(); | 394 | 4 | } | 395 | 4 | const auto& ldata = assert_cast<const ColumnString*>(jsonb_data_column.get())->get_chars(); | 396 | 4 | const auto& loffsets = | 397 | 4 | assert_cast<const ColumnString*>(jsonb_data_column.get())->get_offsets(); | 398 | | | 399 | | // prepare parse path column prepare | 400 | 4 | std::vector<const ColumnString*> jsonb_path_columns; | 401 | 4 | std::vector<bool> path_const(arguments.size() - 1); | 402 | 4 | std::vector<const NullMap*> path_null_maps(arguments.size() - 1, nullptr); | 403 | 8 | for (int i = 0; i < arguments.size() - 1; ++i) { | 404 | 4 | ColumnPtr path_column; | 405 | 4 | bool is_const = false; | 406 | 4 | std::tie(path_column, is_const) = | 407 | 4 | unpack_if_const(block.get_by_position(arguments[i + 1]).column); | 408 | 4 | path_const[i] = is_const; | 409 | 4 | if (const auto* nullable_column = | 410 | 4 | check_and_get_column<ColumnNullable>(path_column.get())) { | 411 | 4 | path_column = nullable_column->get_nested_column_ptr(); | 412 | 4 | path_null_maps[i] = &nullable_column->get_null_map_data(); | 413 | 4 | } | 414 | 4 | jsonb_path_columns.push_back(assert_cast<const ColumnString*>(path_column.get())); | 415 | 4 | } | 416 | | | 417 | 4 | auto null_map = ColumnUInt8::create(input_rows_count, 0); | 418 | 4 | auto res = Impl::ColumnType::create(); | 419 | | | 420 | | // execute Impl | 421 | | if constexpr (std::is_same_v<typename Impl::ReturnType, DataTypeString> || | 422 | 4 | std::is_same_v<typename Impl::ReturnType, DataTypeJsonb>) { | 423 | 4 | auto& res_data = res->get_chars(); | 424 | 4 | auto& res_offsets = res->get_offsets(); | 425 | 4 | RETURN_IF_ERROR(Impl::vector_vector_v2( | 426 | 4 | context, ldata, loffsets, data_null_map, jsonb_data_const, jsonb_path_columns, | 427 | 4 | path_null_maps, path_const, res_data, res_offsets, null_map->get_data())); | 428 | | } else { | 429 | | // not support other extract type for now (e.g. int, double, ...) | 430 | | DORIS_CHECK_EQ(jsonb_path_columns.size(), 1); | 431 | | const auto& rdata = jsonb_path_columns[0]->get_chars(); | 432 | | const auto& roffsets = jsonb_path_columns[0]->get_offsets(); | 433 | | | 434 | | auto create_all_null_result = [&]() { | 435 | | res = Impl::ColumnType::create(); | 436 | | res->insert_default(); | 437 | | auto nullable_column = | 438 | | ColumnNullable::create(std::move(res), ColumnUInt8::create(1, 1)); | 439 | | auto const_column = | 440 | | ColumnConst::create(std::move(nullable_column), input_rows_count); | 441 | | block.get_by_position(result).column = std::move(const_column); | 442 | | return Status::OK(); | 443 | | }; | 444 | | | 445 | | if (jsonb_data_const) { | 446 | | if (data_null_map && (*data_null_map)[0]) { | 447 | | return create_all_null_result(); | 448 | | } | 449 | | | 450 | | RETURN_IF_ERROR(Impl::scalar_vector(context, jsonb_data_column->get_data_at(0), | 451 | | rdata, roffsets, path_null_maps[0], | 452 | | res->get_data(), null_map->get_data())); | 453 | | } else if (path_const[0]) { | 454 | | if (path_null_maps[0] && (*path_null_maps[0])[0]) { | 455 | | return create_all_null_result(); | 456 | | } | 457 | | RETURN_IF_ERROR(Impl::vector_scalar(context, ldata, loffsets, data_null_map, | 458 | | jsonb_path_columns[0]->get_data_at(0), | 459 | | res->get_data(), null_map->get_data())); | 460 | | } else { | 461 | | RETURN_IF_ERROR(Impl::vector_vector(context, ldata, loffsets, data_null_map, rdata, | 462 | | roffsets, path_null_maps[0], res->get_data(), | 463 | | null_map->get_data())); | 464 | | } | 465 | | } | 466 | | | 467 | 4 | block.get_by_position(result).column = | 468 | 4 | ColumnNullable::create(std::move(res), std::move(null_map)); | 469 | 4 | return Status::OK(); | 470 | 5 | } |
Unexecuted instantiation: _ZNK5doris20FunctionJsonbExtractINS_25JsonbExtractJsonbNoQuotesEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm |
471 | | }; |
472 | | |
473 | | class FunctionJsonbKeys : public IFunction { |
474 | | public: |
475 | | static constexpr auto name = "json_keys"; |
476 | | static constexpr auto alias = "jsonb_keys"; |
477 | 4 | static FunctionPtr create() { return std::make_shared<FunctionJsonbKeys>(); } |
478 | 0 | String get_name() const override { return name; } |
479 | 3 | bool is_variadic() const override { return true; } |
480 | 0 | size_t get_number_of_arguments() const override { return 0; } |
481 | | |
482 | 4 | bool use_default_implementation_for_nulls() const override { return false; } |
483 | | |
484 | 2 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
485 | 2 | return make_nullable( |
486 | 2 | std::make_shared<DataTypeArray>(make_nullable(std::make_shared<DataTypeString>()))); |
487 | 2 | } |
488 | | |
489 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
490 | 2 | uint32_t result, size_t input_rows_count) const override { |
491 | 2 | DORIS_CHECK_GE(arguments.size(), 1); |
492 | 2 | DORIS_CHECK(arguments.size() == 1 || arguments.size() == 2) |
493 | 0 | << "json_keys should have 1 or 2 arguments, but got " << arguments.size(); |
494 | | |
495 | 2 | const NullMap* data_null_map = nullptr; |
496 | 2 | const ColumnString* col_from_string = nullptr; |
497 | | // prepare jsonb data column |
498 | 2 | auto&& [jsonb_data_column, json_data_const] = |
499 | 2 | unpack_if_const(block.get_by_position(arguments[0]).column); |
500 | 2 | if (const auto* nullable = check_and_get_column<ColumnNullable>(jsonb_data_column.get())) { |
501 | 0 | col_from_string = |
502 | 0 | assert_cast<const ColumnString*>(nullable->get_nested_column_ptr().get()); |
503 | 0 | data_null_map = &nullable->get_null_map_data(); |
504 | 2 | } else { |
505 | 2 | col_from_string = assert_cast<const ColumnString*>(jsonb_data_column.get()); |
506 | 2 | } |
507 | | |
508 | | // prepare parse path column prepare, maybe we do not have path column |
509 | 2 | ColumnPtr jsonb_path_column = nullptr; |
510 | 2 | const ColumnString* jsonb_path_col = nullptr; |
511 | 2 | bool path_const = false; |
512 | 2 | const NullMap* path_null_map = nullptr; |
513 | 2 | if (arguments.size() == 2) { |
514 | | // we have should have a ColumnString for path |
515 | 2 | std::tie(jsonb_path_column, path_const) = |
516 | 2 | unpack_if_const(block.get_by_position(arguments[1]).column); |
517 | 2 | if (const auto* nullable = |
518 | 2 | check_and_get_column<ColumnNullable>(jsonb_path_column.get())) { |
519 | 0 | jsonb_path_column = nullable->get_nested_column_ptr(); |
520 | 0 | path_null_map = &nullable->get_null_map_data(); |
521 | 0 | } |
522 | 2 | jsonb_path_col = check_and_get_column<ColumnString>(jsonb_path_column.get()); |
523 | 2 | } |
524 | | |
525 | 2 | auto null_map = ColumnUInt8::create(input_rows_count, 0); |
526 | 2 | NullMap& res_null_map = null_map->get_data(); |
527 | | |
528 | 2 | auto dst_arr = ColumnArray::create( |
529 | 2 | ColumnNullable::create(ColumnString::create(), ColumnUInt8::create()), |
530 | 2 | ColumnArray::ColumnOffsets::create()); |
531 | 2 | auto& dst_nested_column = assert_cast<ColumnNullable&>(dst_arr->get_data()); |
532 | | |
533 | 2 | Status st = std::visit( |
534 | 2 | [&](auto data_const, auto has_path, auto path_const) { |
535 | 2 | return inner_loop_impl<data_const, has_path, path_const>( |
536 | 2 | input_rows_count, *dst_arr, dst_nested_column, res_null_map, |
537 | 2 | *col_from_string, data_null_map, jsonb_path_col, path_null_map); |
538 | 2 | }, Unexecuted instantiation: _ZZNK5doris17FunctionJsonbKeys12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_T0_T1_E_clISt17integral_constantIbLb0EESG_SG_EEDaSA_SB_SC_ Unexecuted instantiation: _ZZNK5doris17FunctionJsonbKeys12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_T0_T1_E_clISt17integral_constantIbLb0EESG_SF_IbLb1EEEEDaSA_SB_SC_ _ZZNK5doris17FunctionJsonbKeys12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_T0_T1_E_clISt17integral_constantIbLb0EESF_IbLb1EESG_EEDaSA_SB_SC_ Line | Count | Source | 534 | 1 | [&](auto data_const, auto has_path, auto path_const) { | 535 | 1 | return inner_loop_impl<data_const, has_path, path_const>( | 536 | 1 | input_rows_count, *dst_arr, dst_nested_column, res_null_map, | 537 | 1 | *col_from_string, data_null_map, jsonb_path_col, path_null_map); | 538 | 1 | }, |
_ZZNK5doris17FunctionJsonbKeys12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_T0_T1_E_clISt17integral_constantIbLb0EESF_IbLb1EESH_EEDaSA_SB_SC_ Line | Count | Source | 534 | 1 | [&](auto data_const, auto has_path, auto path_const) { | 535 | 1 | return inner_loop_impl<data_const, has_path, path_const>( | 536 | 1 | input_rows_count, *dst_arr, dst_nested_column, res_null_map, | 537 | 1 | *col_from_string, data_null_map, jsonb_path_col, path_null_map); | 538 | 1 | }, |
Unexecuted instantiation: _ZZNK5doris17FunctionJsonbKeys12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_T0_T1_E_clISt17integral_constantIbLb1EESF_IbLb0EESH_EEDaSA_SB_SC_ Unexecuted instantiation: _ZZNK5doris17FunctionJsonbKeys12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_T0_T1_E_clISt17integral_constantIbLb1EESF_IbLb0EESG_EEDaSA_SB_SC_ Unexecuted instantiation: _ZZNK5doris17FunctionJsonbKeys12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_T0_T1_E_clISt17integral_constantIbLb1EESG_SF_IbLb0EEEEDaSA_SB_SC_ Unexecuted instantiation: _ZZNK5doris17FunctionJsonbKeys12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmENKUlT_T0_T1_E_clISt17integral_constantIbLb1EESG_SG_EEDaSA_SB_SC_ |
539 | 2 | make_bool_variant(json_data_const), make_bool_variant(jsonb_path_column), |
540 | 2 | make_bool_variant(path_const)); |
541 | 2 | if (!st.ok()) { |
542 | 2 | return st; |
543 | 2 | } |
544 | 0 | block.get_by_position(result).column = |
545 | 0 | ColumnNullable::create(std::move(dst_arr), std::move(null_map)); |
546 | 0 | return st; |
547 | 2 | } |
548 | | |
549 | | private: |
550 | | template <bool JSONB_DATA_CONST, bool JSONB_PATH_PARAM, bool JSON_PATH_CONST> |
551 | | static ALWAYS_INLINE Status inner_loop_impl(size_t input_rows_count, ColumnArray& dst_arr, |
552 | | ColumnNullable& dst_nested_column, |
553 | | NullMap& res_null_map, |
554 | | const ColumnString& col_from_string, |
555 | | const NullMap* jsonb_data_nullmap, |
556 | | const ColumnString* jsonb_path_column, |
557 | 2 | const NullMap* path_null_map) { |
558 | | // if path is const, we just need to parse it once |
559 | 2 | JsonbPath const_path; |
560 | 2 | if constexpr (JSONB_PATH_PARAM && JSON_PATH_CONST) { |
561 | 1 | StringRef r_raw_ref = jsonb_path_column->get_data_at(0); |
562 | 1 | if (!const_path.seek(r_raw_ref.data, r_raw_ref.size)) { |
563 | 0 | return Status::InvalidArgument("Json path error: Invalid Json Path for value: {}", |
564 | 0 | r_raw_ref.to_string()); |
565 | 0 | } |
566 | | |
567 | 1 | if (const_path.is_wildcard() || const_path.is_supper_wildcard()) { |
568 | 1 | return Status::InvalidJsonPath( |
569 | 1 | "In this situation, path expressions may not contain the * and ** tokens " |
570 | 1 | "or an array range."); |
571 | 1 | } |
572 | 1 | } |
573 | | |
574 | 4 | for (size_t i = 0; i < input_rows_count; ++i) { |
575 | 2 | auto index = index_check_const(i, JSONB_DATA_CONST); |
576 | | // if jsonb data is null or path column is null , we should return null |
577 | 2 | if (jsonb_data_nullmap && (*jsonb_data_nullmap)[index]) { |
578 | 0 | res_null_map[i] = 1; |
579 | 0 | dst_arr.insert_default(); |
580 | 0 | continue; |
581 | 0 | } |
582 | 2 | if constexpr (JSONB_PATH_PARAM && !JSON_PATH_CONST) { |
583 | 2 | if (path_null_map && (*path_null_map)[i]) { |
584 | 0 | res_null_map[i] = 1; |
585 | 0 | dst_arr.insert_default(); |
586 | 0 | continue; |
587 | 0 | } |
588 | 2 | } |
589 | | |
590 | 2 | auto json_data = col_from_string.get_data_at(index); |
591 | 2 | const JsonbDocument* doc = nullptr; |
592 | 2 | auto st = JsonbDocument::checkAndCreateDocument(json_data.data, json_data.size, &doc); |
593 | 2 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { |
594 | 0 | dst_arr.clear(); |
595 | 0 | return Status::InvalidArgument("jsonb data is invalid"); |
596 | 0 | } |
597 | 2 | const JsonbValue* obj_val; |
598 | 2 | JsonbFindResult find_result; |
599 | 2 | if constexpr (JSONB_PATH_PARAM) { |
600 | 2 | if constexpr (!JSON_PATH_CONST) { |
601 | 2 | auto data = jsonb_path_column->get_data_at(i); |
602 | 2 | JsonbPath path; |
603 | 2 | if (!path.seek(data.data, data.size)) { |
604 | 0 | return Status::InvalidArgument( |
605 | 0 | "Json path error: Invalid Json Path for value: {} at row: {}", |
606 | 0 | std::string_view(data.data, data.size), i); |
607 | 0 | } |
608 | | |
609 | 2 | if (path.is_wildcard() || path.is_supper_wildcard()) { |
610 | 1 | return Status::InvalidJsonPath( |
611 | 1 | "In this situation, path expressions may not contain the * and ** " |
612 | 1 | "tokens " |
613 | 1 | "or an array range. at row: {}", |
614 | 1 | i); |
615 | 1 | } |
616 | 1 | find_result = doc->getValue()->findValue(path); |
617 | 1 | } else { |
618 | 0 | find_result = doc->getValue()->findValue(const_path); |
619 | 0 | } |
620 | 0 | obj_val = find_result.value; |
621 | 2 | } else { |
622 | 0 | obj_val = doc->getValue(); |
623 | 0 | } |
624 | | |
625 | 2 | if (!obj_val || !obj_val->isObject()) { |
626 | | // if jsonb data is not object we should return null |
627 | 0 | res_null_map[i] = 1; |
628 | 0 | dst_arr.insert_default(); |
629 | 0 | continue; |
630 | 0 | } |
631 | 2 | const auto* obj = obj_val->unpack<ObjectVal>(); |
632 | 2 | for (const auto& it : *obj) { |
633 | 1 | dst_nested_column.insert_data(it.getKeyStr(), it.klen()); |
634 | 1 | } |
635 | 2 | dst_arr.get_offsets().push_back(dst_nested_column.size()); |
636 | 2 | } //for |
637 | 2 | return Status::OK(); |
638 | 2 | } Unexecuted instantiation: _ZN5doris17FunctionJsonbKeys15inner_loop_implILb0ELb0ELb0EEENS_6StatusEmRNS_11ColumnArrayERNS_14ColumnNullableERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS_9ColumnStrIjEEPKSB_PSF_SI_ Unexecuted instantiation: _ZN5doris17FunctionJsonbKeys15inner_loop_implILb0ELb0ELb1EEENS_6StatusEmRNS_11ColumnArrayERNS_14ColumnNullableERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS_9ColumnStrIjEEPKSB_PSF_SI_ _ZN5doris17FunctionJsonbKeys15inner_loop_implILb0ELb1ELb0EEENS_6StatusEmRNS_11ColumnArrayERNS_14ColumnNullableERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS_9ColumnStrIjEEPKSB_PSF_SI_ Line | Count | Source | 557 | 1 | const NullMap* path_null_map) { | 558 | | // if path is const, we just need to parse it once | 559 | 1 | JsonbPath const_path; | 560 | | if constexpr (JSONB_PATH_PARAM && JSON_PATH_CONST) { | 561 | | StringRef r_raw_ref = jsonb_path_column->get_data_at(0); | 562 | | if (!const_path.seek(r_raw_ref.data, r_raw_ref.size)) { | 563 | | return Status::InvalidArgument("Json path error: Invalid Json Path for value: {}", | 564 | | r_raw_ref.to_string()); | 565 | | } | 566 | | | 567 | | if (const_path.is_wildcard() || const_path.is_supper_wildcard()) { | 568 | | return Status::InvalidJsonPath( | 569 | | "In this situation, path expressions may not contain the * and ** tokens " | 570 | | "or an array range."); | 571 | | } | 572 | | } | 573 | | | 574 | 3 | for (size_t i = 0; i < input_rows_count; ++i) { | 575 | 2 | auto index = index_check_const(i, JSONB_DATA_CONST); | 576 | | // if jsonb data is null or path column is null , we should return null | 577 | 2 | if (jsonb_data_nullmap && (*jsonb_data_nullmap)[index]) { | 578 | 0 | res_null_map[i] = 1; | 579 | 0 | dst_arr.insert_default(); | 580 | 0 | continue; | 581 | 0 | } | 582 | 2 | if constexpr (JSONB_PATH_PARAM && !JSON_PATH_CONST) { | 583 | 2 | if (path_null_map && (*path_null_map)[i]) { | 584 | 0 | res_null_map[i] = 1; | 585 | 0 | dst_arr.insert_default(); | 586 | 0 | continue; | 587 | 0 | } | 588 | 2 | } | 589 | | | 590 | 2 | auto json_data = col_from_string.get_data_at(index); | 591 | 2 | const JsonbDocument* doc = nullptr; | 592 | 2 | auto st = JsonbDocument::checkAndCreateDocument(json_data.data, json_data.size, &doc); | 593 | 2 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { | 594 | 0 | dst_arr.clear(); | 595 | 0 | return Status::InvalidArgument("jsonb data is invalid"); | 596 | 0 | } | 597 | 2 | const JsonbValue* obj_val; | 598 | 2 | JsonbFindResult find_result; | 599 | 2 | if constexpr (JSONB_PATH_PARAM) { | 600 | 2 | if constexpr (!JSON_PATH_CONST) { | 601 | 2 | auto data = jsonb_path_column->get_data_at(i); | 602 | 2 | JsonbPath path; | 603 | 2 | if (!path.seek(data.data, data.size)) { | 604 | 0 | return Status::InvalidArgument( | 605 | 0 | "Json path error: Invalid Json Path for value: {} at row: {}", | 606 | 0 | std::string_view(data.data, data.size), i); | 607 | 0 | } | 608 | | | 609 | 2 | if (path.is_wildcard() || path.is_supper_wildcard()) { | 610 | 1 | return Status::InvalidJsonPath( | 611 | 1 | "In this situation, path expressions may not contain the * and ** " | 612 | 1 | "tokens " | 613 | 1 | "or an array range. at row: {}", | 614 | 1 | i); | 615 | 1 | } | 616 | 1 | find_result = doc->getValue()->findValue(path); | 617 | | } else { | 618 | | find_result = doc->getValue()->findValue(const_path); | 619 | | } | 620 | 0 | obj_val = find_result.value; | 621 | | } else { | 622 | | obj_val = doc->getValue(); | 623 | | } | 624 | | | 625 | 2 | if (!obj_val || !obj_val->isObject()) { | 626 | | // if jsonb data is not object we should return null | 627 | 0 | res_null_map[i] = 1; | 628 | 0 | dst_arr.insert_default(); | 629 | 0 | continue; | 630 | 0 | } | 631 | 2 | const auto* obj = obj_val->unpack<ObjectVal>(); | 632 | 2 | for (const auto& it : *obj) { | 633 | 1 | dst_nested_column.insert_data(it.getKeyStr(), it.klen()); | 634 | 1 | } | 635 | 2 | dst_arr.get_offsets().push_back(dst_nested_column.size()); | 636 | 2 | } //for | 637 | 1 | return Status::OK(); | 638 | 1 | } |
_ZN5doris17FunctionJsonbKeys15inner_loop_implILb0ELb1ELb1EEENS_6StatusEmRNS_11ColumnArrayERNS_14ColumnNullableERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS_9ColumnStrIjEEPKSB_PSF_SI_ Line | Count | Source | 557 | 1 | const NullMap* path_null_map) { | 558 | | // if path is const, we just need to parse it once | 559 | 1 | JsonbPath const_path; | 560 | 1 | if constexpr (JSONB_PATH_PARAM && JSON_PATH_CONST) { | 561 | 1 | StringRef r_raw_ref = jsonb_path_column->get_data_at(0); | 562 | 1 | if (!const_path.seek(r_raw_ref.data, r_raw_ref.size)) { | 563 | 0 | return Status::InvalidArgument("Json path error: Invalid Json Path for value: {}", | 564 | 0 | r_raw_ref.to_string()); | 565 | 0 | } | 566 | | | 567 | 1 | if (const_path.is_wildcard() || const_path.is_supper_wildcard()) { | 568 | 1 | return Status::InvalidJsonPath( | 569 | 1 | "In this situation, path expressions may not contain the * and ** tokens " | 570 | 1 | "or an array range."); | 571 | 1 | } | 572 | 1 | } | 573 | | | 574 | 1 | for (size_t i = 0; i < input_rows_count; ++i) { | 575 | 0 | auto index = index_check_const(i, JSONB_DATA_CONST); | 576 | | // if jsonb data is null or path column is null , we should return null | 577 | 0 | if (jsonb_data_nullmap && (*jsonb_data_nullmap)[index]) { | 578 | 0 | res_null_map[i] = 1; | 579 | 0 | dst_arr.insert_default(); | 580 | 0 | continue; | 581 | 0 | } | 582 | | if constexpr (JSONB_PATH_PARAM && !JSON_PATH_CONST) { | 583 | | if (path_null_map && (*path_null_map)[i]) { | 584 | | res_null_map[i] = 1; | 585 | | dst_arr.insert_default(); | 586 | | continue; | 587 | | } | 588 | | } | 589 | |
| 590 | 0 | auto json_data = col_from_string.get_data_at(index); | 591 | 0 | const JsonbDocument* doc = nullptr; | 592 | 0 | auto st = JsonbDocument::checkAndCreateDocument(json_data.data, json_data.size, &doc); | 593 | 0 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { | 594 | 0 | dst_arr.clear(); | 595 | 0 | return Status::InvalidArgument("jsonb data is invalid"); | 596 | 0 | } | 597 | 0 | const JsonbValue* obj_val; | 598 | 0 | JsonbFindResult find_result; | 599 | 0 | if constexpr (JSONB_PATH_PARAM) { | 600 | | if constexpr (!JSON_PATH_CONST) { | 601 | | auto data = jsonb_path_column->get_data_at(i); | 602 | | JsonbPath path; | 603 | | if (!path.seek(data.data, data.size)) { | 604 | | return Status::InvalidArgument( | 605 | | "Json path error: Invalid Json Path for value: {} at row: {}", | 606 | | std::string_view(data.data, data.size), i); | 607 | | } | 608 | | | 609 | | if (path.is_wildcard() || path.is_supper_wildcard()) { | 610 | | return Status::InvalidJsonPath( | 611 | | "In this situation, path expressions may not contain the * and ** " | 612 | | "tokens " | 613 | | "or an array range. at row: {}", | 614 | | i); | 615 | | } | 616 | | find_result = doc->getValue()->findValue(path); | 617 | 0 | } else { | 618 | 0 | find_result = doc->getValue()->findValue(const_path); | 619 | 0 | } | 620 | 0 | obj_val = find_result.value; | 621 | | } else { | 622 | | obj_val = doc->getValue(); | 623 | | } | 624 | |
| 625 | 0 | if (!obj_val || !obj_val->isObject()) { | 626 | | // if jsonb data is not object we should return null | 627 | 0 | res_null_map[i] = 1; | 628 | 0 | dst_arr.insert_default(); | 629 | 0 | continue; | 630 | 0 | } | 631 | 0 | const auto* obj = obj_val->unpack<ObjectVal>(); | 632 | 0 | for (const auto& it : *obj) { | 633 | 0 | dst_nested_column.insert_data(it.getKeyStr(), it.klen()); | 634 | 0 | } | 635 | 0 | dst_arr.get_offsets().push_back(dst_nested_column.size()); | 636 | 0 | } //for | 637 | 1 | return Status::OK(); | 638 | 1 | } |
Unexecuted instantiation: _ZN5doris17FunctionJsonbKeys15inner_loop_implILb1ELb0ELb0EEENS_6StatusEmRNS_11ColumnArrayERNS_14ColumnNullableERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS_9ColumnStrIjEEPKSB_PSF_SI_ Unexecuted instantiation: _ZN5doris17FunctionJsonbKeys15inner_loop_implILb1ELb0ELb1EEENS_6StatusEmRNS_11ColumnArrayERNS_14ColumnNullableERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS_9ColumnStrIjEEPKSB_PSF_SI_ Unexecuted instantiation: _ZN5doris17FunctionJsonbKeys15inner_loop_implILb1ELb1ELb0EEENS_6StatusEmRNS_11ColumnArrayERNS_14ColumnNullableERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS_9ColumnStrIjEEPKSB_PSF_SI_ Unexecuted instantiation: _ZN5doris17FunctionJsonbKeys15inner_loop_implILb1ELb1ELb1EEENS_6StatusEmRNS_11ColumnArrayERNS_14ColumnNullableERNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS_9ColumnStrIjEEPKSB_PSF_SI_ |
639 | | }; |
640 | | |
641 | | class FunctionJsonbExtractPath : public IFunction { |
642 | | public: |
643 | | static constexpr auto name = "json_exists_path"; |
644 | | static constexpr auto alias = "jsonb_exists_path"; |
645 | | using ColumnType = ColumnUInt8; |
646 | | using Container = typename ColumnType::Container; |
647 | 2 | static FunctionPtr create() { return std::make_shared<FunctionJsonbExtractPath>(); } |
648 | 1 | String get_name() const override { return name; } |
649 | 0 | size_t get_number_of_arguments() const override { return 2; } |
650 | 0 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
651 | | // it only needs to indicate existence and does not need to return nullable values. |
652 | 0 | const auto nullable = std::ranges::any_of( |
653 | 0 | arguments, [](const DataTypePtr& type) { return type->is_nullable(); }); |
654 | 0 | if (nullable) { |
655 | 0 | return make_nullable(std::make_shared<DataTypeUInt8>()); |
656 | 0 | } else { |
657 | 0 | return std::make_shared<DataTypeUInt8>(); |
658 | 0 | } |
659 | 0 | } |
660 | | |
661 | 0 | bool use_default_implementation_for_nulls() const override { return false; } |
662 | | |
663 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
664 | 0 | uint32_t result, size_t input_rows_count) const override { |
665 | | // prepare jsonb data column |
666 | 0 | auto&& [jsonb_data_column, jsonb_data_const] = |
667 | 0 | unpack_if_const(block.get_by_position(arguments[0]).column); |
668 | |
|
669 | 0 | const NullMap* data_null_map = nullptr; |
670 | 0 | const ColumnString* data_col = nullptr; |
671 | 0 | if (const auto* nullable = check_and_get_column<ColumnNullable>(jsonb_data_column.get())) { |
672 | 0 | data_col = assert_cast<const ColumnString*>(nullable->get_nested_column_ptr().get()); |
673 | 0 | data_null_map = &nullable->get_null_map_data(); |
674 | 0 | } else { |
675 | 0 | data_col = assert_cast<const ColumnString*>(jsonb_data_column.get()); |
676 | 0 | } |
677 | |
|
678 | 0 | const auto& ldata = data_col->get_chars(); |
679 | 0 | const auto& loffsets = data_col->get_offsets(); |
680 | | |
681 | | // prepare parse path column prepare |
682 | 0 | auto&& [path_column, path_const] = |
683 | 0 | unpack_if_const(block.get_by_position(arguments[1]).column); |
684 | 0 | const ColumnString* path_col = nullptr; |
685 | 0 | const NullMap* path_null_map = nullptr; |
686 | 0 | if (const auto* nullable = check_and_get_column<ColumnNullable>(path_column.get())) { |
687 | 0 | path_col = assert_cast<const ColumnString*>(nullable->get_nested_column_ptr().get()); |
688 | 0 | path_null_map = &nullable->get_null_map_data(); |
689 | 0 | } else { |
690 | 0 | path_col = assert_cast<const ColumnString*>(path_column.get()); |
691 | 0 | } |
692 | |
|
693 | 0 | DORIS_CHECK(!(jsonb_data_const && path_const)) |
694 | 0 | << "jsonb_data_const and path_const should not be both const"; |
695 | |
|
696 | 0 | auto create_all_null_result = [&]() { |
697 | 0 | auto res = ColumnType::create(); |
698 | 0 | res->insert_default(); |
699 | 0 | auto nullable_column = |
700 | 0 | ColumnNullable::create(std::move(res), ColumnUInt8::create(1, 1)); |
701 | 0 | auto const_column = ColumnConst::create(std::move(nullable_column), input_rows_count); |
702 | 0 | block.get_by_position(result).column = std::move(const_column); |
703 | 0 | return Status::OK(); |
704 | 0 | }; |
705 | |
|
706 | 0 | ColumnUInt8::MutablePtr result_null_map_column; |
707 | 0 | NullMap* result_null_map = nullptr; |
708 | 0 | if (data_null_map || path_null_map) { |
709 | 0 | result_null_map_column = ColumnUInt8::create(input_rows_count, 0); |
710 | 0 | result_null_map = &result_null_map_column->get_data(); |
711 | |
|
712 | 0 | if (data_null_map) { |
713 | 0 | VectorizedUtils::update_null_map(*result_null_map, *data_null_map, |
714 | 0 | jsonb_data_const); |
715 | 0 | } |
716 | |
|
717 | 0 | if (path_null_map) { |
718 | 0 | VectorizedUtils::update_null_map(*result_null_map, *path_null_map, path_const); |
719 | 0 | } |
720 | |
|
721 | 0 | if (!simd::contain_zero(result_null_map->data(), input_rows_count)) { |
722 | 0 | return create_all_null_result(); |
723 | 0 | } |
724 | 0 | } |
725 | | |
726 | 0 | auto res = ColumnType::create(); |
727 | |
|
728 | 0 | bool is_invalid_json_path = false; |
729 | |
|
730 | 0 | const auto& rdata = path_col->get_chars(); |
731 | 0 | const auto& roffsets = path_col->get_offsets(); |
732 | 0 | if (jsonb_data_const) { |
733 | 0 | if (data_null_map && (*data_null_map)[0]) { |
734 | 0 | return create_all_null_result(); |
735 | 0 | } |
736 | 0 | scalar_vector(context, data_col->get_data_at(0), rdata, roffsets, res->get_data(), |
737 | 0 | result_null_map, is_invalid_json_path); |
738 | 0 | } else if (path_const) { |
739 | 0 | if (path_null_map && (*path_null_map)[0]) { |
740 | 0 | return create_all_null_result(); |
741 | 0 | } |
742 | 0 | vector_scalar(context, ldata, loffsets, path_col->get_data_at(0), res->get_data(), |
743 | 0 | result_null_map, is_invalid_json_path); |
744 | 0 | } else { |
745 | 0 | vector_vector(context, ldata, loffsets, rdata, roffsets, res->get_data(), |
746 | 0 | result_null_map, is_invalid_json_path); |
747 | 0 | } |
748 | 0 | if (is_invalid_json_path) { |
749 | 0 | return Status::InvalidArgument( |
750 | 0 | "Json path error: Invalid Json Path for value: {}", |
751 | 0 | std::string_view(reinterpret_cast<const char*>(rdata.data()), rdata.size())); |
752 | 0 | } |
753 | | |
754 | 0 | if (result_null_map) { |
755 | 0 | auto nullabel_col = |
756 | 0 | ColumnNullable::create(std::move(res), std::move(result_null_map_column)); |
757 | 0 | block.get_by_position(result).column = std::move(nullabel_col); |
758 | 0 | } else { |
759 | 0 | block.get_by_position(result).column = std::move(res); |
760 | 0 | } |
761 | 0 | return Status::OK(); |
762 | 0 | } |
763 | | |
764 | | private: |
765 | | static ALWAYS_INLINE void inner_loop_impl(size_t i, Container& res, const char* l_raw_str, |
766 | 0 | size_t l_str_size, JsonbPath& path) { |
767 | | // doc is NOT necessary to be deleted since JsonbDocument will not allocate memory |
768 | 0 | const JsonbDocument* doc = nullptr; |
769 | 0 | auto st = JsonbDocument::checkAndCreateDocument(l_raw_str, l_str_size, &doc); |
770 | 0 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { |
771 | 0 | return; |
772 | 0 | } |
773 | | |
774 | | // value is NOT necessary to be deleted since JsonbValue will not allocate memory |
775 | 0 | auto result = doc->getValue()->findValue(path); |
776 | |
|
777 | 0 | if (result.value) { |
778 | 0 | res[i] = 1; |
779 | 0 | } |
780 | 0 | } |
781 | | static void vector_vector(FunctionContext* context, const ColumnString::Chars& ldata, |
782 | | const ColumnString::Offsets& loffsets, |
783 | | const ColumnString::Chars& rdata, |
784 | | const ColumnString::Offsets& roffsets, Container& res, |
785 | 0 | const NullMap* result_null_map, bool& is_invalid_json_path) { |
786 | 0 | const size_t size = loffsets.size(); |
787 | 0 | res.resize_fill(size, 0); |
788 | |
|
789 | 0 | for (size_t i = 0; i < size; i++) { |
790 | 0 | if (result_null_map && (*result_null_map)[i]) { |
791 | 0 | continue; |
792 | 0 | } |
793 | | |
794 | 0 | const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]); |
795 | 0 | int l_str_size = loffsets[i] - loffsets[i - 1]; |
796 | |
|
797 | 0 | const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]); |
798 | 0 | int r_str_size = roffsets[i] - roffsets[i - 1]; |
799 | |
|
800 | 0 | JsonbPath path; |
801 | 0 | if (!path.seek(r_raw_str, r_str_size)) { |
802 | 0 | is_invalid_json_path = true; |
803 | 0 | return; |
804 | 0 | } |
805 | | |
806 | 0 | inner_loop_impl(i, res, l_raw_str, l_str_size, path); |
807 | 0 | } |
808 | 0 | } |
809 | | static void scalar_vector(FunctionContext* context, const StringRef& ldata, |
810 | | const ColumnString::Chars& rdata, |
811 | | const ColumnString::Offsets& roffsets, Container& res, |
812 | 0 | const NullMap* result_null_map, bool& is_invalid_json_path) { |
813 | 0 | const size_t size = roffsets.size(); |
814 | 0 | res.resize_fill(size, 0); |
815 | |
|
816 | 0 | for (size_t i = 0; i < size; i++) { |
817 | 0 | if (result_null_map && (*result_null_map)[i]) { |
818 | 0 | continue; |
819 | 0 | } |
820 | 0 | const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]); |
821 | 0 | int r_str_size = roffsets[i] - roffsets[i - 1]; |
822 | |
|
823 | 0 | JsonbPath path; |
824 | 0 | if (!path.seek(r_raw_str, r_str_size)) { |
825 | 0 | is_invalid_json_path = true; |
826 | 0 | return; |
827 | 0 | } |
828 | | |
829 | 0 | inner_loop_impl(i, res, ldata.data, ldata.size, path); |
830 | 0 | } |
831 | 0 | } |
832 | | static void vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata, |
833 | | const ColumnString::Offsets& loffsets, const StringRef& rdata, |
834 | | Container& res, const NullMap* result_null_map, |
835 | 0 | bool& is_invalid_json_path) { |
836 | 0 | const size_t size = loffsets.size(); |
837 | 0 | res.resize_fill(size, 0); |
838 | |
|
839 | 0 | JsonbPath path; |
840 | 0 | if (!path.seek(rdata.data, rdata.size)) { |
841 | 0 | is_invalid_json_path = true; |
842 | 0 | return; |
843 | 0 | } |
844 | | |
845 | 0 | for (size_t i = 0; i < size; i++) { |
846 | 0 | if (result_null_map && (*result_null_map)[i]) { |
847 | 0 | continue; |
848 | 0 | } |
849 | 0 | const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]); |
850 | 0 | int l_str_size = loffsets[i] - loffsets[i - 1]; |
851 | |
|
852 | 0 | inner_loop_impl(i, res, l_raw_str, l_str_size, path); |
853 | 0 | } |
854 | 0 | } |
855 | | }; |
856 | | |
857 | | template <typename ValueType> |
858 | | struct JsonbExtractStringImpl { |
859 | | using ReturnType = typename ValueType::ReturnType; |
860 | | using ColumnType = typename ValueType::ColumnType; |
861 | | |
862 | | private: |
863 | | static ALWAYS_INLINE void inner_loop_impl(JsonbWriter* writer, size_t i, |
864 | | ColumnString::Chars& res_data, |
865 | | ColumnString::Offsets& res_offsets, NullMap& null_map, |
866 | | std::unique_ptr<JsonbToJson>& formater, |
867 | 90 | const char* l_raw, size_t l_size, JsonbPath& path) { |
868 | | // doc is NOT necessary to be deleted since JsonbDocument will not allocate memory |
869 | 90 | const JsonbDocument* doc = nullptr; |
870 | 90 | auto st = JsonbDocument::checkAndCreateDocument(l_raw, l_size, &doc); |
871 | 90 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { |
872 | 0 | StringOP::push_null_string(i, res_data, res_offsets, null_map); |
873 | 0 | return; |
874 | 0 | } |
875 | | |
876 | | // value is NOT necessary to be deleted since JsonbValue will not allocate memory |
877 | 90 | auto find_result = doc->getValue()->findValue(path); |
878 | | |
879 | 90 | if (UNLIKELY(!find_result.value)) { |
880 | 46 | StringOP::push_null_string(i, res_data, res_offsets, null_map); |
881 | 46 | return; |
882 | 46 | } |
883 | | |
884 | 44 | if constexpr (ValueType::only_get_type) { |
885 | 0 | StringOP::push_value_string(std::string_view(find_result.value->typeName()), i, |
886 | 0 | res_data, res_offsets); |
887 | 0 | return; |
888 | 44 | } else { |
889 | 44 | static_assert(std::is_same_v<DataTypeJsonb, ReturnType>); |
890 | 44 | if constexpr (ValueType::no_quotes) { |
891 | 0 | if (find_result.value->isString()) { |
892 | 0 | const auto* str_value = find_result.value->unpack<JsonbStringVal>(); |
893 | 0 | const auto* blob = str_value->getBlob(); |
894 | 0 | if (str_value->length() > 1 && blob[0] == '"' && |
895 | 0 | blob[str_value->length() - 1] == '"') { |
896 | 0 | writer->writeStartString(); |
897 | 0 | writer->writeString(blob + 1, str_value->length() - 2); |
898 | 0 | writer->writeEndString(); |
899 | 0 | StringOP::push_value_string( |
900 | 0 | std::string_view(writer->getOutput()->getBuffer(), |
901 | 0 | writer->getOutput()->getSize()), |
902 | 0 | i, res_data, res_offsets); |
903 | 0 | return; |
904 | 0 | } |
905 | 0 | } |
906 | 0 | } |
907 | 0 | writer->writeValueSimple(find_result.value); |
908 | 44 | StringOP::push_value_string(std::string_view(writer->getOutput()->getBuffer(), |
909 | 44 | writer->getOutput()->getSize()), |
910 | 44 | i, res_data, res_offsets); |
911 | 44 | } |
912 | 44 | } Unexecuted instantiation: _ZN5doris22JsonbExtractStringImplINS_13JsonbTypeTypeEE15inner_loop_implEPNS_12JsonbWriterTINS_14JsonbOutStreamEEEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNS7_IjLm4096ESA_Lm16ELm15EEESC_RSt10unique_ptrINS_11JsonbToJsonESt14default_deleteISG_EEPKcmRNS_9JsonbPathE _ZN5doris22JsonbExtractStringImplINS_13JsonbTypeJsonEE15inner_loop_implEPNS_12JsonbWriterTINS_14JsonbOutStreamEEEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNS7_IjLm4096ESA_Lm16ELm15EEESC_RSt10unique_ptrINS_11JsonbToJsonESt14default_deleteISG_EEPKcmRNS_9JsonbPathE Line | Count | Source | 867 | 90 | const char* l_raw, size_t l_size, JsonbPath& path) { | 868 | | // doc is NOT necessary to be deleted since JsonbDocument will not allocate memory | 869 | 90 | const JsonbDocument* doc = nullptr; | 870 | 90 | auto st = JsonbDocument::checkAndCreateDocument(l_raw, l_size, &doc); | 871 | 90 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { | 872 | 0 | StringOP::push_null_string(i, res_data, res_offsets, null_map); | 873 | 0 | return; | 874 | 0 | } | 875 | | | 876 | | // value is NOT necessary to be deleted since JsonbValue will not allocate memory | 877 | 90 | auto find_result = doc->getValue()->findValue(path); | 878 | | | 879 | 90 | if (UNLIKELY(!find_result.value)) { | 880 | 46 | StringOP::push_null_string(i, res_data, res_offsets, null_map); | 881 | 46 | return; | 882 | 46 | } | 883 | | | 884 | | if constexpr (ValueType::only_get_type) { | 885 | | StringOP::push_value_string(std::string_view(find_result.value->typeName()), i, | 886 | | res_data, res_offsets); | 887 | | return; | 888 | 44 | } else { | 889 | 44 | static_assert(std::is_same_v<DataTypeJsonb, ReturnType>); | 890 | | if constexpr (ValueType::no_quotes) { | 891 | | if (find_result.value->isString()) { | 892 | | const auto* str_value = find_result.value->unpack<JsonbStringVal>(); | 893 | | const auto* blob = str_value->getBlob(); | 894 | | if (str_value->length() > 1 && blob[0] == '"' && | 895 | | blob[str_value->length() - 1] == '"') { | 896 | | writer->writeStartString(); | 897 | | writer->writeString(blob + 1, str_value->length() - 2); | 898 | | writer->writeEndString(); | 899 | | StringOP::push_value_string( | 900 | | std::string_view(writer->getOutput()->getBuffer(), | 901 | | writer->getOutput()->getSize()), | 902 | | i, res_data, res_offsets); | 903 | | return; | 904 | | } | 905 | | } | 906 | | } | 907 | 44 | writer->writeValueSimple(find_result.value); | 908 | 44 | StringOP::push_value_string(std::string_view(writer->getOutput()->getBuffer(), | 909 | 44 | writer->getOutput()->getSize()), | 910 | 44 | i, res_data, res_offsets); | 911 | 44 | } | 912 | 44 | } |
Unexecuted instantiation: _ZN5doris22JsonbExtractStringImplINS_21JsonbTypeJsonNoQuotesEE15inner_loop_implEPNS_12JsonbWriterTINS_14JsonbOutStreamEEEmRNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERNS7_IjLm4096ESA_Lm16ELm15EEESC_RSt10unique_ptrINS_11JsonbToJsonESt14default_deleteISG_EEPKcmRNS_9JsonbPathE |
913 | | |
914 | | public: |
915 | | // for jsonb_extract_string |
916 | | static Status vector_vector_v2( |
917 | | FunctionContext* context, const ColumnString::Chars& ldata, |
918 | | const ColumnString::Offsets& loffsets, const NullMap* l_null_map, |
919 | | const bool& json_data_const, |
920 | | const std::vector<const ColumnString*>& rdata_columns, // here we can support more paths |
921 | | const std::vector<const NullMap*>& r_null_maps, const std::vector<bool>& path_const, |
922 | 4 | ColumnString::Chars& res_data, ColumnString::Offsets& res_offsets, NullMap& null_map) { |
923 | 4 | const size_t input_rows_count = null_map.size(); |
924 | 4 | res_offsets.resize(input_rows_count); |
925 | | |
926 | 4 | auto writer = std::make_unique<JsonbWriter>(); |
927 | 4 | std::unique_ptr<JsonbToJson> formater; |
928 | | |
929 | | // reuseable json path list, espacially for const path |
930 | 4 | std::vector<JsonbPath> json_path_list; |
931 | 4 | json_path_list.resize(rdata_columns.size()); |
932 | | |
933 | | // lambda function to parse json path for row i and path pi |
934 | 90 | auto parse_json_path = [&](size_t i, size_t pi) -> Status { |
935 | 90 | const auto index = index_check_const(i, path_const[pi]); |
936 | | |
937 | 90 | const ColumnString* path_col = rdata_columns[pi]; |
938 | 90 | const ColumnString::Chars& rdata = path_col->get_chars(); |
939 | 90 | const ColumnString::Offsets& roffsets = path_col->get_offsets(); |
940 | 90 | size_t r_off = roffsets[index - 1]; |
941 | 90 | size_t r_size = roffsets[index] - r_off; |
942 | 90 | const char* r_raw = reinterpret_cast<const char*>(&rdata[r_off]); |
943 | | |
944 | 90 | JsonbPath path; |
945 | 90 | if (!path.seek(r_raw, r_size)) { |
946 | 0 | return Status::InvalidArgument("Json path error: Invalid Json Path for value: {}", |
947 | 0 | std::string_view(r_raw, r_size)); |
948 | 0 | } |
949 | | |
950 | 90 | json_path_list[pi] = std::move(path); |
951 | | |
952 | 90 | return Status::OK(); |
953 | 90 | }; Unexecuted instantiation: _ZZN5doris22JsonbExtractStringImplINS_13JsonbTypeTypeEE16vector_vector_v2EPNS_15FunctionContextERKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS5_IjLm4096ES8_Lm16ELm15EEEPSA_RKbRKSt6vectorIPKNS_9ColumnStrIjEESaISM_EERKSI_ISF_SaISF_EERKSI_IbSaIbEERS9_RSC_SZ_ENKUlmmE_clEmm _ZZN5doris22JsonbExtractStringImplINS_13JsonbTypeJsonEE16vector_vector_v2EPNS_15FunctionContextERKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS5_IjLm4096ES8_Lm16ELm15EEEPSA_RKbRKSt6vectorIPKNS_9ColumnStrIjEESaISM_EERKSI_ISF_SaISF_EERKSI_IbSaIbEERS9_RSC_SZ_ENKUlmmE_clEmm Line | Count | Source | 934 | 90 | auto parse_json_path = [&](size_t i, size_t pi) -> Status { | 935 | 90 | const auto index = index_check_const(i, path_const[pi]); | 936 | | | 937 | 90 | const ColumnString* path_col = rdata_columns[pi]; | 938 | 90 | const ColumnString::Chars& rdata = path_col->get_chars(); | 939 | 90 | const ColumnString::Offsets& roffsets = path_col->get_offsets(); | 940 | 90 | size_t r_off = roffsets[index - 1]; | 941 | 90 | size_t r_size = roffsets[index] - r_off; | 942 | 90 | const char* r_raw = reinterpret_cast<const char*>(&rdata[r_off]); | 943 | | | 944 | 90 | JsonbPath path; | 945 | 90 | if (!path.seek(r_raw, r_size)) { | 946 | 0 | return Status::InvalidArgument("Json path error: Invalid Json Path for value: {}", | 947 | 0 | std::string_view(r_raw, r_size)); | 948 | 0 | } | 949 | | | 950 | 90 | json_path_list[pi] = std::move(path); | 951 | | | 952 | 90 | return Status::OK(); | 953 | 90 | }; |
Unexecuted instantiation: _ZZN5doris22JsonbExtractStringImplINS_21JsonbTypeJsonNoQuotesEE16vector_vector_v2EPNS_15FunctionContextERKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS5_IjLm4096ES8_Lm16ELm15EEEPSA_RKbRKSt6vectorIPKNS_9ColumnStrIjEESaISM_EERKSI_ISF_SaISF_EERKSI_IbSaIbEERS9_RSC_SZ_ENKUlmmE_clEmm |
954 | | |
955 | 8 | for (size_t pi = 0; pi < rdata_columns.size(); pi++) { |
956 | 4 | if (path_const[pi]) { |
957 | 0 | if (r_null_maps[pi] && (*r_null_maps[pi])[0]) { |
958 | 0 | continue; |
959 | 0 | } |
960 | 0 | RETURN_IF_ERROR(parse_json_path(0, pi)); |
961 | 0 | } |
962 | 4 | } |
963 | | |
964 | 4 | res_data.reserve(ldata.size()); |
965 | 98 | for (size_t i = 0; i < input_rows_count; ++i) { |
966 | 94 | if (null_map[i]) { |
967 | 0 | continue; |
968 | 0 | } |
969 | | |
970 | 94 | const auto data_index = index_check_const(i, json_data_const); |
971 | 94 | if (l_null_map && (*l_null_map)[data_index]) { |
972 | 4 | StringOP::push_null_string(i, res_data, res_offsets, null_map); |
973 | 4 | continue; |
974 | 4 | } |
975 | | |
976 | 90 | size_t l_off = loffsets[data_index - 1]; |
977 | 90 | size_t l_size = loffsets[data_index] - l_off; |
978 | 90 | const char* l_raw = reinterpret_cast<const char*>(&ldata[l_off]); |
979 | 90 | if (rdata_columns.size() == 1) { // just return origin value |
980 | 90 | const auto path_index = index_check_const(i, path_const[0]); |
981 | 90 | if (r_null_maps[0] && (*r_null_maps[0])[path_index]) { |
982 | 0 | StringOP::push_null_string(i, res_data, res_offsets, null_map); |
983 | 0 | continue; |
984 | 0 | } |
985 | | |
986 | 90 | if (!path_const[0]) { |
987 | 90 | RETURN_IF_ERROR(parse_json_path(i, 0)); |
988 | 90 | } |
989 | | |
990 | 90 | writer->reset(); |
991 | 90 | inner_loop_impl(writer.get(), i, res_data, res_offsets, null_map, formater, l_raw, |
992 | 90 | l_size, json_path_list[0]); |
993 | 90 | } else { // will make array string to user |
994 | 0 | writer->reset(); |
995 | 0 | bool has_value = false; |
996 | | |
997 | | // doc is NOT necessary to be deleted since JsonbDocument will not allocate memory |
998 | 0 | const JsonbDocument* doc = nullptr; |
999 | 0 | auto st = JsonbDocument::checkAndCreateDocument(l_raw, l_size, &doc); |
1000 | |
|
1001 | 0 | for (size_t pi = 0; pi < rdata_columns.size(); ++pi) { |
1002 | 0 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { |
1003 | 0 | continue; |
1004 | 0 | } |
1005 | | |
1006 | 0 | const auto path_index = index_check_const(i, path_const[pi]); |
1007 | 0 | if (r_null_maps[pi] && (*r_null_maps[pi])[path_index]) { |
1008 | 0 | StringOP::push_null_string(i, res_data, res_offsets, null_map); |
1009 | 0 | break; |
1010 | 0 | } |
1011 | | |
1012 | 0 | if (!path_const[pi]) { |
1013 | 0 | RETURN_IF_ERROR(parse_json_path(i, pi)); |
1014 | 0 | } |
1015 | | |
1016 | 0 | auto find_result = doc->getValue()->findValue(json_path_list[pi]); |
1017 | |
|
1018 | 0 | if (find_result.value) { |
1019 | 0 | if (!has_value) { |
1020 | 0 | has_value = true; |
1021 | 0 | writer->writeStartArray(); |
1022 | 0 | } |
1023 | 0 | if (find_result.value->isArray() && find_result.is_wildcard) { |
1024 | | // To avoid getting results of nested array like [[1, 2, 3], [4, 5, 6]], |
1025 | | // if value is array, we should write all items in array, instead of write the array itself. |
1026 | | // finaly we will get results like [1, 2, 3, 4, 5, 6] |
1027 | 0 | for (const auto& item : *find_result.value->unpack<ArrayVal>()) { |
1028 | 0 | writer->writeValue(&item); |
1029 | 0 | } |
1030 | 0 | } else { |
1031 | 0 | writer->writeValue(find_result.value); |
1032 | 0 | } |
1033 | 0 | } |
1034 | 0 | } |
1035 | 0 | if (has_value) { |
1036 | 0 | writer->writeEndArray(); |
1037 | 0 | StringOP::push_value_string(std::string_view(writer->getOutput()->getBuffer(), |
1038 | 0 | writer->getOutput()->getSize()), |
1039 | 0 | i, res_data, res_offsets); |
1040 | 0 | } else { |
1041 | 0 | StringOP::push_null_string(i, res_data, res_offsets, null_map); |
1042 | 0 | } |
1043 | 0 | } |
1044 | 90 | } //for |
1045 | 4 | return Status::OK(); |
1046 | 4 | } Unexecuted instantiation: _ZN5doris22JsonbExtractStringImplINS_13JsonbTypeTypeEE16vector_vector_v2EPNS_15FunctionContextERKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS5_IjLm4096ES8_Lm16ELm15EEEPSA_RKbRKSt6vectorIPKNS_9ColumnStrIjEESaISM_EERKSI_ISF_SaISF_EERKSI_IbSaIbEERS9_RSC_SZ_ _ZN5doris22JsonbExtractStringImplINS_13JsonbTypeJsonEE16vector_vector_v2EPNS_15FunctionContextERKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS5_IjLm4096ES8_Lm16ELm15EEEPSA_RKbRKSt6vectorIPKNS_9ColumnStrIjEESaISM_EERKSI_ISF_SaISF_EERKSI_IbSaIbEERS9_RSC_SZ_ Line | Count | Source | 922 | 4 | ColumnString::Chars& res_data, ColumnString::Offsets& res_offsets, NullMap& null_map) { | 923 | 4 | const size_t input_rows_count = null_map.size(); | 924 | 4 | res_offsets.resize(input_rows_count); | 925 | | | 926 | 4 | auto writer = std::make_unique<JsonbWriter>(); | 927 | 4 | std::unique_ptr<JsonbToJson> formater; | 928 | | | 929 | | // reuseable json path list, espacially for const path | 930 | 4 | std::vector<JsonbPath> json_path_list; | 931 | 4 | json_path_list.resize(rdata_columns.size()); | 932 | | | 933 | | // lambda function to parse json path for row i and path pi | 934 | 4 | auto parse_json_path = [&](size_t i, size_t pi) -> Status { | 935 | 4 | const auto index = index_check_const(i, path_const[pi]); | 936 | | | 937 | 4 | const ColumnString* path_col = rdata_columns[pi]; | 938 | 4 | const ColumnString::Chars& rdata = path_col->get_chars(); | 939 | 4 | const ColumnString::Offsets& roffsets = path_col->get_offsets(); | 940 | 4 | size_t r_off = roffsets[index - 1]; | 941 | 4 | size_t r_size = roffsets[index] - r_off; | 942 | 4 | const char* r_raw = reinterpret_cast<const char*>(&rdata[r_off]); | 943 | | | 944 | 4 | JsonbPath path; | 945 | 4 | if (!path.seek(r_raw, r_size)) { | 946 | 4 | return Status::InvalidArgument("Json path error: Invalid Json Path for value: {}", | 947 | 4 | std::string_view(r_raw, r_size)); | 948 | 4 | } | 949 | | | 950 | 4 | json_path_list[pi] = std::move(path); | 951 | | | 952 | 4 | return Status::OK(); | 953 | 4 | }; | 954 | | | 955 | 8 | for (size_t pi = 0; pi < rdata_columns.size(); pi++) { | 956 | 4 | if (path_const[pi]) { | 957 | 0 | if (r_null_maps[pi] && (*r_null_maps[pi])[0]) { | 958 | 0 | continue; | 959 | 0 | } | 960 | 0 | RETURN_IF_ERROR(parse_json_path(0, pi)); | 961 | 0 | } | 962 | 4 | } | 963 | | | 964 | 4 | res_data.reserve(ldata.size()); | 965 | 98 | for (size_t i = 0; i < input_rows_count; ++i) { | 966 | 94 | if (null_map[i]) { | 967 | 0 | continue; | 968 | 0 | } | 969 | | | 970 | 94 | const auto data_index = index_check_const(i, json_data_const); | 971 | 94 | if (l_null_map && (*l_null_map)[data_index]) { | 972 | 4 | StringOP::push_null_string(i, res_data, res_offsets, null_map); | 973 | 4 | continue; | 974 | 4 | } | 975 | | | 976 | 90 | size_t l_off = loffsets[data_index - 1]; | 977 | 90 | size_t l_size = loffsets[data_index] - l_off; | 978 | 90 | const char* l_raw = reinterpret_cast<const char*>(&ldata[l_off]); | 979 | 90 | if (rdata_columns.size() == 1) { // just return origin value | 980 | 90 | const auto path_index = index_check_const(i, path_const[0]); | 981 | 90 | if (r_null_maps[0] && (*r_null_maps[0])[path_index]) { | 982 | 0 | StringOP::push_null_string(i, res_data, res_offsets, null_map); | 983 | 0 | continue; | 984 | 0 | } | 985 | | | 986 | 90 | if (!path_const[0]) { | 987 | 90 | RETURN_IF_ERROR(parse_json_path(i, 0)); | 988 | 90 | } | 989 | | | 990 | 90 | writer->reset(); | 991 | 90 | inner_loop_impl(writer.get(), i, res_data, res_offsets, null_map, formater, l_raw, | 992 | 90 | l_size, json_path_list[0]); | 993 | 90 | } else { // will make array string to user | 994 | 0 | writer->reset(); | 995 | 0 | bool has_value = false; | 996 | | | 997 | | // doc is NOT necessary to be deleted since JsonbDocument will not allocate memory | 998 | 0 | const JsonbDocument* doc = nullptr; | 999 | 0 | auto st = JsonbDocument::checkAndCreateDocument(l_raw, l_size, &doc); | 1000 | |
| 1001 | 0 | for (size_t pi = 0; pi < rdata_columns.size(); ++pi) { | 1002 | 0 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { | 1003 | 0 | continue; | 1004 | 0 | } | 1005 | | | 1006 | 0 | const auto path_index = index_check_const(i, path_const[pi]); | 1007 | 0 | if (r_null_maps[pi] && (*r_null_maps[pi])[path_index]) { | 1008 | 0 | StringOP::push_null_string(i, res_data, res_offsets, null_map); | 1009 | 0 | break; | 1010 | 0 | } | 1011 | | | 1012 | 0 | if (!path_const[pi]) { | 1013 | 0 | RETURN_IF_ERROR(parse_json_path(i, pi)); | 1014 | 0 | } | 1015 | | | 1016 | 0 | auto find_result = doc->getValue()->findValue(json_path_list[pi]); | 1017 | |
| 1018 | 0 | if (find_result.value) { | 1019 | 0 | if (!has_value) { | 1020 | 0 | has_value = true; | 1021 | 0 | writer->writeStartArray(); | 1022 | 0 | } | 1023 | 0 | if (find_result.value->isArray() && find_result.is_wildcard) { | 1024 | | // To avoid getting results of nested array like [[1, 2, 3], [4, 5, 6]], | 1025 | | // if value is array, we should write all items in array, instead of write the array itself. | 1026 | | // finaly we will get results like [1, 2, 3, 4, 5, 6] | 1027 | 0 | for (const auto& item : *find_result.value->unpack<ArrayVal>()) { | 1028 | 0 | writer->writeValue(&item); | 1029 | 0 | } | 1030 | 0 | } else { | 1031 | 0 | writer->writeValue(find_result.value); | 1032 | 0 | } | 1033 | 0 | } | 1034 | 0 | } | 1035 | 0 | if (has_value) { | 1036 | 0 | writer->writeEndArray(); | 1037 | 0 | StringOP::push_value_string(std::string_view(writer->getOutput()->getBuffer(), | 1038 | 0 | writer->getOutput()->getSize()), | 1039 | 0 | i, res_data, res_offsets); | 1040 | 0 | } else { | 1041 | 0 | StringOP::push_null_string(i, res_data, res_offsets, null_map); | 1042 | 0 | } | 1043 | 0 | } | 1044 | 90 | } //for | 1045 | 4 | return Status::OK(); | 1046 | 4 | } |
Unexecuted instantiation: _ZN5doris22JsonbExtractStringImplINS_21JsonbTypeJsonNoQuotesEE16vector_vector_v2EPNS_15FunctionContextERKNS_8PODArrayIhLm4096ENS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm16ELm15EEERKNS5_IjLm4096ES8_Lm16ELm15EEEPSA_RKbRKSt6vectorIPKNS_9ColumnStrIjEESaISM_EERKSI_ISF_SaISF_EERKSI_IbSaIbEERS9_RSC_SZ_ |
1047 | | |
1048 | | static Status vector_vector(FunctionContext* context, const ColumnString::Chars& ldata, |
1049 | | const ColumnString::Offsets& loffsets, const NullMap* l_null_map, |
1050 | | const ColumnString::Chars& rdata, |
1051 | | const ColumnString::Offsets& roffsets, const NullMap* r_null_map, |
1052 | | ColumnString::Chars& res_data, ColumnString::Offsets& res_offsets, |
1053 | | NullMap& null_map) { |
1054 | | size_t input_rows_count = loffsets.size(); |
1055 | | res_offsets.resize(input_rows_count); |
1056 | | |
1057 | | std::unique_ptr<JsonbToJson> formater; |
1058 | | |
1059 | | JsonbWriter writer; |
1060 | | for (size_t i = 0; i < input_rows_count; ++i) { |
1061 | | if (l_null_map && (*l_null_map)[i]) { |
1062 | | StringOP::push_null_string(i, res_data, res_offsets, null_map); |
1063 | | continue; |
1064 | | } |
1065 | | |
1066 | | if (r_null_map && (*r_null_map)[i]) { |
1067 | | StringOP::push_null_string(i, res_data, res_offsets, null_map); |
1068 | | continue; |
1069 | | } |
1070 | | |
1071 | | int l_size = loffsets[i] - loffsets[i - 1]; |
1072 | | const char* l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]); |
1073 | | |
1074 | | int r_size = roffsets[i] - roffsets[i - 1]; |
1075 | | const char* r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]); |
1076 | | |
1077 | | JsonbPath path; |
1078 | | if (!path.seek(r_raw, r_size)) { |
1079 | | return Status::InvalidArgument( |
1080 | | "Json path error: Invalid Json Path for value: {} at row: {}", |
1081 | | std::string_view(r_raw, r_size), i); |
1082 | | } |
1083 | | |
1084 | | writer.reset(); |
1085 | | inner_loop_impl(&writer, i, res_data, res_offsets, null_map, formater, l_raw, l_size, |
1086 | | path); |
1087 | | } //for |
1088 | | return Status::OK(); |
1089 | | } //function |
1090 | | |
1091 | | static Status vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata, |
1092 | | const ColumnString::Offsets& loffsets, const NullMap* l_null_map, |
1093 | | const StringRef& rdata, ColumnString::Chars& res_data, |
1094 | | ColumnString::Offsets& res_offsets, NullMap& null_map) { |
1095 | | size_t input_rows_count = loffsets.size(); |
1096 | | res_offsets.resize(input_rows_count); |
1097 | | |
1098 | | std::unique_ptr<JsonbToJson> formater; |
1099 | | |
1100 | | JsonbPath path; |
1101 | | if (!path.seek(rdata.data, rdata.size)) { |
1102 | | return Status::InvalidArgument("Json path error: Invalid Json Path for value: {}", |
1103 | | std::string_view(rdata.data, rdata.size)); |
1104 | | } |
1105 | | |
1106 | | JsonbWriter writer; |
1107 | | for (size_t i = 0; i < input_rows_count; ++i) { |
1108 | | if (l_null_map && (*l_null_map)[i]) { |
1109 | | StringOP::push_null_string(i, res_data, res_offsets, null_map); |
1110 | | continue; |
1111 | | } |
1112 | | |
1113 | | int l_size = loffsets[i] - loffsets[i - 1]; |
1114 | | const char* l_raw = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]); |
1115 | | |
1116 | | writer.reset(); |
1117 | | inner_loop_impl(&writer, i, res_data, res_offsets, null_map, formater, l_raw, l_size, |
1118 | | path); |
1119 | | } //for |
1120 | | return Status::OK(); |
1121 | | } //function |
1122 | | |
1123 | | static Status scalar_vector(FunctionContext* context, const StringRef& ldata, |
1124 | | const ColumnString::Chars& rdata, |
1125 | | const ColumnString::Offsets& roffsets, const NullMap* r_null_map, |
1126 | | ColumnString::Chars& res_data, ColumnString::Offsets& res_offsets, |
1127 | | NullMap& null_map) { |
1128 | | size_t input_rows_count = roffsets.size(); |
1129 | | res_offsets.resize(input_rows_count); |
1130 | | |
1131 | | std::unique_ptr<JsonbToJson> formater; |
1132 | | |
1133 | | JsonbWriter writer; |
1134 | | |
1135 | | for (size_t i = 0; i < input_rows_count; ++i) { |
1136 | | if (r_null_map && (*r_null_map)[i]) { |
1137 | | StringOP::push_null_string(i, res_data, res_offsets, null_map); |
1138 | | continue; |
1139 | | } |
1140 | | |
1141 | | int r_size = roffsets[i] - roffsets[i - 1]; |
1142 | | const char* r_raw = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]); |
1143 | | |
1144 | | JsonbPath path; |
1145 | | if (!path.seek(r_raw, r_size)) { |
1146 | | return Status::InvalidArgument( |
1147 | | "Json path error: Invalid Json Path for value: {} at row: {}", |
1148 | | std::string_view(r_raw, r_size), i); |
1149 | | } |
1150 | | |
1151 | | writer.reset(); |
1152 | | inner_loop_impl(&writer, i, res_data, res_offsets, null_map, formater, ldata.data, |
1153 | | ldata.size, path); |
1154 | | } //for |
1155 | | return Status::OK(); |
1156 | | } //function |
1157 | | }; |
1158 | | |
1159 | | struct JsonbExtractIsnull { |
1160 | | static constexpr auto name = "json_extract_isnull"; |
1161 | | static constexpr auto alias = "jsonb_extract_isnull"; |
1162 | | |
1163 | | using ReturnType = DataTypeUInt8; |
1164 | | using ColumnType = ColumnUInt8; |
1165 | | using Container = typename ColumnType::Container; |
1166 | | |
1167 | | private: |
1168 | | static ALWAYS_INLINE void inner_loop_impl(size_t i, Container& res, NullMap& null_map, |
1169 | | const char* l_raw_str, size_t l_str_size, |
1170 | 0 | JsonbPath& path) { |
1171 | 0 | if (null_map[i]) { |
1172 | 0 | res[i] = 0; |
1173 | 0 | return; |
1174 | 0 | } |
1175 | | |
1176 | | // doc is NOT necessary to be deleted since JsonbDocument will not allocate memory |
1177 | 0 | const JsonbDocument* doc = nullptr; |
1178 | 0 | auto st = JsonbDocument::checkAndCreateDocument(l_raw_str, l_str_size, &doc); |
1179 | 0 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { |
1180 | 0 | null_map[i] = 1; |
1181 | 0 | res[i] = 0; |
1182 | 0 | return; |
1183 | 0 | } |
1184 | | |
1185 | | // value is NOT necessary to be deleted since JsonbValue will not allocate memory |
1186 | 0 | auto find_result = doc->getValue()->findValue(path); |
1187 | 0 | const auto* value = find_result.value; |
1188 | |
|
1189 | 0 | if (UNLIKELY(!value)) { |
1190 | 0 | null_map[i] = 1; |
1191 | 0 | res[i] = 0; |
1192 | 0 | return; |
1193 | 0 | } |
1194 | | |
1195 | 0 | res[i] = value->isNull(); |
1196 | 0 | } |
1197 | | |
1198 | | public: |
1199 | | // for jsonb_extract_int/int64/double |
1200 | | static Status vector_vector(FunctionContext* context, const ColumnString::Chars& ldata, |
1201 | | const ColumnString::Offsets& loffsets, const NullMap* l_null_map, |
1202 | | const ColumnString::Chars& rdata, |
1203 | | const ColumnString::Offsets& roffsets, const NullMap* r_null_map, |
1204 | 0 | Container& res, NullMap& null_map) { |
1205 | 0 | size_t size = loffsets.size(); |
1206 | 0 | res.resize(size); |
1207 | |
|
1208 | 0 | for (size_t i = 0; i < loffsets.size(); i++) { |
1209 | 0 | if ((l_null_map && (*l_null_map)[i]) || (r_null_map && (*r_null_map)[i])) { |
1210 | 0 | res[i] = 0; |
1211 | 0 | null_map[i] = 1; |
1212 | 0 | continue; |
1213 | 0 | } |
1214 | | |
1215 | 0 | const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]); |
1216 | 0 | int l_str_size = loffsets[i] - loffsets[i - 1]; |
1217 | |
|
1218 | 0 | const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]); |
1219 | 0 | int r_str_size = roffsets[i] - roffsets[i - 1]; |
1220 | |
|
1221 | 0 | JsonbPath path; |
1222 | 0 | if (!path.seek(r_raw_str, r_str_size)) { |
1223 | 0 | return Status::InvalidArgument( |
1224 | 0 | "Json path error: Invalid Json Path for value: {} at row: {}", |
1225 | 0 | std::string_view(r_raw_str, r_str_size), i); |
1226 | 0 | } |
1227 | | |
1228 | 0 | inner_loop_impl(i, res, null_map, l_raw_str, l_str_size, path); |
1229 | 0 | } //for |
1230 | 0 | return Status::OK(); |
1231 | 0 | } //function |
1232 | | |
1233 | | static Status scalar_vector(FunctionContext* context, const StringRef& ldata, |
1234 | | const ColumnString::Chars& rdata, |
1235 | | const ColumnString::Offsets& roffsets, const NullMap* r_null_map, |
1236 | 0 | Container& res, NullMap& null_map) { |
1237 | 0 | size_t size = roffsets.size(); |
1238 | 0 | res.resize(size); |
1239 | |
|
1240 | 0 | for (size_t i = 0; i < size; i++) { |
1241 | 0 | if (r_null_map && (*r_null_map)[i]) { |
1242 | 0 | res[i] = 0; |
1243 | 0 | null_map[i] = 1; |
1244 | 0 | continue; |
1245 | 0 | } |
1246 | | |
1247 | 0 | const char* r_raw_str = reinterpret_cast<const char*>(&rdata[roffsets[i - 1]]); |
1248 | 0 | int r_str_size = roffsets[i] - roffsets[i - 1]; |
1249 | |
|
1250 | 0 | JsonbPath path; |
1251 | 0 | if (!path.seek(r_raw_str, r_str_size)) { |
1252 | 0 | return Status::InvalidArgument( |
1253 | 0 | "Json path error: Invalid Json Path for value: {} at row: {}", |
1254 | 0 | std::string_view(r_raw_str, r_str_size), i); |
1255 | 0 | } |
1256 | | |
1257 | 0 | inner_loop_impl(i, res, null_map, ldata.data, ldata.size, path); |
1258 | 0 | } //for |
1259 | 0 | return Status::OK(); |
1260 | 0 | } //function |
1261 | | |
1262 | | static Status vector_scalar(FunctionContext* context, const ColumnString::Chars& ldata, |
1263 | | const ColumnString::Offsets& loffsets, const NullMap* l_null_map, |
1264 | 0 | const StringRef& rdata, Container& res, NullMap& null_map) { |
1265 | 0 | size_t size = loffsets.size(); |
1266 | 0 | res.resize(size); |
1267 | |
|
1268 | 0 | JsonbPath path; |
1269 | 0 | if (!path.seek(rdata.data, rdata.size)) { |
1270 | 0 | return Status::InvalidArgument("Json path error: Invalid Json Path for value: {}", |
1271 | 0 | std::string_view(rdata.data, rdata.size)); |
1272 | 0 | } |
1273 | | |
1274 | 0 | for (size_t i = 0; i < loffsets.size(); i++) { |
1275 | 0 | if (l_null_map && (*l_null_map)[i]) { |
1276 | 0 | res[i] = 0; |
1277 | 0 | null_map[i] = 1; |
1278 | 0 | continue; |
1279 | 0 | } |
1280 | | |
1281 | 0 | const char* l_raw_str = reinterpret_cast<const char*>(&ldata[loffsets[i - 1]]); |
1282 | 0 | int l_str_size = loffsets[i] - loffsets[i - 1]; |
1283 | |
|
1284 | 0 | inner_loop_impl(i, res, null_map, l_raw_str, l_str_size, path); |
1285 | 0 | } //for |
1286 | 0 | return Status::OK(); |
1287 | 0 | } //function |
1288 | | }; |
1289 | | |
1290 | | struct JsonbTypeJson { |
1291 | | using T = std::string; |
1292 | | using ReturnType = DataTypeJsonb; |
1293 | | using ColumnType = ColumnString; |
1294 | | static const bool only_get_type = false; |
1295 | | static const bool no_quotes = false; |
1296 | | }; |
1297 | | |
1298 | | struct JsonbTypeJsonNoQuotes { |
1299 | | using T = std::string; |
1300 | | using ReturnType = DataTypeJsonb; |
1301 | | using ColumnType = ColumnString; |
1302 | | static const bool only_get_type = false; |
1303 | | static const bool no_quotes = true; |
1304 | | }; |
1305 | | |
1306 | | struct JsonbTypeType { |
1307 | | using T = std::string; |
1308 | | using ReturnType = DataTypeString; |
1309 | | using ColumnType = ColumnString; |
1310 | | static const bool only_get_type = true; |
1311 | | static const bool no_quotes = false; |
1312 | | }; |
1313 | | |
1314 | | struct JsonbExtractJsonb : public JsonbExtractStringImpl<JsonbTypeJson> { |
1315 | | static constexpr auto name = "jsonb_extract"; |
1316 | | static constexpr auto alias = "json_extract"; |
1317 | | }; |
1318 | | |
1319 | | struct JsonbExtractJsonbNoQuotes : public JsonbExtractStringImpl<JsonbTypeJsonNoQuotes> { |
1320 | | static constexpr auto name = "jsonb_extract_no_quotes"; |
1321 | | static constexpr auto alias = "json_extract_no_quotes"; |
1322 | | }; |
1323 | | |
1324 | | struct JsonbTypeImpl : public JsonbExtractStringImpl<JsonbTypeType> { |
1325 | | static constexpr auto name = "json_type"; |
1326 | | static constexpr auto alias = "jsonb_type"; |
1327 | | }; |
1328 | | |
1329 | | using FunctionJsonbExists = FunctionJsonbExtractPath; |
1330 | | using FunctionJsonbType = FunctionJsonbExtract<JsonbTypeImpl>; |
1331 | | |
1332 | | using FunctionJsonbExtractIsnull = FunctionJsonbExtract<JsonbExtractIsnull>; |
1333 | | using FunctionJsonbExtractJsonb = FunctionJsonbExtract<JsonbExtractJsonb>; |
1334 | | using FunctionJsonbExtractJsonbNoQuotes = FunctionJsonbExtract<JsonbExtractJsonbNoQuotes>; |
1335 | | |
1336 | | template <typename Impl> |
1337 | | class FunctionJsonbLength : public IFunction { |
1338 | | public: |
1339 | | static constexpr auto name = "json_length"; |
1340 | 1 | String get_name() const override { return name; } |
1341 | 4 | static FunctionPtr create() { return std::make_shared<FunctionJsonbLength<Impl>>(); } |
1342 | | |
1343 | 2 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
1344 | 2 | return make_nullable(std::make_shared<DataTypeInt32>()); |
1345 | 2 | } |
1346 | 3 | DataTypes get_variadic_argument_types_impl() const override { |
1347 | 3 | return Impl::get_variadic_argument_types(); |
1348 | 3 | } |
1349 | 2 | size_t get_number_of_arguments() const override { |
1350 | 2 | return get_variadic_argument_types_impl().size(); |
1351 | 2 | } |
1352 | | |
1353 | 4 | bool use_default_implementation_for_nulls() const override { return false; } |
1354 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
1355 | 2 | uint32_t result, size_t input_rows_count) const override { |
1356 | 2 | return Impl::execute_impl(context, block, arguments, result, input_rows_count); |
1357 | 2 | } |
1358 | | }; |
1359 | | |
1360 | | struct JsonbLengthUtil { |
1361 | | static Status jsonb_length_execute(FunctionContext* context, Block& block, |
1362 | | const ColumnNumbers& arguments, uint32_t result, |
1363 | 2 | size_t input_rows_count) { |
1364 | 2 | DORIS_CHECK_GE(arguments.size(), 2); |
1365 | 2 | ColumnPtr jsonb_data_column; |
1366 | 2 | bool jsonb_data_const = false; |
1367 | | // prepare jsonb data column |
1368 | 2 | std::tie(jsonb_data_column, jsonb_data_const) = |
1369 | 2 | unpack_if_const(block.get_by_position(arguments[0]).column); |
1370 | 2 | ColumnPtr path_column; |
1371 | 2 | bool is_const = false; |
1372 | 2 | std::tie(path_column, is_const) = |
1373 | 2 | unpack_if_const(block.get_by_position(arguments[1]).column); |
1374 | | |
1375 | 2 | auto null_map = ColumnUInt8::create(input_rows_count, 0); |
1376 | 2 | auto return_type = block.get_data_type(result); |
1377 | 2 | MutableColumnPtr res = return_type->create_column(); |
1378 | | |
1379 | 2 | JsonbPath path; |
1380 | 2 | if (is_const) { |
1381 | 1 | if (path_column->is_null_at(0)) { |
1382 | 2 | for (size_t i = 0; i < input_rows_count; ++i) { |
1383 | 1 | null_map->get_data()[i] = 1; |
1384 | 1 | res->insert_data(nullptr, 0); |
1385 | 1 | } |
1386 | | |
1387 | 1 | block.replace_by_position( |
1388 | 1 | result, ColumnNullable::create(std::move(res), std::move(null_map))); |
1389 | 1 | return Status::OK(); |
1390 | 1 | } |
1391 | | |
1392 | 0 | auto path_value = path_column->get_data_at(0); |
1393 | 0 | if (!path.seek(path_value.data, path_value.size)) { |
1394 | 0 | return Status::InvalidArgument("Json path error: Invalid Json Path for value: {}", |
1395 | 0 | std::string_view(path_value.data, path_value.size)); |
1396 | 0 | } |
1397 | 0 | } |
1398 | | |
1399 | 5 | for (size_t i = 0; i < input_rows_count; ++i) { |
1400 | 4 | if (jsonb_data_column->is_null_at(i) || path_column->is_null_at(i) || |
1401 | 4 | (jsonb_data_column->get_data_at(i).size == 0)) { |
1402 | 1 | null_map->get_data()[i] = 1; |
1403 | 1 | res->insert_data(nullptr, 0); |
1404 | 1 | continue; |
1405 | 1 | } |
1406 | 3 | if (!is_const) { |
1407 | 3 | auto path_value = path_column->get_data_at(i); |
1408 | 3 | path.clean(); |
1409 | 3 | if (!path.seek(path_value.data, path_value.size)) { |
1410 | 0 | return Status::InvalidArgument( |
1411 | 0 | "Json path error: Invalid Json Path for value: {}", |
1412 | 0 | std::string_view(path_value.data, path_value.size)); |
1413 | 0 | } |
1414 | 3 | } |
1415 | 3 | auto jsonb_value = jsonb_data_column->get_data_at(i); |
1416 | | // doc is NOT necessary to be deleted since JsonbDocument will not allocate memory |
1417 | 3 | const JsonbDocument* doc = nullptr; |
1418 | 3 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(jsonb_value.data, |
1419 | 3 | jsonb_value.size, &doc)); |
1420 | 3 | auto find_result = doc->getValue()->findValue(path); |
1421 | 3 | const auto* value = find_result.value; |
1422 | 3 | if (UNLIKELY(!value)) { |
1423 | 0 | null_map->get_data()[i] = 1; |
1424 | 0 | res->insert_data(nullptr, 0); |
1425 | 0 | continue; |
1426 | 0 | } |
1427 | 3 | auto length = value->numElements(); |
1428 | 3 | res->insert_data(const_cast<const char*>((char*)&length), 0); |
1429 | 3 | } |
1430 | 1 | block.replace_by_position(result, |
1431 | 1 | ColumnNullable::create(std::move(res), std::move(null_map))); |
1432 | 1 | return Status::OK(); |
1433 | 1 | } |
1434 | | }; |
1435 | | |
1436 | | struct JsonbLengthAndPathImpl { |
1437 | 3 | static DataTypes get_variadic_argument_types() { |
1438 | 3 | return {std::make_shared<DataTypeJsonb>(), std::make_shared<DataTypeString>()}; |
1439 | 3 | } |
1440 | | |
1441 | | static Status execute_impl(FunctionContext* context, Block& block, |
1442 | | const ColumnNumbers& arguments, uint32_t result, |
1443 | 2 | size_t input_rows_count) { |
1444 | 2 | return JsonbLengthUtil::jsonb_length_execute(context, block, arguments, result, |
1445 | 2 | input_rows_count); |
1446 | 2 | } |
1447 | | }; |
1448 | | |
1449 | | template <typename Impl> |
1450 | | class FunctionJsonbContains : public IFunction { |
1451 | | public: |
1452 | | static constexpr auto name = "json_contains"; |
1453 | 1 | String get_name() const override { return name; } |
1454 | 4 | static FunctionPtr create() { return std::make_shared<FunctionJsonbContains<Impl>>(); } |
1455 | | |
1456 | 2 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
1457 | 2 | return make_nullable(std::make_shared<DataTypeUInt8>()); |
1458 | 2 | } |
1459 | 3 | DataTypes get_variadic_argument_types_impl() const override { |
1460 | 3 | return Impl::get_variadic_argument_types(); |
1461 | 3 | } |
1462 | 2 | size_t get_number_of_arguments() const override { |
1463 | 2 | return get_variadic_argument_types_impl().size(); |
1464 | 2 | } |
1465 | | |
1466 | 4 | bool use_default_implementation_for_nulls() const override { return false; } |
1467 | | |
1468 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
1469 | 2 | uint32_t result, size_t input_rows_count) const override { |
1470 | 2 | return Impl::execute_impl(context, block, arguments, result, input_rows_count); |
1471 | 2 | } |
1472 | | }; |
1473 | | |
1474 | | struct JsonbContainsUtil { |
1475 | | static Status jsonb_contains_execute(FunctionContext* context, Block& block, |
1476 | | const ColumnNumbers& arguments, uint32_t result, |
1477 | 2 | size_t input_rows_count) { |
1478 | 2 | DORIS_CHECK_GE(arguments.size(), 3); |
1479 | | |
1480 | 2 | auto jsonb_data1_column = block.get_by_position(arguments[0]).column; |
1481 | 2 | auto jsonb_data2_column = block.get_by_position(arguments[1]).column; |
1482 | | |
1483 | 2 | ColumnPtr path_column; |
1484 | 2 | bool is_const = false; |
1485 | 2 | std::tie(path_column, is_const) = |
1486 | 2 | unpack_if_const(block.get_by_position(arguments[2]).column); |
1487 | | |
1488 | 2 | auto null_map = ColumnUInt8::create(input_rows_count, 0); |
1489 | 2 | auto return_type = block.get_data_type(result); |
1490 | 2 | MutableColumnPtr res = return_type->create_column(); |
1491 | | |
1492 | 2 | JsonbPath path; |
1493 | 2 | if (is_const) { |
1494 | 1 | if (path_column->is_null_at(0)) { |
1495 | 2 | for (size_t i = 0; i < input_rows_count; ++i) { |
1496 | 1 | null_map->get_data()[i] = 1; |
1497 | 1 | res->insert_data(nullptr, 0); |
1498 | 1 | } |
1499 | | |
1500 | 1 | block.replace_by_position( |
1501 | 1 | result, ColumnNullable::create(std::move(res), std::move(null_map))); |
1502 | 1 | return Status::OK(); |
1503 | 1 | } |
1504 | | |
1505 | 0 | auto path_value = path_column->get_data_at(0); |
1506 | 0 | if (!path.seek(path_value.data, path_value.size)) { |
1507 | 0 | return Status::InvalidArgument("Json path error: Invalid Json Path for value: {}", |
1508 | 0 | std::string_view(path_value.data, path_value.size)); |
1509 | 0 | } |
1510 | 0 | } |
1511 | | |
1512 | 5 | for (size_t i = 0; i < input_rows_count; ++i) { |
1513 | 4 | if (jsonb_data1_column->is_null_at(i) || jsonb_data2_column->is_null_at(i) || |
1514 | 4 | path_column->is_null_at(i)) { |
1515 | 1 | null_map->get_data()[i] = 1; |
1516 | 1 | res->insert_data(nullptr, 0); |
1517 | 1 | continue; |
1518 | 1 | } |
1519 | | |
1520 | 3 | if (!is_const) { |
1521 | 3 | auto path_value = path_column->get_data_at(i); |
1522 | 3 | path.clean(); |
1523 | 3 | if (!path.seek(path_value.data, path_value.size)) { |
1524 | 0 | return Status::InvalidArgument( |
1525 | 0 | "Json path error: Invalid Json Path for value: {}", |
1526 | 0 | std::string_view(path_value.data, path_value.size)); |
1527 | 0 | } |
1528 | 3 | } |
1529 | | |
1530 | 3 | auto jsonb_value1 = jsonb_data1_column->get_data_at(i); |
1531 | 3 | auto jsonb_value2 = jsonb_data2_column->get_data_at(i); |
1532 | | |
1533 | 3 | if (jsonb_value1.size == 0 || jsonb_value2.size == 0) { |
1534 | 1 | null_map->get_data()[i] = 1; |
1535 | 1 | res->insert_data(nullptr, 0); |
1536 | 1 | continue; |
1537 | 1 | } |
1538 | | // doc is NOT necessary to be deleted since JsonbDocument will not allocate memory |
1539 | 2 | const JsonbDocument* doc1 = nullptr; |
1540 | 2 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(jsonb_value1.data, |
1541 | 2 | jsonb_value1.size, &doc1)); |
1542 | 2 | const JsonbDocument* doc2 = nullptr; |
1543 | 2 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(jsonb_value2.data, |
1544 | 2 | jsonb_value2.size, &doc2)); |
1545 | | |
1546 | 2 | auto find_result = doc1->getValue()->findValue(path); |
1547 | 2 | const auto* value1 = find_result.value; |
1548 | 2 | const JsonbValue* value2 = doc2->getValue(); |
1549 | 2 | if (!value1 || !value2) { |
1550 | 0 | null_map->get_data()[i] = 1; |
1551 | 0 | res->insert_data(nullptr, 0); |
1552 | 0 | continue; |
1553 | 0 | } |
1554 | 2 | auto contains_value = value1->contains(value2); |
1555 | 2 | res->insert_data(const_cast<const char*>((char*)&contains_value), 0); |
1556 | 2 | } |
1557 | | |
1558 | 1 | block.replace_by_position(result, |
1559 | 1 | ColumnNullable::create(std::move(res), std::move(null_map))); |
1560 | 1 | return Status::OK(); |
1561 | 1 | } |
1562 | | }; |
1563 | | |
1564 | | template <bool ignore_null> |
1565 | | class FunctionJsonbArray : public IFunction { |
1566 | | public: |
1567 | | static constexpr auto name = "json_array"; |
1568 | | static constexpr auto alias = "jsonb_array"; |
1569 | | |
1570 | 6 | static FunctionPtr create() { return std::make_shared<FunctionJsonbArray>(); }_ZN5doris18FunctionJsonbArrayILb0EE6createEv Line | Count | Source | 1570 | 3 | static FunctionPtr create() { return std::make_shared<FunctionJsonbArray>(); } |
_ZN5doris18FunctionJsonbArrayILb1EE6createEv Line | Count | Source | 1570 | 3 | static FunctionPtr create() { return std::make_shared<FunctionJsonbArray>(); } |
|
1571 | | |
1572 | 0 | String get_name() const override { return name; }Unexecuted instantiation: _ZNK5doris18FunctionJsonbArrayILb0EE8get_nameB5cxx11Ev Unexecuted instantiation: _ZNK5doris18FunctionJsonbArrayILb1EE8get_nameB5cxx11Ev |
1573 | | |
1574 | 0 | size_t get_number_of_arguments() const override { return 0; }Unexecuted instantiation: _ZNK5doris18FunctionJsonbArrayILb0EE23get_number_of_argumentsEv Unexecuted instantiation: _ZNK5doris18FunctionJsonbArrayILb1EE23get_number_of_argumentsEv |
1575 | 4 | bool is_variadic() const override { return true; }_ZNK5doris18FunctionJsonbArrayILb0EE11is_variadicEv Line | Count | Source | 1575 | 2 | bool is_variadic() const override { return true; } |
_ZNK5doris18FunctionJsonbArrayILb1EE11is_variadicEv Line | Count | Source | 1575 | 2 | bool is_variadic() const override { return true; } |
|
1576 | | |
1577 | 4 | bool use_default_implementation_for_nulls() const override { return false; }_ZNK5doris18FunctionJsonbArrayILb0EE36use_default_implementation_for_nullsEv Line | Count | Source | 1577 | 2 | bool use_default_implementation_for_nulls() const override { return false; } |
_ZNK5doris18FunctionJsonbArrayILb1EE36use_default_implementation_for_nullsEv Line | Count | Source | 1577 | 2 | bool use_default_implementation_for_nulls() const override { return false; } |
|
1578 | | |
1579 | 2 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
1580 | 2 | return std::make_shared<DataTypeJsonb>(); |
1581 | 2 | } _ZNK5doris18FunctionJsonbArrayILb0EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS6_EE Line | Count | Source | 1579 | 1 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { | 1580 | 1 | return std::make_shared<DataTypeJsonb>(); | 1581 | 1 | } |
_ZNK5doris18FunctionJsonbArrayILb1EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS6_EE Line | Count | Source | 1579 | 1 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { | 1580 | 1 | return std::make_shared<DataTypeJsonb>(); | 1581 | 1 | } |
|
1582 | | |
1583 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
1584 | 2 | uint32_t result, size_t input_rows_count) const override { |
1585 | 2 | auto return_data_type = std::make_shared<DataTypeJsonb>(); |
1586 | 2 | auto column = return_data_type->create_column(); |
1587 | 2 | column->reserve(input_rows_count); |
1588 | | |
1589 | 2 | JsonbWriter writer; |
1590 | 23 | for (size_t i = 0; i < input_rows_count; ++i) { |
1591 | 20 | writer.writeStartArray(); |
1592 | 20 | for (auto argument : arguments) { |
1593 | 20 | auto&& [arg_column, is_const] = |
1594 | 20 | unpack_if_const(block.get_by_position(argument).column); |
1595 | 20 | if (const auto* nullable_column = |
1596 | 20 | check_and_get_column<ColumnNullable>(arg_column.get())) { |
1597 | 20 | const auto& null_map = nullable_column->get_null_map_data(); |
1598 | 20 | const auto& nested_column = nullable_column->get_nested_column(); |
1599 | 20 | const auto& jsonb_column = |
1600 | 20 | assert_cast<const ColumnString&, TypeCheckOnRelease::DISABLE>( |
1601 | 20 | nested_column); |
1602 | | |
1603 | 20 | auto index = index_check_const(i, is_const); |
1604 | 20 | if (null_map[index]) { |
1605 | 2 | if constexpr (ignore_null) { |
1606 | 1 | continue; |
1607 | 1 | } else { |
1608 | 1 | writer.writeNull(); |
1609 | 1 | } |
1610 | 18 | } else { |
1611 | 18 | auto jsonb_binary = jsonb_column.get_data_at(index); |
1612 | 18 | const JsonbDocument* doc = nullptr; |
1613 | 18 | auto st = JsonbDocument::checkAndCreateDocument(jsonb_binary.data, |
1614 | 18 | jsonb_binary.size, &doc); |
1615 | 18 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { |
1616 | 0 | if constexpr (ignore_null) { |
1617 | 0 | continue; |
1618 | 0 | } else { |
1619 | 0 | writer.writeNull(); |
1620 | 0 | } |
1621 | 18 | } else { |
1622 | 18 | writer.writeValue(doc->getValue()); |
1623 | 18 | } |
1624 | 18 | } |
1625 | 20 | } else { |
1626 | 0 | const auto& jsonb_column = |
1627 | 0 | assert_cast<const ColumnString&, TypeCheckOnRelease::DISABLE>( |
1628 | 0 | *arg_column); |
1629 | |
|
1630 | 0 | auto index = index_check_const(i, is_const); |
1631 | 0 | auto jsonb_binary = jsonb_column.get_data_at(index); |
1632 | 0 | const JsonbDocument* doc = nullptr; |
1633 | 0 | auto st = JsonbDocument::checkAndCreateDocument(jsonb_binary.data, |
1634 | 0 | jsonb_binary.size, &doc); |
1635 | 0 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { |
1636 | 0 | if constexpr (ignore_null) { |
1637 | 0 | continue; |
1638 | 0 | } else { |
1639 | 0 | writer.writeNull(); |
1640 | 0 | } |
1641 | 0 | } else { |
1642 | 0 | writer.writeValue(doc->getValue()); |
1643 | 0 | } |
1644 | 0 | } |
1645 | 20 | } |
1646 | 11 | writer.writeEndArray(); |
1647 | 11 | column->insert_data(writer.getOutput()->getBuffer(), writer.getOutput()->getSize()); |
1648 | 11 | writer.reset(); |
1649 | 11 | } |
1650 | | |
1651 | 2 | block.get_by_position(result).column = std::move(column); |
1652 | 2 | return Status::OK(); |
1653 | 2 | } _ZNK5doris18FunctionJsonbArrayILb0EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm Line | Count | Source | 1584 | 1 | uint32_t result, size_t input_rows_count) const override { | 1585 | 1 | auto return_data_type = std::make_shared<DataTypeJsonb>(); | 1586 | 1 | auto column = return_data_type->create_column(); | 1587 | 1 | column->reserve(input_rows_count); | 1588 | | | 1589 | 1 | JsonbWriter writer; | 1590 | 11 | for (size_t i = 0; i < input_rows_count; ++i) { | 1591 | 10 | writer.writeStartArray(); | 1592 | 10 | for (auto argument : arguments) { | 1593 | 10 | auto&& [arg_column, is_const] = | 1594 | 10 | unpack_if_const(block.get_by_position(argument).column); | 1595 | 10 | if (const auto* nullable_column = | 1596 | 10 | check_and_get_column<ColumnNullable>(arg_column.get())) { | 1597 | 10 | const auto& null_map = nullable_column->get_null_map_data(); | 1598 | 10 | const auto& nested_column = nullable_column->get_nested_column(); | 1599 | 10 | const auto& jsonb_column = | 1600 | 10 | assert_cast<const ColumnString&, TypeCheckOnRelease::DISABLE>( | 1601 | 10 | nested_column); | 1602 | | | 1603 | 10 | auto index = index_check_const(i, is_const); | 1604 | 10 | if (null_map[index]) { | 1605 | | if constexpr (ignore_null) { | 1606 | | continue; | 1607 | 1 | } else { | 1608 | 1 | writer.writeNull(); | 1609 | 1 | } | 1610 | 9 | } else { | 1611 | 9 | auto jsonb_binary = jsonb_column.get_data_at(index); | 1612 | 9 | const JsonbDocument* doc = nullptr; | 1613 | 9 | auto st = JsonbDocument::checkAndCreateDocument(jsonb_binary.data, | 1614 | 9 | jsonb_binary.size, &doc); | 1615 | 9 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { | 1616 | | if constexpr (ignore_null) { | 1617 | | continue; | 1618 | 0 | } else { | 1619 | 0 | writer.writeNull(); | 1620 | 0 | } | 1621 | 9 | } else { | 1622 | 9 | writer.writeValue(doc->getValue()); | 1623 | 9 | } | 1624 | 9 | } | 1625 | 10 | } else { | 1626 | 0 | const auto& jsonb_column = | 1627 | 0 | assert_cast<const ColumnString&, TypeCheckOnRelease::DISABLE>( | 1628 | 0 | *arg_column); | 1629 | |
| 1630 | 0 | auto index = index_check_const(i, is_const); | 1631 | 0 | auto jsonb_binary = jsonb_column.get_data_at(index); | 1632 | 0 | const JsonbDocument* doc = nullptr; | 1633 | 0 | auto st = JsonbDocument::checkAndCreateDocument(jsonb_binary.data, | 1634 | 0 | jsonb_binary.size, &doc); | 1635 | 0 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { | 1636 | | if constexpr (ignore_null) { | 1637 | | continue; | 1638 | 0 | } else { | 1639 | 0 | writer.writeNull(); | 1640 | 0 | } | 1641 | 0 | } else { | 1642 | 0 | writer.writeValue(doc->getValue()); | 1643 | 0 | } | 1644 | 0 | } | 1645 | 10 | } | 1646 | 10 | writer.writeEndArray(); | 1647 | 10 | column->insert_data(writer.getOutput()->getBuffer(), writer.getOutput()->getSize()); | 1648 | 10 | writer.reset(); | 1649 | 10 | } | 1650 | | | 1651 | 1 | block.get_by_position(result).column = std::move(column); | 1652 | 1 | return Status::OK(); | 1653 | 1 | } |
_ZNK5doris18FunctionJsonbArrayILb1EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm Line | Count | Source | 1584 | 1 | uint32_t result, size_t input_rows_count) const override { | 1585 | 1 | auto return_data_type = std::make_shared<DataTypeJsonb>(); | 1586 | 1 | auto column = return_data_type->create_column(); | 1587 | 1 | column->reserve(input_rows_count); | 1588 | | | 1589 | 1 | JsonbWriter writer; | 1590 | 12 | for (size_t i = 0; i < input_rows_count; ++i) { | 1591 | 10 | writer.writeStartArray(); | 1592 | 10 | for (auto argument : arguments) { | 1593 | 10 | auto&& [arg_column, is_const] = | 1594 | 10 | unpack_if_const(block.get_by_position(argument).column); | 1595 | 10 | if (const auto* nullable_column = | 1596 | 10 | check_and_get_column<ColumnNullable>(arg_column.get())) { | 1597 | 10 | const auto& null_map = nullable_column->get_null_map_data(); | 1598 | 10 | const auto& nested_column = nullable_column->get_nested_column(); | 1599 | 10 | const auto& jsonb_column = | 1600 | 10 | assert_cast<const ColumnString&, TypeCheckOnRelease::DISABLE>( | 1601 | 10 | nested_column); | 1602 | | | 1603 | 10 | auto index = index_check_const(i, is_const); | 1604 | 10 | if (null_map[index]) { | 1605 | 1 | if constexpr (ignore_null) { | 1606 | 1 | continue; | 1607 | | } else { | 1608 | | writer.writeNull(); | 1609 | | } | 1610 | 9 | } else { | 1611 | 9 | auto jsonb_binary = jsonb_column.get_data_at(index); | 1612 | 9 | const JsonbDocument* doc = nullptr; | 1613 | 9 | auto st = JsonbDocument::checkAndCreateDocument(jsonb_binary.data, | 1614 | 9 | jsonb_binary.size, &doc); | 1615 | 9 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { | 1616 | 0 | if constexpr (ignore_null) { | 1617 | 0 | continue; | 1618 | | } else { | 1619 | | writer.writeNull(); | 1620 | | } | 1621 | 9 | } else { | 1622 | 9 | writer.writeValue(doc->getValue()); | 1623 | 9 | } | 1624 | 9 | } | 1625 | 10 | } else { | 1626 | 0 | const auto& jsonb_column = | 1627 | 0 | assert_cast<const ColumnString&, TypeCheckOnRelease::DISABLE>( | 1628 | 0 | *arg_column); | 1629 | |
| 1630 | 0 | auto index = index_check_const(i, is_const); | 1631 | 0 | auto jsonb_binary = jsonb_column.get_data_at(index); | 1632 | 0 | const JsonbDocument* doc = nullptr; | 1633 | 0 | auto st = JsonbDocument::checkAndCreateDocument(jsonb_binary.data, | 1634 | 0 | jsonb_binary.size, &doc); | 1635 | 0 | if (!st.ok() || !doc || !doc->getValue()) [[unlikely]] { | 1636 | 0 | if constexpr (ignore_null) { | 1637 | 0 | continue; | 1638 | | } else { | 1639 | | writer.writeNull(); | 1640 | | } | 1641 | 0 | } else { | 1642 | 0 | writer.writeValue(doc->getValue()); | 1643 | 0 | } | 1644 | 0 | } | 1645 | 10 | } | 1646 | 11 | writer.writeEndArray(); | 1647 | 11 | column->insert_data(writer.getOutput()->getBuffer(), writer.getOutput()->getSize()); | 1648 | 11 | writer.reset(); | 1649 | 11 | } | 1650 | | | 1651 | 2 | block.get_by_position(result).column = std::move(column); | 1652 | 2 | return Status::OK(); | 1653 | 1 | } |
|
1654 | | }; |
1655 | | |
1656 | | class FunctionJsonbObject : public IFunction { |
1657 | | public: |
1658 | | static constexpr auto name = "json_object"; |
1659 | | static constexpr auto alias = "jsonb_object"; |
1660 | | |
1661 | 2 | static FunctionPtr create() { return std::make_shared<FunctionJsonbObject>(); } |
1662 | | |
1663 | 0 | String get_name() const override { return name; } |
1664 | | |
1665 | 0 | size_t get_number_of_arguments() const override { return 0; } |
1666 | 1 | bool is_variadic() const override { return true; } |
1667 | | |
1668 | 0 | bool use_default_implementation_for_nulls() const override { return false; } |
1669 | | |
1670 | 0 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
1671 | 0 | return std::make_shared<DataTypeJsonb>(); |
1672 | 0 | } |
1673 | | |
1674 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
1675 | 0 | uint32_t result, size_t input_rows_count) const override { |
1676 | 0 | if (arguments.size() % 2 != 0) { |
1677 | 0 | return Status::InvalidArgument( |
1678 | 0 | "JSON object must have an even number of arguments, but got: {}", |
1679 | 0 | arguments.size()); |
1680 | 0 | } |
1681 | | |
1682 | 0 | auto return_data_type = std::make_shared<DataTypeJsonb>(); |
1683 | |
|
1684 | 0 | auto write_key = [](JsonbWriter& writer, const ColumnString& key_col, const bool is_const, |
1685 | 0 | const NullMap* null_map, const size_t arg_index, const size_t row_idx) { |
1686 | 0 | auto index = index_check_const(row_idx, is_const); |
1687 | 0 | if (null_map && (*null_map)[index]) { |
1688 | 0 | return Status::InvalidArgument( |
1689 | 0 | "JSON documents may not contain NULL member name(argument " |
1690 | 0 | "index: " |
1691 | 0 | "{}, row index: {})", |
1692 | 0 | row_idx, arg_index); |
1693 | 0 | } |
1694 | | |
1695 | 0 | auto key_string = key_col.get_data_at(index); |
1696 | 0 | if (key_string.size > 255) { |
1697 | 0 | return Status::InvalidArgument( |
1698 | 0 | "JSON object keys(argument index: {}) must be less than 256 " |
1699 | 0 | "bytes, but got size: {}", |
1700 | 0 | arg_index, key_string.size); |
1701 | 0 | } |
1702 | 0 | writer.writeKey(key_string.data, static_cast<uint8_t>(key_string.size)); |
1703 | 0 | return Status::OK(); |
1704 | 0 | }; |
1705 | |
|
1706 | 0 | auto write_value = [](JsonbWriter& writer, const ColumnString& value_col, |
1707 | 0 | const bool is_const, const NullMap* null_map, const size_t arg_index, |
1708 | 0 | const size_t row_idx) { |
1709 | 0 | auto index = index_check_const(row_idx, is_const); |
1710 | 0 | if (null_map && (*null_map)[index]) { |
1711 | 0 | writer.writeNull(); |
1712 | 0 | return Status::OK(); |
1713 | 0 | } |
1714 | | |
1715 | 0 | auto value_string = value_col.get_data_at(index); |
1716 | 0 | const JsonbDocument* doc = nullptr; |
1717 | 0 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(value_string.data, |
1718 | 0 | value_string.size, &doc)); |
1719 | 0 | writer.writeValue(doc->getValue()); |
1720 | 0 | return Status::OK(); |
1721 | 0 | }; |
1722 | |
|
1723 | 0 | for (size_t arg_idx = 0; arg_idx != arguments.size(); arg_idx += 2) { |
1724 | 0 | auto key_argument = arguments[arg_idx]; |
1725 | 0 | auto value_argument = arguments[arg_idx + 1]; |
1726 | |
|
1727 | 0 | auto& key_data_type = block.get_by_position(key_argument).type; |
1728 | 0 | auto& value_data_type = block.get_by_position(value_argument).type; |
1729 | 0 | if (!is_string_type(key_data_type->get_primitive_type())) { |
1730 | 0 | return Status::InvalidArgument( |
1731 | 0 | "JSON object key(argument index: {}) must be String, but got type: " |
1732 | 0 | "{}(primitive type: {})", |
1733 | 0 | arg_idx, key_data_type->get_name(), |
1734 | 0 | static_cast<int>(key_data_type->get_primitive_type())); |
1735 | 0 | } |
1736 | | |
1737 | 0 | if (value_data_type->get_primitive_type() != PrimitiveType::TYPE_JSONB) { |
1738 | 0 | return Status::InvalidArgument( |
1739 | 0 | "JSON object value(argument index: {}) must be JSON, but got type: {}", |
1740 | 0 | arg_idx, value_data_type->get_name()); |
1741 | 0 | } |
1742 | 0 | } |
1743 | | |
1744 | 0 | auto column = return_data_type->create_column(); |
1745 | 0 | column->reserve(input_rows_count); |
1746 | |
|
1747 | 0 | JsonbWriter writer; |
1748 | 0 | for (size_t i = 0; i != input_rows_count; ++i) { |
1749 | 0 | writer.writeStartObject(); |
1750 | 0 | for (size_t arg_idx = 0; arg_idx != arguments.size(); arg_idx += 2) { |
1751 | 0 | auto key_argument = arguments[arg_idx]; |
1752 | 0 | auto value_argument = arguments[arg_idx + 1]; |
1753 | 0 | auto&& [key_column, key_const] = |
1754 | 0 | unpack_if_const(block.get_by_position(key_argument).column); |
1755 | 0 | auto&& [value_column, value_const] = |
1756 | 0 | unpack_if_const(block.get_by_position(value_argument).column); |
1757 | |
|
1758 | 0 | if (const auto* nullable_column = |
1759 | 0 | check_and_get_column<ColumnNullable>(key_column.get())) { |
1760 | 0 | const auto& null_map = nullable_column->get_null_map_data(); |
1761 | 0 | const auto& nested_column = nullable_column->get_nested_column(); |
1762 | 0 | const auto& key_arg_column = |
1763 | 0 | assert_cast<const ColumnString&, TypeCheckOnRelease::DISABLE>( |
1764 | 0 | nested_column); |
1765 | |
|
1766 | 0 | RETURN_IF_ERROR( |
1767 | 0 | write_key(writer, key_arg_column, key_const, &null_map, arg_idx, i)); |
1768 | 0 | } else { |
1769 | 0 | const auto& key_arg_column = |
1770 | 0 | assert_cast<const ColumnString&, TypeCheckOnRelease::DISABLE>( |
1771 | 0 | *key_column); |
1772 | 0 | RETURN_IF_ERROR( |
1773 | 0 | write_key(writer, key_arg_column, key_const, nullptr, arg_idx, i)); |
1774 | 0 | } |
1775 | | |
1776 | 0 | if (const auto* nullable_column = |
1777 | 0 | check_and_get_column<ColumnNullable>(value_column.get())) { |
1778 | 0 | const auto& null_map = nullable_column->get_null_map_data(); |
1779 | 0 | const auto& nested_column = nullable_column->get_nested_column(); |
1780 | 0 | const auto& value_arg_column = |
1781 | 0 | assert_cast<const ColumnString&, TypeCheckOnRelease::DISABLE>( |
1782 | 0 | nested_column); |
1783 | |
|
1784 | 0 | RETURN_IF_ERROR(write_value(writer, value_arg_column, value_const, &null_map, |
1785 | 0 | arg_idx + 1, i)); |
1786 | 0 | } else { |
1787 | 0 | const auto& value_arg_column = |
1788 | 0 | assert_cast<const ColumnString&, TypeCheckOnRelease::DISABLE>( |
1789 | 0 | *value_column); |
1790 | 0 | RETURN_IF_ERROR(write_value(writer, value_arg_column, value_const, nullptr, |
1791 | 0 | arg_idx + 1, i)); |
1792 | 0 | } |
1793 | 0 | } |
1794 | | |
1795 | 0 | writer.writeEndObject(); |
1796 | 0 | column->insert_data(writer.getOutput()->getBuffer(), writer.getOutput()->getSize()); |
1797 | 0 | writer.reset(); |
1798 | 0 | } |
1799 | | |
1800 | 0 | block.get_by_position(result).column = std::move(column); |
1801 | 0 | return Status::OK(); |
1802 | 0 | } |
1803 | | }; |
1804 | | |
1805 | | enum class JsonbModifyType { Insert, Set, Replace }; |
1806 | | |
1807 | | template <JsonbModifyType modify_type> |
1808 | | struct JsonbModifyName { |
1809 | | static constexpr auto name = "jsonb_modify"; |
1810 | | static constexpr auto alias = "json_modify"; |
1811 | | }; |
1812 | | |
1813 | | template <> |
1814 | | struct JsonbModifyName<JsonbModifyType::Insert> { |
1815 | | static constexpr auto name = "jsonb_insert"; |
1816 | | static constexpr auto alias = "json_insert"; |
1817 | | }; |
1818 | | template <> |
1819 | | struct JsonbModifyName<JsonbModifyType::Set> { |
1820 | | static constexpr auto name = "jsonb_set"; |
1821 | | static constexpr auto alias = "json_set"; |
1822 | | }; |
1823 | | template <> |
1824 | | struct JsonbModifyName<JsonbModifyType::Replace> { |
1825 | | static constexpr auto name = "jsonb_replace"; |
1826 | | static constexpr auto alias = "json_replace"; |
1827 | | }; |
1828 | | |
1829 | | template <JsonbModifyType modify_type> |
1830 | | class FunctionJsonbModify : public IFunction { |
1831 | | public: |
1832 | | static constexpr auto name = JsonbModifyName<modify_type>::name; |
1833 | | static constexpr auto alias = JsonbModifyName<modify_type>::alias; |
1834 | | |
1835 | 8 | static FunctionPtr create() { return std::make_shared<FunctionJsonbModify<modify_type>>(); }_ZN5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE0EE6createEv Line | Count | Source | 1835 | 3 | static FunctionPtr create() { return std::make_shared<FunctionJsonbModify<modify_type>>(); } |
_ZN5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE1EE6createEv Line | Count | Source | 1835 | 3 | static FunctionPtr create() { return std::make_shared<FunctionJsonbModify<modify_type>>(); } |
_ZN5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE2EE6createEv Line | Count | Source | 1835 | 2 | static FunctionPtr create() { return std::make_shared<FunctionJsonbModify<modify_type>>(); } |
|
1836 | | |
1837 | 0 | String get_name() const override { return name; }Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE0EE8get_nameB5cxx11Ev Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE1EE8get_nameB5cxx11Ev Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE2EE8get_nameB5cxx11Ev |
1838 | | |
1839 | 0 | size_t get_number_of_arguments() const override { return 0; }Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE0EE23get_number_of_argumentsEv Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE1EE23get_number_of_argumentsEv Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE2EE23get_number_of_argumentsEv |
1840 | 5 | bool is_variadic() const override { return true; }_ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE0EE11is_variadicEv Line | Count | Source | 1840 | 2 | bool is_variadic() const override { return true; } |
_ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE1EE11is_variadicEv Line | Count | Source | 1840 | 2 | bool is_variadic() const override { return true; } |
_ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE2EE11is_variadicEv Line | Count | Source | 1840 | 1 | bool is_variadic() const override { return true; } |
|
1841 | | |
1842 | 4 | bool use_default_implementation_for_nulls() const override { return false; }_ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE0EE36use_default_implementation_for_nullsEv Line | Count | Source | 1842 | 2 | bool use_default_implementation_for_nulls() const override { return false; } |
_ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE1EE36use_default_implementation_for_nullsEv Line | Count | Source | 1842 | 2 | bool use_default_implementation_for_nulls() const override { return false; } |
Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE2EE36use_default_implementation_for_nullsEv |
1843 | | |
1844 | 2 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
1845 | 2 | return make_nullable(std::make_shared<DataTypeJsonb>()); |
1846 | 2 | } _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE0EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE Line | Count | Source | 1844 | 1 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { | 1845 | 1 | return make_nullable(std::make_shared<DataTypeJsonb>()); | 1846 | 1 | } |
_ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE1EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE Line | Count | Source | 1844 | 1 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { | 1845 | 1 | return make_nullable(std::make_shared<DataTypeJsonb>()); | 1846 | 1 | } |
Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE2EE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE |
1847 | | |
1848 | | Status create_all_null_result(const DataTypePtr& return_data_type, Block& block, |
1849 | 0 | uint32_t result, size_t input_rows_count) const { |
1850 | 0 | auto result_column = return_data_type->create_column(); |
1851 | 0 | result_column->insert_default(); |
1852 | 0 | auto const_column = ColumnConst::create(std::move(result_column), input_rows_count); |
1853 | 0 | block.get_by_position(result).column = std::move(const_column); |
1854 | 0 | return Status::OK(); |
1855 | 0 | } Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE0EE22create_all_null_resultERKSt10shared_ptrIKNS_9IDataTypeEERNS_5BlockEjm Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE1EE22create_all_null_resultERKSt10shared_ptrIKNS_9IDataTypeEERNS_5BlockEjm Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE2EE22create_all_null_resultERKSt10shared_ptrIKNS_9IDataTypeEERNS_5BlockEjm |
1856 | | |
1857 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
1858 | 2 | uint32_t result, size_t input_rows_count) const override { |
1859 | 2 | if (arguments.size() % 2 != 1 || arguments.size() < 3) { |
1860 | 0 | return Status::InvalidArgument( |
1861 | 0 | "Function {} must have an odd number of arguments and more than 2 arguments, " |
1862 | 0 | "but got: {}", |
1863 | 0 | name, arguments.size()); |
1864 | 0 | } |
1865 | | |
1866 | 2 | const size_t keys_count = (arguments.size() - 1) / 2; |
1867 | | |
1868 | 2 | auto return_data_type = make_nullable(std::make_shared<DataTypeJsonb>()); |
1869 | | |
1870 | 2 | auto result_column = return_data_type->create_column(); |
1871 | 2 | auto& result_nullable_col = assert_cast<ColumnNullable&>(*result_column); |
1872 | 2 | auto& null_map = result_nullable_col.get_null_map_data(); |
1873 | 2 | auto& res_string_column = |
1874 | 2 | assert_cast<ColumnString&>(result_nullable_col.get_nested_column()); |
1875 | 2 | auto& res_chars = res_string_column.get_chars(); |
1876 | 2 | auto& res_offsets = res_string_column.get_offsets(); |
1877 | | |
1878 | 2 | null_map.resize_fill(input_rows_count, 0); |
1879 | 2 | res_offsets.resize(input_rows_count); |
1880 | 2 | auto&& [json_data_arg_column, json_data_const] = |
1881 | 2 | unpack_if_const(block.get_by_position(arguments[0]).column); |
1882 | | |
1883 | 2 | if (json_data_const) { |
1884 | 0 | if (json_data_arg_column->is_null_at(0)) { |
1885 | 0 | return create_all_null_result(return_data_type, block, result, input_rows_count); |
1886 | 0 | } |
1887 | 0 | } |
1888 | | |
1889 | 2 | std::vector<const ColumnString*> json_path_columns(keys_count); |
1890 | 2 | std::vector<bool> json_path_constant(keys_count); |
1891 | 2 | std::vector<const NullMap*> json_path_null_maps(keys_count, nullptr); |
1892 | | |
1893 | 2 | std::vector<const ColumnString*> json_value_columns(keys_count); |
1894 | 2 | std::vector<bool> json_value_constant(keys_count); |
1895 | 2 | std::vector<const NullMap*> json_value_null_maps(keys_count, nullptr); |
1896 | | |
1897 | 2 | const NullMap* json_data_null_map = nullptr; |
1898 | 2 | const ColumnString* json_data_column; |
1899 | 2 | if (const auto* nullable_column = |
1900 | 2 | check_and_get_column<ColumnNullable>(json_data_arg_column.get())) { |
1901 | 2 | json_data_null_map = &nullable_column->get_null_map_data(); |
1902 | 2 | const auto& nested_column = nullable_column->get_nested_column(); |
1903 | 2 | json_data_column = assert_cast<const ColumnString*>(&nested_column); |
1904 | 2 | } else { |
1905 | 0 | json_data_column = assert_cast<const ColumnString*>(json_data_arg_column.get()); |
1906 | 0 | } |
1907 | | |
1908 | 4 | for (size_t i = 1; i < arguments.size(); i += 2) { |
1909 | 2 | auto&& [path_column, path_const] = |
1910 | 2 | unpack_if_const(block.get_by_position(arguments[i]).column); |
1911 | 2 | auto&& [value_column, value_const] = |
1912 | 2 | unpack_if_const(block.get_by_position(arguments[i + 1]).column); |
1913 | | |
1914 | 2 | if (path_const) { |
1915 | 0 | if (path_column->is_null_at(0)) { |
1916 | 0 | return create_all_null_result(return_data_type, block, result, |
1917 | 0 | input_rows_count); |
1918 | 0 | } |
1919 | 0 | } |
1920 | | |
1921 | 2 | json_path_constant[i / 2] = path_const; |
1922 | 2 | if (const auto* nullable_column = |
1923 | 2 | check_and_get_column<ColumnNullable>(path_column.get())) { |
1924 | 2 | json_path_null_maps[i / 2] = &nullable_column->get_null_map_data(); |
1925 | 2 | const auto& nested_column = nullable_column->get_nested_column(); |
1926 | 2 | json_path_columns[i / 2] = assert_cast<const ColumnString*>(&nested_column); |
1927 | 2 | } else { |
1928 | 0 | json_path_columns[i / 2] = assert_cast<const ColumnString*>(path_column.get()); |
1929 | 0 | } |
1930 | | |
1931 | 2 | json_value_constant[i / 2] = value_const; |
1932 | 2 | if (const auto* nullable_column = |
1933 | 2 | check_and_get_column<ColumnNullable>(value_column.get())) { |
1934 | 2 | json_value_null_maps[i / 2] = &nullable_column->get_null_map_data(); |
1935 | 2 | const auto& nested_column = nullable_column->get_nested_column(); |
1936 | 2 | json_value_columns[i / 2] = assert_cast<const ColumnString*>(&nested_column); |
1937 | 2 | } else { |
1938 | 0 | json_value_columns[i / 2] = assert_cast<const ColumnString*>(value_column.get()); |
1939 | 0 | } |
1940 | 2 | } |
1941 | | |
1942 | 2 | DorisVector<const JsonbDocument*> json_documents(input_rows_count); |
1943 | 2 | if (json_data_const) { |
1944 | 0 | auto json_data_string = json_data_column->get_data_at(0); |
1945 | 0 | const JsonbDocument* doc = nullptr; |
1946 | 0 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(json_data_string.data, |
1947 | 0 | json_data_string.size, &doc)); |
1948 | 0 | if (!doc || !doc->getValue()) [[unlikely]] { |
1949 | 0 | return create_all_null_result(return_data_type, block, result, input_rows_count); |
1950 | 0 | } |
1951 | 0 | for (size_t i = 0; i != input_rows_count; ++i) { |
1952 | 0 | json_documents[i] = doc; |
1953 | 0 | } |
1954 | 2 | } else { |
1955 | 8 | for (size_t i = 0; i != input_rows_count; ++i) { |
1956 | 6 | if (json_data_null_map && (*json_data_null_map)[i]) { |
1957 | 0 | null_map[i] = 1; |
1958 | 0 | json_documents[i] = nullptr; |
1959 | 0 | continue; |
1960 | 0 | } |
1961 | | |
1962 | 6 | auto json_data_string = json_data_column->get_data_at(i); |
1963 | 6 | const JsonbDocument* doc = nullptr; |
1964 | 6 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(json_data_string.data, |
1965 | 6 | json_data_string.size, &doc)); |
1966 | 6 | if (!doc || !doc->getValue()) [[unlikely]] { |
1967 | 0 | null_map[i] = 1; |
1968 | 0 | continue; |
1969 | 0 | } |
1970 | 6 | json_documents[i] = doc; |
1971 | 6 | } |
1972 | 2 | } |
1973 | | |
1974 | 2 | DorisVector<DorisVector<JsonbPath>> json_paths(keys_count); |
1975 | 2 | DorisVector<DorisVector<const JsonbValue*>> json_values(keys_count); |
1976 | | |
1977 | 2 | RETURN_IF_ERROR(parse_paths_and_values(json_paths, json_values, arguments, input_rows_count, |
1978 | 2 | json_path_columns, json_path_constant, |
1979 | 2 | json_path_null_maps, json_value_columns, |
1980 | 2 | json_value_constant, json_value_null_maps)); |
1981 | | |
1982 | 2 | JsonbWriter writer; |
1983 | 2 | struct DocumentBuffer { |
1984 | 2 | DorisUniqueBufferPtr<char> ptr; |
1985 | 2 | size_t size = 0; |
1986 | 2 | size_t capacity = 0; |
1987 | 2 | }; |
1988 | | |
1989 | 2 | DocumentBuffer tmp_buffer; |
1990 | | |
1991 | 8 | for (size_t row_idx = 0; row_idx != input_rows_count; ++row_idx) { |
1992 | 12 | for (size_t i = 1; i < arguments.size(); i += 2) { |
1993 | 6 | const size_t index = i / 2; |
1994 | 6 | auto& json_path = json_paths[index]; |
1995 | 6 | auto& json_value = json_values[index]; |
1996 | | |
1997 | 6 | const auto path_index = index_check_const(row_idx, json_path_constant[index]); |
1998 | 6 | const auto value_index = index_check_const(row_idx, json_value_constant[index]); |
1999 | | |
2000 | 6 | if (null_map[row_idx]) { |
2001 | 0 | continue; |
2002 | 0 | } |
2003 | | |
2004 | 6 | if (json_documents[row_idx] == nullptr) { |
2005 | 0 | null_map[row_idx] = 1; |
2006 | 0 | continue; |
2007 | 0 | } |
2008 | | |
2009 | 6 | if (json_path_null_maps[index] && (*json_path_null_maps[index])[path_index]) { |
2010 | 0 | null_map[row_idx] = 1; |
2011 | 0 | continue; |
2012 | 0 | } |
2013 | | |
2014 | 6 | auto find_result = |
2015 | 6 | json_documents[row_idx]->getValue()->findValue(json_path[path_index]); |
2016 | | |
2017 | 6 | if (find_result.is_wildcard) { |
2018 | 0 | return Status::InvalidArgument( |
2019 | 0 | " In this situation, path expressions may not contain the * and ** " |
2020 | 0 | "tokens or an array range, argument index: {}, row index: {}", |
2021 | 0 | i, row_idx); |
2022 | 0 | } |
2023 | | |
2024 | 6 | if constexpr (modify_type == JsonbModifyType::Insert) { |
2025 | 3 | if (find_result.value) { |
2026 | 0 | continue; |
2027 | 0 | } |
2028 | 3 | } else if constexpr (modify_type == JsonbModifyType::Replace) { |
2029 | 0 | if (!find_result.value) { |
2030 | 0 | continue; |
2031 | 0 | } |
2032 | 0 | } |
2033 | | |
2034 | 3 | std::vector<const JsonbValue*> parents; |
2035 | | |
2036 | 6 | bool replace = false; |
2037 | 6 | parents.emplace_back(json_documents[row_idx]->getValue()); |
2038 | 6 | const auto legs_count = json_path[path_index].get_leg_vector_size(); |
2039 | 6 | if (find_result.value) { |
2040 | | // find target path, replace it with the new value. |
2041 | 0 | replace = true; |
2042 | 0 | if (!build_parents_by_path(json_documents[row_idx]->getValue(), |
2043 | 0 | json_path[path_index], parents)) { |
2044 | 0 | continue; |
2045 | 0 | } |
2046 | 6 | } else { |
2047 | | // does not find target path, insert the new value. |
2048 | 6 | JsonbPath new_path; |
2049 | 6 | DCHECK_GT(legs_count, 0); |
2050 | 10 | for (size_t j = 0; j + 1 < legs_count; ++j) { |
2051 | 4 | auto* current_leg = json_path[path_index].get_leg_from_leg_vector(j); |
2052 | 4 | std::unique_ptr<leg_info> leg = std::make_unique<leg_info>( |
2053 | 4 | current_leg->leg_ptr, current_leg->leg_len, |
2054 | 4 | current_leg->array_index, current_leg->type); |
2055 | 4 | new_path.add_leg_to_leg_vector(std::move(leg)); |
2056 | 4 | } |
2057 | | |
2058 | 6 | if (!build_parents_by_path(json_documents[row_idx]->getValue(), new_path, |
2059 | 6 | parents)) { |
2060 | 0 | continue; |
2061 | 0 | } |
2062 | 6 | } |
2063 | | |
2064 | 6 | leg_info* last_leg = |
2065 | 6 | legs_count > 0 |
2066 | 6 | ? json_path[path_index].get_leg_from_leg_vector(legs_count - 1) |
2067 | 6 | : nullptr; |
2068 | 6 | RETURN_IF_ERROR(write_json_value(json_documents[row_idx]->getValue(), parents, 0, |
2069 | 6 | json_value[value_index], replace, last_leg, |
2070 | 6 | writer)); |
2071 | | |
2072 | 6 | auto* writer_output = writer.getOutput(); |
2073 | 6 | if (writer_output->getSize() > tmp_buffer.capacity) { |
2074 | 2 | tmp_buffer.capacity = |
2075 | 2 | ((size_t(writer_output->getSize()) + 1024 - 1) / 1024) * 1024; |
2076 | 2 | tmp_buffer.ptr = make_unique_buffer<char>(tmp_buffer.capacity); |
2077 | 2 | DCHECK_LE(writer_output->getSize(), tmp_buffer.capacity); |
2078 | 2 | } |
2079 | | |
2080 | 6 | memcpy(tmp_buffer.ptr.get(), writer_output->getBuffer(), writer_output->getSize()); |
2081 | 6 | tmp_buffer.size = writer_output->getSize(); |
2082 | | |
2083 | 6 | writer.reset(); |
2084 | | |
2085 | 6 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument( |
2086 | 6 | tmp_buffer.ptr.get(), tmp_buffer.size, &json_documents[row_idx])); |
2087 | 6 | } |
2088 | | |
2089 | 6 | if (!null_map[row_idx]) { |
2090 | 6 | const auto* jsonb_document = json_documents[row_idx]; |
2091 | 6 | const auto size = jsonb_document->numPackedBytes(); |
2092 | 6 | res_chars.insert(reinterpret_cast<const char*>(jsonb_document), |
2093 | 6 | reinterpret_cast<const char*>(jsonb_document) + size); |
2094 | 6 | } |
2095 | | |
2096 | 6 | res_offsets[row_idx] = static_cast<uint32_t>(res_chars.size()); |
2097 | | |
2098 | 6 | if (!null_map[row_idx]) { |
2099 | 6 | auto* ptr = res_chars.data() + res_offsets[row_idx - 1]; |
2100 | 6 | auto size = res_offsets[row_idx] - res_offsets[row_idx - 1]; |
2101 | 6 | const JsonbDocument* doc = nullptr; |
2102 | 6 | THROW_IF_ERROR(JsonbDocument::checkAndCreateDocument( |
2103 | 6 | reinterpret_cast<const char*>(ptr), size, &doc)); |
2104 | 6 | } |
2105 | 6 | } |
2106 | | |
2107 | 2 | block.get_by_position(result).column = std::move(result_column); |
2108 | 2 | return Status::OK(); |
2109 | 2 | } _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE0EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm Line | Count | Source | 1858 | 1 | uint32_t result, size_t input_rows_count) const override { | 1859 | 1 | if (arguments.size() % 2 != 1 || arguments.size() < 3) { | 1860 | 0 | return Status::InvalidArgument( | 1861 | 0 | "Function {} must have an odd number of arguments and more than 2 arguments, " | 1862 | 0 | "but got: {}", | 1863 | 0 | name, arguments.size()); | 1864 | 0 | } | 1865 | | | 1866 | 1 | const size_t keys_count = (arguments.size() - 1) / 2; | 1867 | | | 1868 | 1 | auto return_data_type = make_nullable(std::make_shared<DataTypeJsonb>()); | 1869 | | | 1870 | 1 | auto result_column = return_data_type->create_column(); | 1871 | 1 | auto& result_nullable_col = assert_cast<ColumnNullable&>(*result_column); | 1872 | 1 | auto& null_map = result_nullable_col.get_null_map_data(); | 1873 | 1 | auto& res_string_column = | 1874 | 1 | assert_cast<ColumnString&>(result_nullable_col.get_nested_column()); | 1875 | 1 | auto& res_chars = res_string_column.get_chars(); | 1876 | 1 | auto& res_offsets = res_string_column.get_offsets(); | 1877 | | | 1878 | 1 | null_map.resize_fill(input_rows_count, 0); | 1879 | 1 | res_offsets.resize(input_rows_count); | 1880 | 1 | auto&& [json_data_arg_column, json_data_const] = | 1881 | 1 | unpack_if_const(block.get_by_position(arguments[0]).column); | 1882 | | | 1883 | 1 | if (json_data_const) { | 1884 | 0 | if (json_data_arg_column->is_null_at(0)) { | 1885 | 0 | return create_all_null_result(return_data_type, block, result, input_rows_count); | 1886 | 0 | } | 1887 | 0 | } | 1888 | | | 1889 | 1 | std::vector<const ColumnString*> json_path_columns(keys_count); | 1890 | 1 | std::vector<bool> json_path_constant(keys_count); | 1891 | 1 | std::vector<const NullMap*> json_path_null_maps(keys_count, nullptr); | 1892 | | | 1893 | 1 | std::vector<const ColumnString*> json_value_columns(keys_count); | 1894 | 1 | std::vector<bool> json_value_constant(keys_count); | 1895 | 1 | std::vector<const NullMap*> json_value_null_maps(keys_count, nullptr); | 1896 | | | 1897 | 1 | const NullMap* json_data_null_map = nullptr; | 1898 | 1 | const ColumnString* json_data_column; | 1899 | 1 | if (const auto* nullable_column = | 1900 | 1 | check_and_get_column<ColumnNullable>(json_data_arg_column.get())) { | 1901 | 1 | json_data_null_map = &nullable_column->get_null_map_data(); | 1902 | 1 | const auto& nested_column = nullable_column->get_nested_column(); | 1903 | 1 | json_data_column = assert_cast<const ColumnString*>(&nested_column); | 1904 | 1 | } else { | 1905 | 0 | json_data_column = assert_cast<const ColumnString*>(json_data_arg_column.get()); | 1906 | 0 | } | 1907 | | | 1908 | 2 | for (size_t i = 1; i < arguments.size(); i += 2) { | 1909 | 1 | auto&& [path_column, path_const] = | 1910 | 1 | unpack_if_const(block.get_by_position(arguments[i]).column); | 1911 | 1 | auto&& [value_column, value_const] = | 1912 | 1 | unpack_if_const(block.get_by_position(arguments[i + 1]).column); | 1913 | | | 1914 | 1 | if (path_const) { | 1915 | 0 | if (path_column->is_null_at(0)) { | 1916 | 0 | return create_all_null_result(return_data_type, block, result, | 1917 | 0 | input_rows_count); | 1918 | 0 | } | 1919 | 0 | } | 1920 | | | 1921 | 1 | json_path_constant[i / 2] = path_const; | 1922 | 1 | if (const auto* nullable_column = | 1923 | 1 | check_and_get_column<ColumnNullable>(path_column.get())) { | 1924 | 1 | json_path_null_maps[i / 2] = &nullable_column->get_null_map_data(); | 1925 | 1 | const auto& nested_column = nullable_column->get_nested_column(); | 1926 | 1 | json_path_columns[i / 2] = assert_cast<const ColumnString*>(&nested_column); | 1927 | 1 | } else { | 1928 | 0 | json_path_columns[i / 2] = assert_cast<const ColumnString*>(path_column.get()); | 1929 | 0 | } | 1930 | | | 1931 | 1 | json_value_constant[i / 2] = value_const; | 1932 | 1 | if (const auto* nullable_column = | 1933 | 1 | check_and_get_column<ColumnNullable>(value_column.get())) { | 1934 | 1 | json_value_null_maps[i / 2] = &nullable_column->get_null_map_data(); | 1935 | 1 | const auto& nested_column = nullable_column->get_nested_column(); | 1936 | 1 | json_value_columns[i / 2] = assert_cast<const ColumnString*>(&nested_column); | 1937 | 1 | } else { | 1938 | 0 | json_value_columns[i / 2] = assert_cast<const ColumnString*>(value_column.get()); | 1939 | 0 | } | 1940 | 1 | } | 1941 | | | 1942 | 1 | DorisVector<const JsonbDocument*> json_documents(input_rows_count); | 1943 | 1 | if (json_data_const) { | 1944 | 0 | auto json_data_string = json_data_column->get_data_at(0); | 1945 | 0 | const JsonbDocument* doc = nullptr; | 1946 | 0 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(json_data_string.data, | 1947 | 0 | json_data_string.size, &doc)); | 1948 | 0 | if (!doc || !doc->getValue()) [[unlikely]] { | 1949 | 0 | return create_all_null_result(return_data_type, block, result, input_rows_count); | 1950 | 0 | } | 1951 | 0 | for (size_t i = 0; i != input_rows_count; ++i) { | 1952 | 0 | json_documents[i] = doc; | 1953 | 0 | } | 1954 | 1 | } else { | 1955 | 4 | for (size_t i = 0; i != input_rows_count; ++i) { | 1956 | 3 | if (json_data_null_map && (*json_data_null_map)[i]) { | 1957 | 0 | null_map[i] = 1; | 1958 | 0 | json_documents[i] = nullptr; | 1959 | 0 | continue; | 1960 | 0 | } | 1961 | | | 1962 | 3 | auto json_data_string = json_data_column->get_data_at(i); | 1963 | 3 | const JsonbDocument* doc = nullptr; | 1964 | 3 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(json_data_string.data, | 1965 | 3 | json_data_string.size, &doc)); | 1966 | 3 | if (!doc || !doc->getValue()) [[unlikely]] { | 1967 | 0 | null_map[i] = 1; | 1968 | 0 | continue; | 1969 | 0 | } | 1970 | 3 | json_documents[i] = doc; | 1971 | 3 | } | 1972 | 1 | } | 1973 | | | 1974 | 1 | DorisVector<DorisVector<JsonbPath>> json_paths(keys_count); | 1975 | 1 | DorisVector<DorisVector<const JsonbValue*>> json_values(keys_count); | 1976 | | | 1977 | 1 | RETURN_IF_ERROR(parse_paths_and_values(json_paths, json_values, arguments, input_rows_count, | 1978 | 1 | json_path_columns, json_path_constant, | 1979 | 1 | json_path_null_maps, json_value_columns, | 1980 | 1 | json_value_constant, json_value_null_maps)); | 1981 | | | 1982 | 1 | JsonbWriter writer; | 1983 | 1 | struct DocumentBuffer { | 1984 | 1 | DorisUniqueBufferPtr<char> ptr; | 1985 | 1 | size_t size = 0; | 1986 | 1 | size_t capacity = 0; | 1987 | 1 | }; | 1988 | | | 1989 | 1 | DocumentBuffer tmp_buffer; | 1990 | | | 1991 | 4 | for (size_t row_idx = 0; row_idx != input_rows_count; ++row_idx) { | 1992 | 6 | for (size_t i = 1; i < arguments.size(); i += 2) { | 1993 | 3 | const size_t index = i / 2; | 1994 | 3 | auto& json_path = json_paths[index]; | 1995 | 3 | auto& json_value = json_values[index]; | 1996 | | | 1997 | 3 | const auto path_index = index_check_const(row_idx, json_path_constant[index]); | 1998 | 3 | const auto value_index = index_check_const(row_idx, json_value_constant[index]); | 1999 | | | 2000 | 3 | if (null_map[row_idx]) { | 2001 | 0 | continue; | 2002 | 0 | } | 2003 | | | 2004 | 3 | if (json_documents[row_idx] == nullptr) { | 2005 | 0 | null_map[row_idx] = 1; | 2006 | 0 | continue; | 2007 | 0 | } | 2008 | | | 2009 | 3 | if (json_path_null_maps[index] && (*json_path_null_maps[index])[path_index]) { | 2010 | 0 | null_map[row_idx] = 1; | 2011 | 0 | continue; | 2012 | 0 | } | 2013 | | | 2014 | 3 | auto find_result = | 2015 | 3 | json_documents[row_idx]->getValue()->findValue(json_path[path_index]); | 2016 | | | 2017 | 3 | if (find_result.is_wildcard) { | 2018 | 0 | return Status::InvalidArgument( | 2019 | 0 | " In this situation, path expressions may not contain the * and ** " | 2020 | 0 | "tokens or an array range, argument index: {}, row index: {}", | 2021 | 0 | i, row_idx); | 2022 | 0 | } | 2023 | | | 2024 | 3 | if constexpr (modify_type == JsonbModifyType::Insert) { | 2025 | 3 | if (find_result.value) { | 2026 | 0 | continue; | 2027 | 0 | } | 2028 | | } else if constexpr (modify_type == JsonbModifyType::Replace) { | 2029 | | if (!find_result.value) { | 2030 | | continue; | 2031 | | } | 2032 | | } | 2033 | | | 2034 | 3 | std::vector<const JsonbValue*> parents; | 2035 | | | 2036 | 3 | bool replace = false; | 2037 | 3 | parents.emplace_back(json_documents[row_idx]->getValue()); | 2038 | 3 | const auto legs_count = json_path[path_index].get_leg_vector_size(); | 2039 | 3 | if (find_result.value) { | 2040 | | // find target path, replace it with the new value. | 2041 | 0 | replace = true; | 2042 | 0 | if (!build_parents_by_path(json_documents[row_idx]->getValue(), | 2043 | 0 | json_path[path_index], parents)) { | 2044 | 0 | continue; | 2045 | 0 | } | 2046 | 3 | } else { | 2047 | | // does not find target path, insert the new value. | 2048 | 3 | JsonbPath new_path; | 2049 | 3 | DCHECK_GT(legs_count, 0); | 2050 | 5 | for (size_t j = 0; j + 1 < legs_count; ++j) { | 2051 | 2 | auto* current_leg = json_path[path_index].get_leg_from_leg_vector(j); | 2052 | 2 | std::unique_ptr<leg_info> leg = std::make_unique<leg_info>( | 2053 | 2 | current_leg->leg_ptr, current_leg->leg_len, | 2054 | 2 | current_leg->array_index, current_leg->type); | 2055 | 2 | new_path.add_leg_to_leg_vector(std::move(leg)); | 2056 | 2 | } | 2057 | | | 2058 | 3 | if (!build_parents_by_path(json_documents[row_idx]->getValue(), new_path, | 2059 | 3 | parents)) { | 2060 | 0 | continue; | 2061 | 0 | } | 2062 | 3 | } | 2063 | | | 2064 | 3 | leg_info* last_leg = | 2065 | 3 | legs_count > 0 | 2066 | 3 | ? json_path[path_index].get_leg_from_leg_vector(legs_count - 1) | 2067 | 3 | : nullptr; | 2068 | 3 | RETURN_IF_ERROR(write_json_value(json_documents[row_idx]->getValue(), parents, 0, | 2069 | 3 | json_value[value_index], replace, last_leg, | 2070 | 3 | writer)); | 2071 | | | 2072 | 3 | auto* writer_output = writer.getOutput(); | 2073 | 3 | if (writer_output->getSize() > tmp_buffer.capacity) { | 2074 | 1 | tmp_buffer.capacity = | 2075 | 1 | ((size_t(writer_output->getSize()) + 1024 - 1) / 1024) * 1024; | 2076 | 1 | tmp_buffer.ptr = make_unique_buffer<char>(tmp_buffer.capacity); | 2077 | 1 | DCHECK_LE(writer_output->getSize(), tmp_buffer.capacity); | 2078 | 1 | } | 2079 | | | 2080 | 3 | memcpy(tmp_buffer.ptr.get(), writer_output->getBuffer(), writer_output->getSize()); | 2081 | 3 | tmp_buffer.size = writer_output->getSize(); | 2082 | | | 2083 | 3 | writer.reset(); | 2084 | | | 2085 | 3 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument( | 2086 | 3 | tmp_buffer.ptr.get(), tmp_buffer.size, &json_documents[row_idx])); | 2087 | 3 | } | 2088 | | | 2089 | 3 | if (!null_map[row_idx]) { | 2090 | 3 | const auto* jsonb_document = json_documents[row_idx]; | 2091 | 3 | const auto size = jsonb_document->numPackedBytes(); | 2092 | 3 | res_chars.insert(reinterpret_cast<const char*>(jsonb_document), | 2093 | 3 | reinterpret_cast<const char*>(jsonb_document) + size); | 2094 | 3 | } | 2095 | | | 2096 | 3 | res_offsets[row_idx] = static_cast<uint32_t>(res_chars.size()); | 2097 | | | 2098 | 3 | if (!null_map[row_idx]) { | 2099 | 3 | auto* ptr = res_chars.data() + res_offsets[row_idx - 1]; | 2100 | 3 | auto size = res_offsets[row_idx] - res_offsets[row_idx - 1]; | 2101 | 3 | const JsonbDocument* doc = nullptr; | 2102 | 3 | THROW_IF_ERROR(JsonbDocument::checkAndCreateDocument( | 2103 | 3 | reinterpret_cast<const char*>(ptr), size, &doc)); | 2104 | 3 | } | 2105 | 3 | } | 2106 | | | 2107 | 1 | block.get_by_position(result).column = std::move(result_column); | 2108 | 1 | return Status::OK(); | 2109 | 1 | } |
_ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE1EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm Line | Count | Source | 1858 | 1 | uint32_t result, size_t input_rows_count) const override { | 1859 | 1 | if (arguments.size() % 2 != 1 || arguments.size() < 3) { | 1860 | 0 | return Status::InvalidArgument( | 1861 | 0 | "Function {} must have an odd number of arguments and more than 2 arguments, " | 1862 | 0 | "but got: {}", | 1863 | 0 | name, arguments.size()); | 1864 | 0 | } | 1865 | | | 1866 | 1 | const size_t keys_count = (arguments.size() - 1) / 2; | 1867 | | | 1868 | 1 | auto return_data_type = make_nullable(std::make_shared<DataTypeJsonb>()); | 1869 | | | 1870 | 1 | auto result_column = return_data_type->create_column(); | 1871 | 1 | auto& result_nullable_col = assert_cast<ColumnNullable&>(*result_column); | 1872 | 1 | auto& null_map = result_nullable_col.get_null_map_data(); | 1873 | 1 | auto& res_string_column = | 1874 | 1 | assert_cast<ColumnString&>(result_nullable_col.get_nested_column()); | 1875 | 1 | auto& res_chars = res_string_column.get_chars(); | 1876 | 1 | auto& res_offsets = res_string_column.get_offsets(); | 1877 | | | 1878 | 1 | null_map.resize_fill(input_rows_count, 0); | 1879 | 1 | res_offsets.resize(input_rows_count); | 1880 | 1 | auto&& [json_data_arg_column, json_data_const] = | 1881 | 1 | unpack_if_const(block.get_by_position(arguments[0]).column); | 1882 | | | 1883 | 1 | if (json_data_const) { | 1884 | 0 | if (json_data_arg_column->is_null_at(0)) { | 1885 | 0 | return create_all_null_result(return_data_type, block, result, input_rows_count); | 1886 | 0 | } | 1887 | 0 | } | 1888 | | | 1889 | 1 | std::vector<const ColumnString*> json_path_columns(keys_count); | 1890 | 1 | std::vector<bool> json_path_constant(keys_count); | 1891 | 1 | std::vector<const NullMap*> json_path_null_maps(keys_count, nullptr); | 1892 | | | 1893 | 1 | std::vector<const ColumnString*> json_value_columns(keys_count); | 1894 | 1 | std::vector<bool> json_value_constant(keys_count); | 1895 | 1 | std::vector<const NullMap*> json_value_null_maps(keys_count, nullptr); | 1896 | | | 1897 | 1 | const NullMap* json_data_null_map = nullptr; | 1898 | 1 | const ColumnString* json_data_column; | 1899 | 1 | if (const auto* nullable_column = | 1900 | 1 | check_and_get_column<ColumnNullable>(json_data_arg_column.get())) { | 1901 | 1 | json_data_null_map = &nullable_column->get_null_map_data(); | 1902 | 1 | const auto& nested_column = nullable_column->get_nested_column(); | 1903 | 1 | json_data_column = assert_cast<const ColumnString*>(&nested_column); | 1904 | 1 | } else { | 1905 | 0 | json_data_column = assert_cast<const ColumnString*>(json_data_arg_column.get()); | 1906 | 0 | } | 1907 | | | 1908 | 2 | for (size_t i = 1; i < arguments.size(); i += 2) { | 1909 | 1 | auto&& [path_column, path_const] = | 1910 | 1 | unpack_if_const(block.get_by_position(arguments[i]).column); | 1911 | 1 | auto&& [value_column, value_const] = | 1912 | 1 | unpack_if_const(block.get_by_position(arguments[i + 1]).column); | 1913 | | | 1914 | 1 | if (path_const) { | 1915 | 0 | if (path_column->is_null_at(0)) { | 1916 | 0 | return create_all_null_result(return_data_type, block, result, | 1917 | 0 | input_rows_count); | 1918 | 0 | } | 1919 | 0 | } | 1920 | | | 1921 | 1 | json_path_constant[i / 2] = path_const; | 1922 | 1 | if (const auto* nullable_column = | 1923 | 1 | check_and_get_column<ColumnNullable>(path_column.get())) { | 1924 | 1 | json_path_null_maps[i / 2] = &nullable_column->get_null_map_data(); | 1925 | 1 | const auto& nested_column = nullable_column->get_nested_column(); | 1926 | 1 | json_path_columns[i / 2] = assert_cast<const ColumnString*>(&nested_column); | 1927 | 1 | } else { | 1928 | 0 | json_path_columns[i / 2] = assert_cast<const ColumnString*>(path_column.get()); | 1929 | 0 | } | 1930 | | | 1931 | 1 | json_value_constant[i / 2] = value_const; | 1932 | 1 | if (const auto* nullable_column = | 1933 | 1 | check_and_get_column<ColumnNullable>(value_column.get())) { | 1934 | 1 | json_value_null_maps[i / 2] = &nullable_column->get_null_map_data(); | 1935 | 1 | const auto& nested_column = nullable_column->get_nested_column(); | 1936 | 1 | json_value_columns[i / 2] = assert_cast<const ColumnString*>(&nested_column); | 1937 | 1 | } else { | 1938 | 0 | json_value_columns[i / 2] = assert_cast<const ColumnString*>(value_column.get()); | 1939 | 0 | } | 1940 | 1 | } | 1941 | | | 1942 | 1 | DorisVector<const JsonbDocument*> json_documents(input_rows_count); | 1943 | 1 | if (json_data_const) { | 1944 | 0 | auto json_data_string = json_data_column->get_data_at(0); | 1945 | 0 | const JsonbDocument* doc = nullptr; | 1946 | 0 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(json_data_string.data, | 1947 | 0 | json_data_string.size, &doc)); | 1948 | 0 | if (!doc || !doc->getValue()) [[unlikely]] { | 1949 | 0 | return create_all_null_result(return_data_type, block, result, input_rows_count); | 1950 | 0 | } | 1951 | 0 | for (size_t i = 0; i != input_rows_count; ++i) { | 1952 | 0 | json_documents[i] = doc; | 1953 | 0 | } | 1954 | 1 | } else { | 1955 | 4 | for (size_t i = 0; i != input_rows_count; ++i) { | 1956 | 3 | if (json_data_null_map && (*json_data_null_map)[i]) { | 1957 | 0 | null_map[i] = 1; | 1958 | 0 | json_documents[i] = nullptr; | 1959 | 0 | continue; | 1960 | 0 | } | 1961 | | | 1962 | 3 | auto json_data_string = json_data_column->get_data_at(i); | 1963 | 3 | const JsonbDocument* doc = nullptr; | 1964 | 3 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(json_data_string.data, | 1965 | 3 | json_data_string.size, &doc)); | 1966 | 3 | if (!doc || !doc->getValue()) [[unlikely]] { | 1967 | 0 | null_map[i] = 1; | 1968 | 0 | continue; | 1969 | 0 | } | 1970 | 3 | json_documents[i] = doc; | 1971 | 3 | } | 1972 | 1 | } | 1973 | | | 1974 | 1 | DorisVector<DorisVector<JsonbPath>> json_paths(keys_count); | 1975 | 1 | DorisVector<DorisVector<const JsonbValue*>> json_values(keys_count); | 1976 | | | 1977 | 1 | RETURN_IF_ERROR(parse_paths_and_values(json_paths, json_values, arguments, input_rows_count, | 1978 | 1 | json_path_columns, json_path_constant, | 1979 | 1 | json_path_null_maps, json_value_columns, | 1980 | 1 | json_value_constant, json_value_null_maps)); | 1981 | | | 1982 | 1 | JsonbWriter writer; | 1983 | 1 | struct DocumentBuffer { | 1984 | 1 | DorisUniqueBufferPtr<char> ptr; | 1985 | 1 | size_t size = 0; | 1986 | 1 | size_t capacity = 0; | 1987 | 1 | }; | 1988 | | | 1989 | 1 | DocumentBuffer tmp_buffer; | 1990 | | | 1991 | 4 | for (size_t row_idx = 0; row_idx != input_rows_count; ++row_idx) { | 1992 | 6 | for (size_t i = 1; i < arguments.size(); i += 2) { | 1993 | 3 | const size_t index = i / 2; | 1994 | 3 | auto& json_path = json_paths[index]; | 1995 | 3 | auto& json_value = json_values[index]; | 1996 | | | 1997 | 3 | const auto path_index = index_check_const(row_idx, json_path_constant[index]); | 1998 | 3 | const auto value_index = index_check_const(row_idx, json_value_constant[index]); | 1999 | | | 2000 | 3 | if (null_map[row_idx]) { | 2001 | 0 | continue; | 2002 | 0 | } | 2003 | | | 2004 | 3 | if (json_documents[row_idx] == nullptr) { | 2005 | 0 | null_map[row_idx] = 1; | 2006 | 0 | continue; | 2007 | 0 | } | 2008 | | | 2009 | 3 | if (json_path_null_maps[index] && (*json_path_null_maps[index])[path_index]) { | 2010 | 0 | null_map[row_idx] = 1; | 2011 | 0 | continue; | 2012 | 0 | } | 2013 | | | 2014 | 3 | auto find_result = | 2015 | 3 | json_documents[row_idx]->getValue()->findValue(json_path[path_index]); | 2016 | | | 2017 | 3 | if (find_result.is_wildcard) { | 2018 | 0 | return Status::InvalidArgument( | 2019 | 0 | " In this situation, path expressions may not contain the * and ** " | 2020 | 0 | "tokens or an array range, argument index: {}, row index: {}", | 2021 | 0 | i, row_idx); | 2022 | 0 | } | 2023 | | | 2024 | | if constexpr (modify_type == JsonbModifyType::Insert) { | 2025 | | if (find_result.value) { | 2026 | | continue; | 2027 | | } | 2028 | 3 | } else if constexpr (modify_type == JsonbModifyType::Replace) { | 2029 | 3 | if (!find_result.value) { | 2030 | 3 | continue; | 2031 | 3 | } | 2032 | 3 | } | 2033 | | | 2034 | 3 | std::vector<const JsonbValue*> parents; | 2035 | | | 2036 | 3 | bool replace = false; | 2037 | 3 | parents.emplace_back(json_documents[row_idx]->getValue()); | 2038 | 3 | const auto legs_count = json_path[path_index].get_leg_vector_size(); | 2039 | 3 | if (find_result.value) { | 2040 | | // find target path, replace it with the new value. | 2041 | 0 | replace = true; | 2042 | 0 | if (!build_parents_by_path(json_documents[row_idx]->getValue(), | 2043 | 0 | json_path[path_index], parents)) { | 2044 | 0 | continue; | 2045 | 0 | } | 2046 | 3 | } else { | 2047 | | // does not find target path, insert the new value. | 2048 | 3 | JsonbPath new_path; | 2049 | 3 | DCHECK_GT(legs_count, 0); | 2050 | 5 | for (size_t j = 0; j + 1 < legs_count; ++j) { | 2051 | 2 | auto* current_leg = json_path[path_index].get_leg_from_leg_vector(j); | 2052 | 2 | std::unique_ptr<leg_info> leg = std::make_unique<leg_info>( | 2053 | 2 | current_leg->leg_ptr, current_leg->leg_len, | 2054 | 2 | current_leg->array_index, current_leg->type); | 2055 | 2 | new_path.add_leg_to_leg_vector(std::move(leg)); | 2056 | 2 | } | 2057 | | | 2058 | 3 | if (!build_parents_by_path(json_documents[row_idx]->getValue(), new_path, | 2059 | 3 | parents)) { | 2060 | 0 | continue; | 2061 | 0 | } | 2062 | 3 | } | 2063 | | | 2064 | 3 | leg_info* last_leg = | 2065 | 3 | legs_count > 0 | 2066 | 3 | ? json_path[path_index].get_leg_from_leg_vector(legs_count - 1) | 2067 | 3 | : nullptr; | 2068 | 3 | RETURN_IF_ERROR(write_json_value(json_documents[row_idx]->getValue(), parents, 0, | 2069 | 3 | json_value[value_index], replace, last_leg, | 2070 | 3 | writer)); | 2071 | | | 2072 | 3 | auto* writer_output = writer.getOutput(); | 2073 | 3 | if (writer_output->getSize() > tmp_buffer.capacity) { | 2074 | 1 | tmp_buffer.capacity = | 2075 | 1 | ((size_t(writer_output->getSize()) + 1024 - 1) / 1024) * 1024; | 2076 | 1 | tmp_buffer.ptr = make_unique_buffer<char>(tmp_buffer.capacity); | 2077 | 1 | DCHECK_LE(writer_output->getSize(), tmp_buffer.capacity); | 2078 | 1 | } | 2079 | | | 2080 | 3 | memcpy(tmp_buffer.ptr.get(), writer_output->getBuffer(), writer_output->getSize()); | 2081 | 3 | tmp_buffer.size = writer_output->getSize(); | 2082 | | | 2083 | 3 | writer.reset(); | 2084 | | | 2085 | 3 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument( | 2086 | 3 | tmp_buffer.ptr.get(), tmp_buffer.size, &json_documents[row_idx])); | 2087 | 3 | } | 2088 | | | 2089 | 3 | if (!null_map[row_idx]) { | 2090 | 3 | const auto* jsonb_document = json_documents[row_idx]; | 2091 | 3 | const auto size = jsonb_document->numPackedBytes(); | 2092 | 3 | res_chars.insert(reinterpret_cast<const char*>(jsonb_document), | 2093 | 3 | reinterpret_cast<const char*>(jsonb_document) + size); | 2094 | 3 | } | 2095 | | | 2096 | 3 | res_offsets[row_idx] = static_cast<uint32_t>(res_chars.size()); | 2097 | | | 2098 | 3 | if (!null_map[row_idx]) { | 2099 | 3 | auto* ptr = res_chars.data() + res_offsets[row_idx - 1]; | 2100 | 3 | auto size = res_offsets[row_idx] - res_offsets[row_idx - 1]; | 2101 | 3 | const JsonbDocument* doc = nullptr; | 2102 | 3 | THROW_IF_ERROR(JsonbDocument::checkAndCreateDocument( | 2103 | 3 | reinterpret_cast<const char*>(ptr), size, &doc)); | 2104 | 3 | } | 2105 | 3 | } | 2106 | | | 2107 | 1 | block.get_by_position(result).column = std::move(result_column); | 2108 | 1 | return Status::OK(); | 2109 | 1 | } |
Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE2EE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm |
2110 | | |
2111 | | bool build_parents_by_path(const JsonbValue* root, const JsonbPath& path, |
2112 | 10 | std::vector<const JsonbValue*>& parents) const { |
2113 | 10 | const size_t index = parents.size() - 1; |
2114 | 10 | if (index == path.get_leg_vector_size()) { |
2115 | 6 | return true; |
2116 | 6 | } |
2117 | | |
2118 | 4 | JsonbPath current; |
2119 | 4 | auto* current_leg = path.get_leg_from_leg_vector(index); |
2120 | 4 | std::unique_ptr<leg_info> leg = |
2121 | 4 | std::make_unique<leg_info>(current_leg->leg_ptr, current_leg->leg_len, |
2122 | 4 | current_leg->array_index, current_leg->type); |
2123 | 4 | current.add_leg_to_leg_vector(std::move(leg)); |
2124 | | |
2125 | 4 | auto find_result = root->findValue(current); |
2126 | 4 | if (!find_result.value) { |
2127 | 0 | std::string path_string; |
2128 | 0 | current.to_string(&path_string); |
2129 | 0 | return false; |
2130 | 4 | } else if (find_result.value == root) { |
2131 | 0 | return true; |
2132 | 4 | } else { |
2133 | 4 | parents.emplace_back(find_result.value); |
2134 | 4 | } |
2135 | | |
2136 | 4 | return build_parents_by_path(find_result.value, path, parents); |
2137 | 4 | } _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE0EE21build_parents_by_pathEPKNS_10JsonbValueERKNS_9JsonbPathERSt6vectorIS5_SaIS5_EE Line | Count | Source | 2112 | 5 | std::vector<const JsonbValue*>& parents) const { | 2113 | 5 | const size_t index = parents.size() - 1; | 2114 | 5 | if (index == path.get_leg_vector_size()) { | 2115 | 3 | return true; | 2116 | 3 | } | 2117 | | | 2118 | 2 | JsonbPath current; | 2119 | 2 | auto* current_leg = path.get_leg_from_leg_vector(index); | 2120 | 2 | std::unique_ptr<leg_info> leg = | 2121 | 2 | std::make_unique<leg_info>(current_leg->leg_ptr, current_leg->leg_len, | 2122 | 2 | current_leg->array_index, current_leg->type); | 2123 | 2 | current.add_leg_to_leg_vector(std::move(leg)); | 2124 | | | 2125 | 2 | auto find_result = root->findValue(current); | 2126 | 2 | if (!find_result.value) { | 2127 | 0 | std::string path_string; | 2128 | 0 | current.to_string(&path_string); | 2129 | 0 | return false; | 2130 | 2 | } else if (find_result.value == root) { | 2131 | 0 | return true; | 2132 | 2 | } else { | 2133 | 2 | parents.emplace_back(find_result.value); | 2134 | 2 | } | 2135 | | | 2136 | 2 | return build_parents_by_path(find_result.value, path, parents); | 2137 | 2 | } |
_ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE1EE21build_parents_by_pathEPKNS_10JsonbValueERKNS_9JsonbPathERSt6vectorIS5_SaIS5_EE Line | Count | Source | 2112 | 5 | std::vector<const JsonbValue*>& parents) const { | 2113 | 5 | const size_t index = parents.size() - 1; | 2114 | 5 | if (index == path.get_leg_vector_size()) { | 2115 | 3 | return true; | 2116 | 3 | } | 2117 | | | 2118 | 2 | JsonbPath current; | 2119 | 2 | auto* current_leg = path.get_leg_from_leg_vector(index); | 2120 | 2 | std::unique_ptr<leg_info> leg = | 2121 | 2 | std::make_unique<leg_info>(current_leg->leg_ptr, current_leg->leg_len, | 2122 | 2 | current_leg->array_index, current_leg->type); | 2123 | 2 | current.add_leg_to_leg_vector(std::move(leg)); | 2124 | | | 2125 | 2 | auto find_result = root->findValue(current); | 2126 | 2 | if (!find_result.value) { | 2127 | 0 | std::string path_string; | 2128 | 0 | current.to_string(&path_string); | 2129 | 0 | return false; | 2130 | 2 | } else if (find_result.value == root) { | 2131 | 0 | return true; | 2132 | 2 | } else { | 2133 | 2 | parents.emplace_back(find_result.value); | 2134 | 2 | } | 2135 | | | 2136 | 2 | return build_parents_by_path(find_result.value, path, parents); | 2137 | 2 | } |
Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE2EE21build_parents_by_pathEPKNS_10JsonbValueERKNS_9JsonbPathERSt6vectorIS5_SaIS5_EE |
2138 | | |
2139 | | Status write_json_value(const JsonbValue* root, const std::vector<const JsonbValue*>& parents, |
2140 | | const size_t parent_index, const JsonbValue* value, const bool replace, |
2141 | 10 | const leg_info* last_leg, JsonbWriter& writer) const { |
2142 | 10 | if (parent_index >= parents.size()) { |
2143 | 0 | return Status::InvalidArgument( |
2144 | 0 | "JsonbModify: parent_index {} is out of bounds for parents size {}", |
2145 | 0 | parent_index, parents.size()); |
2146 | 0 | } |
2147 | | |
2148 | 10 | if (parents[parent_index] != root) { |
2149 | 0 | return Status::InvalidArgument( |
2150 | 0 | "JsonbModify: parent value does not match root value, parent_index: {}, " |
2151 | 0 | "parents size: {}", |
2152 | 0 | parent_index, parents.size()); |
2153 | 0 | } |
2154 | | |
2155 | 10 | if (parent_index == parents.size() - 1 && replace) { |
2156 | | // We are at the last parent, write the value directly |
2157 | 0 | if (value == nullptr) { |
2158 | 0 | writer.writeNull(); |
2159 | 0 | } else { |
2160 | 0 | writer.writeValue(value); |
2161 | 0 | } |
2162 | 0 | return Status::OK(); |
2163 | 0 | } |
2164 | | |
2165 | 10 | bool value_written = false; |
2166 | 10 | bool is_last_parent = (parent_index == parents.size() - 1); |
2167 | 10 | const auto* next_parent = is_last_parent ? nullptr : parents[parent_index + 1]; |
2168 | 10 | if (root->isArray()) { |
2169 | 2 | writer.writeStartArray(); |
2170 | 2 | const auto* array_val = root->unpack<ArrayVal>(); |
2171 | 4 | for (int i = 0; i != array_val->numElem(); ++i) { |
2172 | 2 | auto* it = array_val->get(i); |
2173 | | |
2174 | 2 | if (is_last_parent && last_leg->array_index == i) { |
2175 | 0 | value_written = true; |
2176 | 0 | writer.writeValue(value); |
2177 | 2 | } else if (it == next_parent) { |
2178 | 0 | value_written = true; |
2179 | 0 | RETURN_IF_ERROR(write_json_value(it, parents, parent_index + 1, value, replace, |
2180 | 0 | last_leg, writer)); |
2181 | 2 | } else { |
2182 | 2 | writer.writeValue(it); |
2183 | 2 | } |
2184 | 2 | } |
2185 | 2 | if (is_last_parent && !value_written) { |
2186 | 2 | value_written = true; |
2187 | 2 | writer.writeValue(value); |
2188 | 2 | } |
2189 | | |
2190 | 2 | writer.writeEndArray(); |
2191 | | |
2192 | 8 | } else { |
2193 | | /** |
2194 | | Because even for a non-array object, `$[0]` can still point to that object: |
2195 | | ``` |
2196 | | select json_extract('{"key": "value"}', '$[0]'); |
2197 | | +------------------------------------------+ |
2198 | | | json_extract('{"key": "value"}', '$[0]') | |
2199 | | +------------------------------------------+ |
2200 | | | {"key": "value"} | |
2201 | | +------------------------------------------+ |
2202 | | ``` |
2203 | | So when inserting an element into `$[1]`, even if '$' does not represent an array, |
2204 | | it should be converted to an array before insertion: |
2205 | | ``` |
2206 | | select json_insert('123','$[1]', null); |
2207 | | +---------------------------------+ |
2208 | | | json_insert('123','$[1]', null) | |
2209 | | +---------------------------------+ |
2210 | | | [123, null] | |
2211 | | +---------------------------------+ |
2212 | | ``` |
2213 | | */ |
2214 | 8 | if (is_last_parent && last_leg && last_leg->type == ARRAY_CODE) { |
2215 | 0 | writer.writeStartArray(); |
2216 | 0 | writer.writeValue(root); |
2217 | 0 | writer.writeValue(value); |
2218 | 0 | writer.writeEndArray(); |
2219 | 0 | return Status::OK(); |
2220 | 8 | } else if (root->isObject()) { |
2221 | 8 | writer.writeStartObject(); |
2222 | 8 | const auto* object_val = root->unpack<ObjectVal>(); |
2223 | 8 | for (const auto& it : *object_val) { |
2224 | 4 | writer.writeKey(it.getKeyStr(), it.klen()); |
2225 | 4 | if (it.value() == next_parent) { |
2226 | 4 | value_written = true; |
2227 | 4 | RETURN_IF_ERROR(write_json_value(it.value(), parents, parent_index + 1, |
2228 | 4 | value, replace, last_leg, writer)); |
2229 | 4 | } else { |
2230 | 0 | writer.writeValue(it.value()); |
2231 | 0 | } |
2232 | 4 | } |
2233 | | |
2234 | 8 | if (is_last_parent && !value_written) { |
2235 | 4 | value_written = true; |
2236 | 4 | writer.writeStartObject(); |
2237 | 4 | writer.writeKey(last_leg->leg_ptr, static_cast<uint8_t>(last_leg->leg_len)); |
2238 | 4 | writer.writeValue(value); |
2239 | 4 | writer.writeEndObject(); |
2240 | 4 | } |
2241 | 8 | writer.writeEndObject(); |
2242 | | |
2243 | 8 | } else { |
2244 | 0 | return Status::InvalidArgument("Cannot insert value into this type"); |
2245 | 0 | } |
2246 | 8 | } |
2247 | | |
2248 | 10 | if (!value_written) { |
2249 | 0 | return Status::InvalidArgument( |
2250 | 0 | "JsonbModify: value not written, parent_index: {}, parents size: {}", |
2251 | 0 | parent_index, parents.size()); |
2252 | 0 | } |
2253 | | |
2254 | 10 | return Status::OK(); |
2255 | 10 | } _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE0EE16write_json_valueEPKNS_10JsonbValueERKSt6vectorIS5_SaIS5_EEmS5_bPKNS_8leg_infoERNS_12JsonbWriterTINS_14JsonbOutStreamEEE Line | Count | Source | 2141 | 5 | const leg_info* last_leg, JsonbWriter& writer) const { | 2142 | 5 | if (parent_index >= parents.size()) { | 2143 | 0 | return Status::InvalidArgument( | 2144 | 0 | "JsonbModify: parent_index {} is out of bounds for parents size {}", | 2145 | 0 | parent_index, parents.size()); | 2146 | 0 | } | 2147 | | | 2148 | 5 | if (parents[parent_index] != root) { | 2149 | 0 | return Status::InvalidArgument( | 2150 | 0 | "JsonbModify: parent value does not match root value, parent_index: {}, " | 2151 | 0 | "parents size: {}", | 2152 | 0 | parent_index, parents.size()); | 2153 | 0 | } | 2154 | | | 2155 | 5 | if (parent_index == parents.size() - 1 && replace) { | 2156 | | // We are at the last parent, write the value directly | 2157 | 0 | if (value == nullptr) { | 2158 | 0 | writer.writeNull(); | 2159 | 0 | } else { | 2160 | 0 | writer.writeValue(value); | 2161 | 0 | } | 2162 | 0 | return Status::OK(); | 2163 | 0 | } | 2164 | | | 2165 | 5 | bool value_written = false; | 2166 | 5 | bool is_last_parent = (parent_index == parents.size() - 1); | 2167 | 5 | const auto* next_parent = is_last_parent ? nullptr : parents[parent_index + 1]; | 2168 | 5 | if (root->isArray()) { | 2169 | 1 | writer.writeStartArray(); | 2170 | 1 | const auto* array_val = root->unpack<ArrayVal>(); | 2171 | 2 | for (int i = 0; i != array_val->numElem(); ++i) { | 2172 | 1 | auto* it = array_val->get(i); | 2173 | | | 2174 | 1 | if (is_last_parent && last_leg->array_index == i) { | 2175 | 0 | value_written = true; | 2176 | 0 | writer.writeValue(value); | 2177 | 1 | } else if (it == next_parent) { | 2178 | 0 | value_written = true; | 2179 | 0 | RETURN_IF_ERROR(write_json_value(it, parents, parent_index + 1, value, replace, | 2180 | 0 | last_leg, writer)); | 2181 | 1 | } else { | 2182 | 1 | writer.writeValue(it); | 2183 | 1 | } | 2184 | 1 | } | 2185 | 1 | if (is_last_parent && !value_written) { | 2186 | 1 | value_written = true; | 2187 | 1 | writer.writeValue(value); | 2188 | 1 | } | 2189 | | | 2190 | 1 | writer.writeEndArray(); | 2191 | | | 2192 | 4 | } else { | 2193 | | /** | 2194 | | Because even for a non-array object, `$[0]` can still point to that object: | 2195 | | ``` | 2196 | | select json_extract('{"key": "value"}', '$[0]'); | 2197 | | +------------------------------------------+ | 2198 | | | json_extract('{"key": "value"}', '$[0]') | | 2199 | | +------------------------------------------+ | 2200 | | | {"key": "value"} | | 2201 | | +------------------------------------------+ | 2202 | | ``` | 2203 | | So when inserting an element into `$[1]`, even if '$' does not represent an array, | 2204 | | it should be converted to an array before insertion: | 2205 | | ``` | 2206 | | select json_insert('123','$[1]', null); | 2207 | | +---------------------------------+ | 2208 | | | json_insert('123','$[1]', null) | | 2209 | | +---------------------------------+ | 2210 | | | [123, null] | | 2211 | | +---------------------------------+ | 2212 | | ``` | 2213 | | */ | 2214 | 4 | if (is_last_parent && last_leg && last_leg->type == ARRAY_CODE) { | 2215 | 0 | writer.writeStartArray(); | 2216 | 0 | writer.writeValue(root); | 2217 | 0 | writer.writeValue(value); | 2218 | 0 | writer.writeEndArray(); | 2219 | 0 | return Status::OK(); | 2220 | 4 | } else if (root->isObject()) { | 2221 | 4 | writer.writeStartObject(); | 2222 | 4 | const auto* object_val = root->unpack<ObjectVal>(); | 2223 | 4 | for (const auto& it : *object_val) { | 2224 | 2 | writer.writeKey(it.getKeyStr(), it.klen()); | 2225 | 2 | if (it.value() == next_parent) { | 2226 | 2 | value_written = true; | 2227 | 2 | RETURN_IF_ERROR(write_json_value(it.value(), parents, parent_index + 1, | 2228 | 2 | value, replace, last_leg, writer)); | 2229 | 2 | } else { | 2230 | 0 | writer.writeValue(it.value()); | 2231 | 0 | } | 2232 | 2 | } | 2233 | | | 2234 | 4 | if (is_last_parent && !value_written) { | 2235 | 2 | value_written = true; | 2236 | 2 | writer.writeStartObject(); | 2237 | 2 | writer.writeKey(last_leg->leg_ptr, static_cast<uint8_t>(last_leg->leg_len)); | 2238 | 2 | writer.writeValue(value); | 2239 | 2 | writer.writeEndObject(); | 2240 | 2 | } | 2241 | 4 | writer.writeEndObject(); | 2242 | | | 2243 | 4 | } else { | 2244 | 0 | return Status::InvalidArgument("Cannot insert value into this type"); | 2245 | 0 | } | 2246 | 4 | } | 2247 | | | 2248 | 5 | if (!value_written) { | 2249 | 0 | return Status::InvalidArgument( | 2250 | 0 | "JsonbModify: value not written, parent_index: {}, parents size: {}", | 2251 | 0 | parent_index, parents.size()); | 2252 | 0 | } | 2253 | | | 2254 | 5 | return Status::OK(); | 2255 | 5 | } |
_ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE1EE16write_json_valueEPKNS_10JsonbValueERKSt6vectorIS5_SaIS5_EEmS5_bPKNS_8leg_infoERNS_12JsonbWriterTINS_14JsonbOutStreamEEE Line | Count | Source | 2141 | 5 | const leg_info* last_leg, JsonbWriter& writer) const { | 2142 | 5 | if (parent_index >= parents.size()) { | 2143 | 0 | return Status::InvalidArgument( | 2144 | 0 | "JsonbModify: parent_index {} is out of bounds for parents size {}", | 2145 | 0 | parent_index, parents.size()); | 2146 | 0 | } | 2147 | | | 2148 | 5 | if (parents[parent_index] != root) { | 2149 | 0 | return Status::InvalidArgument( | 2150 | 0 | "JsonbModify: parent value does not match root value, parent_index: {}, " | 2151 | 0 | "parents size: {}", | 2152 | 0 | parent_index, parents.size()); | 2153 | 0 | } | 2154 | | | 2155 | 5 | if (parent_index == parents.size() - 1 && replace) { | 2156 | | // We are at the last parent, write the value directly | 2157 | 0 | if (value == nullptr) { | 2158 | 0 | writer.writeNull(); | 2159 | 0 | } else { | 2160 | 0 | writer.writeValue(value); | 2161 | 0 | } | 2162 | 0 | return Status::OK(); | 2163 | 0 | } | 2164 | | | 2165 | 5 | bool value_written = false; | 2166 | 5 | bool is_last_parent = (parent_index == parents.size() - 1); | 2167 | 5 | const auto* next_parent = is_last_parent ? nullptr : parents[parent_index + 1]; | 2168 | 5 | if (root->isArray()) { | 2169 | 1 | writer.writeStartArray(); | 2170 | 1 | const auto* array_val = root->unpack<ArrayVal>(); | 2171 | 2 | for (int i = 0; i != array_val->numElem(); ++i) { | 2172 | 1 | auto* it = array_val->get(i); | 2173 | | | 2174 | 1 | if (is_last_parent && last_leg->array_index == i) { | 2175 | 0 | value_written = true; | 2176 | 0 | writer.writeValue(value); | 2177 | 1 | } else if (it == next_parent) { | 2178 | 0 | value_written = true; | 2179 | 0 | RETURN_IF_ERROR(write_json_value(it, parents, parent_index + 1, value, replace, | 2180 | 0 | last_leg, writer)); | 2181 | 1 | } else { | 2182 | 1 | writer.writeValue(it); | 2183 | 1 | } | 2184 | 1 | } | 2185 | 1 | if (is_last_parent && !value_written) { | 2186 | 1 | value_written = true; | 2187 | 1 | writer.writeValue(value); | 2188 | 1 | } | 2189 | | | 2190 | 1 | writer.writeEndArray(); | 2191 | | | 2192 | 4 | } else { | 2193 | | /** | 2194 | | Because even for a non-array object, `$[0]` can still point to that object: | 2195 | | ``` | 2196 | | select json_extract('{"key": "value"}', '$[0]'); | 2197 | | +------------------------------------------+ | 2198 | | | json_extract('{"key": "value"}', '$[0]') | | 2199 | | +------------------------------------------+ | 2200 | | | {"key": "value"} | | 2201 | | +------------------------------------------+ | 2202 | | ``` | 2203 | | So when inserting an element into `$[1]`, even if '$' does not represent an array, | 2204 | | it should be converted to an array before insertion: | 2205 | | ``` | 2206 | | select json_insert('123','$[1]', null); | 2207 | | +---------------------------------+ | 2208 | | | json_insert('123','$[1]', null) | | 2209 | | +---------------------------------+ | 2210 | | | [123, null] | | 2211 | | +---------------------------------+ | 2212 | | ``` | 2213 | | */ | 2214 | 4 | if (is_last_parent && last_leg && last_leg->type == ARRAY_CODE) { | 2215 | 0 | writer.writeStartArray(); | 2216 | 0 | writer.writeValue(root); | 2217 | 0 | writer.writeValue(value); | 2218 | 0 | writer.writeEndArray(); | 2219 | 0 | return Status::OK(); | 2220 | 4 | } else if (root->isObject()) { | 2221 | 4 | writer.writeStartObject(); | 2222 | 4 | const auto* object_val = root->unpack<ObjectVal>(); | 2223 | 4 | for (const auto& it : *object_val) { | 2224 | 2 | writer.writeKey(it.getKeyStr(), it.klen()); | 2225 | 2 | if (it.value() == next_parent) { | 2226 | 2 | value_written = true; | 2227 | 2 | RETURN_IF_ERROR(write_json_value(it.value(), parents, parent_index + 1, | 2228 | 2 | value, replace, last_leg, writer)); | 2229 | 2 | } else { | 2230 | 0 | writer.writeValue(it.value()); | 2231 | 0 | } | 2232 | 2 | } | 2233 | | | 2234 | 4 | if (is_last_parent && !value_written) { | 2235 | 2 | value_written = true; | 2236 | 2 | writer.writeStartObject(); | 2237 | 2 | writer.writeKey(last_leg->leg_ptr, static_cast<uint8_t>(last_leg->leg_len)); | 2238 | 2 | writer.writeValue(value); | 2239 | 2 | writer.writeEndObject(); | 2240 | 2 | } | 2241 | 4 | writer.writeEndObject(); | 2242 | | | 2243 | 4 | } else { | 2244 | 0 | return Status::InvalidArgument("Cannot insert value into this type"); | 2245 | 0 | } | 2246 | 4 | } | 2247 | | | 2248 | 5 | if (!value_written) { | 2249 | 0 | return Status::InvalidArgument( | 2250 | 0 | "JsonbModify: value not written, parent_index: {}, parents size: {}", | 2251 | 0 | parent_index, parents.size()); | 2252 | 0 | } | 2253 | | | 2254 | 5 | return Status::OK(); | 2255 | 5 | } |
Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE2EE16write_json_valueEPKNS_10JsonbValueERKSt6vectorIS5_SaIS5_EEmS5_bPKNS_8leg_infoERNS_12JsonbWriterTINS_14JsonbOutStreamEEE |
2256 | | |
2257 | | Status parse_paths_and_values(DorisVector<DorisVector<JsonbPath>>& json_paths, |
2258 | | DorisVector<DorisVector<const JsonbValue*>>& json_values, |
2259 | | const ColumnNumbers& arguments, const size_t input_rows_count, |
2260 | | const std::vector<const ColumnString*>& json_path_columns, |
2261 | | const std::vector<bool>& json_path_constant, |
2262 | | const std::vector<const NullMap*>& json_path_null_maps, |
2263 | | const std::vector<const ColumnString*>& json_value_columns, |
2264 | | const std::vector<bool>& json_value_constant, |
2265 | 2 | const std::vector<const NullMap*>& json_value_null_maps) const { |
2266 | 4 | for (size_t i = 1; i < arguments.size(); i += 2) { |
2267 | 2 | const size_t index = i / 2; |
2268 | 2 | const auto* json_path_column = json_path_columns[index]; |
2269 | 2 | const auto* value_column = json_value_columns[index]; |
2270 | | |
2271 | 2 | json_paths[index].resize(json_path_constant[index] ? 1 : input_rows_count); |
2272 | 2 | json_values[index].resize(json_value_constant[index] ? 1 : input_rows_count, nullptr); |
2273 | | |
2274 | 8 | for (size_t row_idx = 0; row_idx != json_paths[index].size(); ++row_idx) { |
2275 | 6 | if (json_path_null_maps[index] && (*json_path_null_maps[index])[row_idx]) { |
2276 | 0 | continue; |
2277 | 0 | } |
2278 | | |
2279 | 6 | auto path_string = json_path_column->get_data_at(row_idx); |
2280 | 6 | if (!json_paths[index][row_idx].seek(path_string.data, path_string.size)) { |
2281 | 0 | return Status::InvalidArgument( |
2282 | 0 | "Json path error: Invalid Json Path for value: {}, " |
2283 | 0 | "argument " |
2284 | 0 | "index: {}, row index: {}", |
2285 | 0 | std::string_view(path_string.data, path_string.size), i, row_idx); |
2286 | 0 | } |
2287 | | |
2288 | 6 | if (json_paths[index][row_idx].is_wildcard()) { |
2289 | 0 | return Status::InvalidArgument( |
2290 | 0 | "In this situation, path expressions may not contain the * and ** " |
2291 | 0 | "tokens, argument index: {}, row index: {}", |
2292 | 0 | i, row_idx); |
2293 | 0 | } |
2294 | 6 | } |
2295 | | |
2296 | 8 | for (size_t row_idx = 0; row_idx != json_values[index].size(); ++row_idx) { |
2297 | 6 | if (json_value_null_maps[index] && (*json_value_null_maps[index])[row_idx]) { |
2298 | 0 | continue; |
2299 | 0 | } |
2300 | | |
2301 | 6 | auto value_string = value_column->get_data_at(row_idx); |
2302 | 6 | const JsonbDocument* doc = nullptr; |
2303 | 6 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(value_string.data, |
2304 | 6 | value_string.size, &doc)); |
2305 | 6 | if (doc) { |
2306 | 6 | json_values[index][row_idx] = doc->getValue(); |
2307 | 6 | } |
2308 | 6 | } |
2309 | 2 | } |
2310 | | |
2311 | 2 | return Status::OK(); |
2312 | 2 | } _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE0EE22parse_paths_and_valuesERSt6vectorIS3_INS_9JsonbPathENS_18CustomStdAllocatorIS4_NS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEEEEENS5_ISA_S8_EEERS3_IS3_IPKNS_10JsonbValueENS5_ISG_S8_EEENS5_ISI_S8_EEERKS3_IjSaIjEEmRKS3_IPKNS_9ColumnStrIjEESaIST_EERKS3_IbSaIbEERKS3_IPKNS_8PODArrayIhLm4096ES8_Lm16ELm15EEESaIS15_EESX_S11_S19_ Line | Count | Source | 2265 | 1 | const std::vector<const NullMap*>& json_value_null_maps) const { | 2266 | 2 | for (size_t i = 1; i < arguments.size(); i += 2) { | 2267 | 1 | const size_t index = i / 2; | 2268 | 1 | const auto* json_path_column = json_path_columns[index]; | 2269 | 1 | const auto* value_column = json_value_columns[index]; | 2270 | | | 2271 | 1 | json_paths[index].resize(json_path_constant[index] ? 1 : input_rows_count); | 2272 | 1 | json_values[index].resize(json_value_constant[index] ? 1 : input_rows_count, nullptr); | 2273 | | | 2274 | 4 | for (size_t row_idx = 0; row_idx != json_paths[index].size(); ++row_idx) { | 2275 | 3 | if (json_path_null_maps[index] && (*json_path_null_maps[index])[row_idx]) { | 2276 | 0 | continue; | 2277 | 0 | } | 2278 | | | 2279 | 3 | auto path_string = json_path_column->get_data_at(row_idx); | 2280 | 3 | if (!json_paths[index][row_idx].seek(path_string.data, path_string.size)) { | 2281 | 0 | return Status::InvalidArgument( | 2282 | 0 | "Json path error: Invalid Json Path for value: {}, " | 2283 | 0 | "argument " | 2284 | 0 | "index: {}, row index: {}", | 2285 | 0 | std::string_view(path_string.data, path_string.size), i, row_idx); | 2286 | 0 | } | 2287 | | | 2288 | 3 | if (json_paths[index][row_idx].is_wildcard()) { | 2289 | 0 | return Status::InvalidArgument( | 2290 | 0 | "In this situation, path expressions may not contain the * and ** " | 2291 | 0 | "tokens, argument index: {}, row index: {}", | 2292 | 0 | i, row_idx); | 2293 | 0 | } | 2294 | 3 | } | 2295 | | | 2296 | 4 | for (size_t row_idx = 0; row_idx != json_values[index].size(); ++row_idx) { | 2297 | 3 | if (json_value_null_maps[index] && (*json_value_null_maps[index])[row_idx]) { | 2298 | 0 | continue; | 2299 | 0 | } | 2300 | | | 2301 | 3 | auto value_string = value_column->get_data_at(row_idx); | 2302 | 3 | const JsonbDocument* doc = nullptr; | 2303 | 3 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(value_string.data, | 2304 | 3 | value_string.size, &doc)); | 2305 | 3 | if (doc) { | 2306 | 3 | json_values[index][row_idx] = doc->getValue(); | 2307 | 3 | } | 2308 | 3 | } | 2309 | 1 | } | 2310 | | | 2311 | 1 | return Status::OK(); | 2312 | 1 | } |
_ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE1EE22parse_paths_and_valuesERSt6vectorIS3_INS_9JsonbPathENS_18CustomStdAllocatorIS4_NS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEEEEENS5_ISA_S8_EEERS3_IS3_IPKNS_10JsonbValueENS5_ISG_S8_EEENS5_ISI_S8_EEERKS3_IjSaIjEEmRKS3_IPKNS_9ColumnStrIjEESaIST_EERKS3_IbSaIbEERKS3_IPKNS_8PODArrayIhLm4096ES8_Lm16ELm15EEESaIS15_EESX_S11_S19_ Line | Count | Source | 2265 | 1 | const std::vector<const NullMap*>& json_value_null_maps) const { | 2266 | 2 | for (size_t i = 1; i < arguments.size(); i += 2) { | 2267 | 1 | const size_t index = i / 2; | 2268 | 1 | const auto* json_path_column = json_path_columns[index]; | 2269 | 1 | const auto* value_column = json_value_columns[index]; | 2270 | | | 2271 | 1 | json_paths[index].resize(json_path_constant[index] ? 1 : input_rows_count); | 2272 | 1 | json_values[index].resize(json_value_constant[index] ? 1 : input_rows_count, nullptr); | 2273 | | | 2274 | 4 | for (size_t row_idx = 0; row_idx != json_paths[index].size(); ++row_idx) { | 2275 | 3 | if (json_path_null_maps[index] && (*json_path_null_maps[index])[row_idx]) { | 2276 | 0 | continue; | 2277 | 0 | } | 2278 | | | 2279 | 3 | auto path_string = json_path_column->get_data_at(row_idx); | 2280 | 3 | if (!json_paths[index][row_idx].seek(path_string.data, path_string.size)) { | 2281 | 0 | return Status::InvalidArgument( | 2282 | 0 | "Json path error: Invalid Json Path for value: {}, " | 2283 | 0 | "argument " | 2284 | 0 | "index: {}, row index: {}", | 2285 | 0 | std::string_view(path_string.data, path_string.size), i, row_idx); | 2286 | 0 | } | 2287 | | | 2288 | 3 | if (json_paths[index][row_idx].is_wildcard()) { | 2289 | 0 | return Status::InvalidArgument( | 2290 | 0 | "In this situation, path expressions may not contain the * and ** " | 2291 | 0 | "tokens, argument index: {}, row index: {}", | 2292 | 0 | i, row_idx); | 2293 | 0 | } | 2294 | 3 | } | 2295 | | | 2296 | 4 | for (size_t row_idx = 0; row_idx != json_values[index].size(); ++row_idx) { | 2297 | 3 | if (json_value_null_maps[index] && (*json_value_null_maps[index])[row_idx]) { | 2298 | 0 | continue; | 2299 | 0 | } | 2300 | | | 2301 | 3 | auto value_string = value_column->get_data_at(row_idx); | 2302 | 3 | const JsonbDocument* doc = nullptr; | 2303 | 3 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument(value_string.data, | 2304 | 3 | value_string.size, &doc)); | 2305 | 3 | if (doc) { | 2306 | 3 | json_values[index][row_idx] = doc->getValue(); | 2307 | 3 | } | 2308 | 3 | } | 2309 | 1 | } | 2310 | | | 2311 | 1 | return Status::OK(); | 2312 | 1 | } |
Unexecuted instantiation: _ZNK5doris19FunctionJsonbModifyILNS_15JsonbModifyTypeE2EE22parse_paths_and_valuesERSt6vectorIS3_INS_9JsonbPathENS_18CustomStdAllocatorIS4_NS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEEEEENS5_ISA_S8_EEERS3_IS3_IPKNS_10JsonbValueENS5_ISG_S8_EEENS5_ISI_S8_EEERKS3_IjSaIjEEmRKS3_IPKNS_9ColumnStrIjEESaIST_EERKS3_IbSaIbEERKS3_IPKNS_8PODArrayIhLm4096ES8_Lm16ELm15EEESaIS15_EESX_S11_S19_ |
2313 | | }; |
2314 | | |
2315 | | struct JsonbContainsAndPathImpl { |
2316 | 3 | static DataTypes get_variadic_argument_types() { |
2317 | 3 | return {std::make_shared<DataTypeJsonb>(), std::make_shared<DataTypeJsonb>(), |
2318 | 3 | std::make_shared<DataTypeString>()}; |
2319 | 3 | } |
2320 | | |
2321 | | static Status execute_impl(FunctionContext* context, Block& block, |
2322 | | const ColumnNumbers& arguments, uint32_t result, |
2323 | 2 | size_t input_rows_count) { |
2324 | 2 | return JsonbContainsUtil::jsonb_contains_execute(context, block, arguments, result, |
2325 | 2 | input_rows_count); |
2326 | 2 | } |
2327 | | }; |
2328 | | |
2329 | | class FunctionJsonSearch : public IFunction { |
2330 | | private: |
2331 | | using OneFun = std::function<Status(size_t, bool*)>; |
2332 | 0 | static Status always_one(size_t i, bool* res) { |
2333 | 0 | *res = true; |
2334 | 0 | return Status::OK(); |
2335 | 0 | } |
2336 | 0 | static Status always_all(size_t i, bool* res) { |
2337 | 0 | *res = false; |
2338 | 0 | return Status::OK(); |
2339 | 0 | } |
2340 | | |
2341 | | using CheckNullFun = std::function<bool(size_t)>; |
2342 | 0 | static bool always_not_null(size_t) { return false; } |
2343 | | |
2344 | | using GetJsonStringRefFun = std::function<StringRef(size_t)>; |
2345 | | |
2346 | 0 | Status matched(const std::string_view& str, LikeState* state, unsigned char* res) const { |
2347 | 0 | StringRef pattern; // not used |
2348 | 0 | StringRef value_val(str.data(), str.size()); |
2349 | 0 | return (state->scalar_function)(&state->search_state, value_val, pattern, res); |
2350 | 0 | } |
2351 | | |
2352 | | /** |
2353 | | * Recursive search for matching string, if found, the result will be added to a vector |
2354 | | * @param element json element |
2355 | | * @param one_match |
2356 | | * @param search_str |
2357 | | * @param cur_path |
2358 | | * @param matches The path that has already been matched |
2359 | | * @return true if matched else false |
2360 | | */ |
2361 | | bool find_matches(const JsonbValue* element, const bool& one_match, LikeState* state, |
2362 | 0 | JsonbPath* cur_path, std::unordered_set<std::string>* matches) const { |
2363 | 0 | if (element->isString()) { |
2364 | 0 | const auto* json_string = element->unpack<JsonbStringVal>(); |
2365 | 0 | const std::string_view element_str(json_string->getBlob(), json_string->length()); |
2366 | 0 | unsigned char res; |
2367 | 0 | RETURN_IF_ERROR(matched(element_str, state, &res)); |
2368 | 0 | if (res) { |
2369 | 0 | std::string str; |
2370 | 0 | auto valid = cur_path->to_string(&str); |
2371 | 0 | if (!valid) { |
2372 | 0 | return false; |
2373 | 0 | } |
2374 | 0 | return matches->insert(str).second; |
2375 | 0 | } else { |
2376 | 0 | return false; |
2377 | 0 | } |
2378 | 0 | } else if (element->isObject()) { |
2379 | 0 | const auto* object = element->unpack<ObjectVal>(); |
2380 | 0 | bool find = false; |
2381 | 0 | for (const auto& item : *object) { |
2382 | 0 | Slice key(item.getKeyStr(), item.klen()); |
2383 | 0 | const auto* child_element = item.value(); |
2384 | | // construct an object member path leg. |
2385 | 0 | auto leg = std::make_unique<leg_info>(key.data, key.size, 0, MEMBER_CODE); |
2386 | 0 | cur_path->add_leg_to_leg_vector(std::move(leg)); |
2387 | 0 | find |= find_matches(child_element, one_match, state, cur_path, matches); |
2388 | 0 | cur_path->pop_leg_from_leg_vector(); |
2389 | 0 | if (one_match && find) { |
2390 | 0 | return true; |
2391 | 0 | } |
2392 | 0 | } |
2393 | 0 | return find; |
2394 | 0 | } else if (element->isArray()) { |
2395 | 0 | const auto* array = element->unpack<ArrayVal>(); |
2396 | 0 | bool find = false; |
2397 | 0 | for (int i = 0; i < array->numElem(); ++i) { |
2398 | 0 | auto leg = std::make_unique<leg_info>(nullptr, 0, i, ARRAY_CODE); |
2399 | 0 | cur_path->add_leg_to_leg_vector(std::move(leg)); |
2400 | 0 | const auto* child_element = array->get(i); |
2401 | | // construct an array cell path leg. |
2402 | 0 | find |= find_matches(child_element, one_match, state, cur_path, matches); |
2403 | 0 | cur_path->pop_leg_from_leg_vector(); |
2404 | 0 | if (one_match && find) { |
2405 | 0 | return true; |
2406 | 0 | } |
2407 | 0 | } |
2408 | 0 | return find; |
2409 | 0 | } else { |
2410 | 0 | return false; |
2411 | 0 | } |
2412 | 0 | } |
2413 | | |
2414 | | void make_result_str(JsonbWriter& writer, std::unordered_set<std::string>& matches, |
2415 | 0 | ColumnString* result_col) const { |
2416 | 0 | if (matches.size() == 1) { |
2417 | 0 | for (const auto& str_ref : matches) { |
2418 | 0 | writer.writeStartString(); |
2419 | 0 | writer.writeString(str_ref); |
2420 | 0 | writer.writeEndString(); |
2421 | 0 | } |
2422 | 0 | } else { |
2423 | 0 | writer.writeStartArray(); |
2424 | 0 | for (const auto& str_ref : matches) { |
2425 | 0 | writer.writeStartString(); |
2426 | 0 | writer.writeString(str_ref); |
2427 | 0 | writer.writeEndString(); |
2428 | 0 | } |
2429 | 0 | writer.writeEndArray(); |
2430 | 0 | } |
2431 | |
|
2432 | 0 | result_col->insert_data(writer.getOutput()->getBuffer(), |
2433 | 0 | (size_t)writer.getOutput()->getSize()); |
2434 | 0 | } |
2435 | | |
2436 | | template <bool search_is_const> |
2437 | | Status execute_vector(Block& block, size_t input_rows_count, CheckNullFun json_null_check, |
2438 | | GetJsonStringRefFun col_json_string, CheckNullFun one_null_check, |
2439 | | OneFun one_check, CheckNullFun search_null_check, |
2440 | | const ColumnString* col_search_string, FunctionContext* context, |
2441 | 0 | size_t result) const { |
2442 | 0 | auto result_col = ColumnString::create(); |
2443 | 0 | auto null_map = ColumnUInt8::create(input_rows_count, 0); |
2444 | |
|
2445 | 0 | std::shared_ptr<LikeState> state_ptr; |
2446 | 0 | LikeState* state = nullptr; |
2447 | 0 | if (search_is_const) { |
2448 | 0 | state = reinterpret_cast<LikeState*>( |
2449 | 0 | context->get_function_state(FunctionContext::THREAD_LOCAL)); |
2450 | 0 | } |
2451 | |
|
2452 | 0 | bool is_one = false; |
2453 | |
|
2454 | 0 | JsonbWriter writer; |
2455 | 0 | for (size_t i = 0; i < input_rows_count; ++i) { |
2456 | | // an error occurs if the json_doc argument is not a valid json document. |
2457 | 0 | if (json_null_check(i)) { |
2458 | 0 | null_map->get_data()[i] = 1; |
2459 | 0 | result_col->insert_data("", 0); |
2460 | 0 | continue; |
2461 | 0 | } |
2462 | 0 | const auto& json_doc_str = col_json_string(i); |
2463 | 0 | const JsonbDocument* json_doc = nullptr; |
2464 | 0 | auto st = JsonbDocument::checkAndCreateDocument(json_doc_str.data, json_doc_str.size, |
2465 | 0 | &json_doc); |
2466 | 0 | if (!st.ok()) { |
2467 | 0 | return Status::InvalidArgument( |
2468 | 0 | "the json_doc argument at row {} is not a valid json document: {}", i, |
2469 | 0 | st.to_string()); |
2470 | 0 | } |
2471 | | |
2472 | 0 | if (!one_null_check(i)) { |
2473 | 0 | RETURN_IF_ERROR(one_check(i, &is_one)); |
2474 | 0 | } |
2475 | | |
2476 | 0 | if (one_null_check(i) || search_null_check(i)) { |
2477 | 0 | null_map->get_data()[i] = 1; |
2478 | 0 | result_col->insert_data("", 0); |
2479 | 0 | continue; |
2480 | 0 | } |
2481 | | |
2482 | | // an error occurs if any path argument is not a valid path expression. |
2483 | 0 | std::string root_path_str = "$"; |
2484 | 0 | JsonbPath root_path; |
2485 | 0 | root_path.seek(root_path_str.c_str(), root_path_str.size()); |
2486 | 0 | std::vector<JsonbPath*> paths; |
2487 | 0 | paths.push_back(&root_path); |
2488 | |
|
2489 | 0 | if (!search_is_const) { |
2490 | 0 | state_ptr = std::make_shared<LikeState>(); |
2491 | 0 | state_ptr->is_like_pattern = true; |
2492 | 0 | const auto& search_str = col_search_string->get_data_at(i); |
2493 | 0 | RETURN_IF_ERROR(FunctionLike::construct_like_const_state(context, search_str, |
2494 | 0 | state_ptr, false)); |
2495 | 0 | state = state_ptr.get(); |
2496 | 0 | } |
2497 | | |
2498 | | // maintain a hashset to deduplicate matches. |
2499 | 0 | std::unordered_set<std::string> matches; |
2500 | 0 | for (const auto& item : paths) { |
2501 | 0 | auto* cur_path = item; |
2502 | 0 | auto find = find_matches(json_doc->getValue(), is_one, state, cur_path, &matches); |
2503 | 0 | if (is_one && find) { |
2504 | 0 | break; |
2505 | 0 | } |
2506 | 0 | } |
2507 | 0 | if (matches.empty()) { |
2508 | | // returns NULL if the search_str is not found in the document. |
2509 | 0 | null_map->get_data()[i] = 1; |
2510 | 0 | result_col->insert_data("", 0); |
2511 | 0 | continue; |
2512 | 0 | } |
2513 | | |
2514 | 0 | writer.reset(); |
2515 | 0 | make_result_str(writer, matches, result_col.get()); |
2516 | 0 | } |
2517 | 0 | auto result_col_nullable = |
2518 | 0 | ColumnNullable::create(std::move(result_col), std::move(null_map)); |
2519 | 0 | block.replace_by_position(result, std::move(result_col_nullable)); |
2520 | 0 | return Status::OK(); |
2521 | 0 | } Unexecuted instantiation: _ZNK5doris18FunctionJsonSearch14execute_vectorILb1EEENS_6StatusERNS_5BlockEmSt8functionIFbmEES5_IFNS_9StringRefEmEES7_S5_IFS2_mPbEES7_PKNS_9ColumnStrIjEEPNS_15FunctionContextEm Unexecuted instantiation: _ZNK5doris18FunctionJsonSearch14execute_vectorILb0EEENS_6StatusERNS_5BlockEmSt8functionIFbmEES5_IFNS_9StringRefEmEES7_S5_IFS2_mPbEES7_PKNS_9ColumnStrIjEEPNS_15FunctionContextEm |
2522 | | |
2523 | | static constexpr auto one = "one"; |
2524 | | static constexpr auto all = "all"; |
2525 | | |
2526 | | public: |
2527 | | static constexpr auto name = "json_search"; |
2528 | 2 | static FunctionPtr create() { return std::make_shared<FunctionJsonSearch>(); } |
2529 | | |
2530 | 1 | String get_name() const override { return name; } |
2531 | 1 | bool is_variadic() const override { return false; } |
2532 | 0 | size_t get_number_of_arguments() const override { return 3; } |
2533 | | |
2534 | 0 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
2535 | 0 | return make_nullable(std::make_shared<DataTypeJsonb>()); |
2536 | 0 | } |
2537 | | |
2538 | 0 | bool use_default_implementation_for_nulls() const override { return false; } |
2539 | | |
2540 | 0 | Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override { |
2541 | 0 | if (scope != FunctionContext::THREAD_LOCAL) { |
2542 | 0 | return Status::OK(); |
2543 | 0 | } |
2544 | 0 | if (context->is_col_constant(2)) { |
2545 | 0 | std::shared_ptr<LikeState> state = std::make_shared<LikeState>(); |
2546 | 0 | state->is_like_pattern = true; |
2547 | 0 | const auto pattern_col = context->get_constant_col(2)->column_ptr; |
2548 | 0 | const auto& pattern = pattern_col->get_data_at(0); |
2549 | 0 | RETURN_IF_ERROR( |
2550 | 0 | FunctionLike::construct_like_const_state(context, pattern, state, false)); |
2551 | 0 | context->set_function_state(scope, state); |
2552 | 0 | } |
2553 | 0 | return Status::OK(); |
2554 | 0 | } |
2555 | | |
2556 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
2557 | 0 | uint32_t result, size_t input_rows_count) const override { |
2558 | | // the json_doc, one_or_all, and search_str must be given. |
2559 | | // and we require the positions are static. |
2560 | 0 | if (arguments.size() < 3) { |
2561 | 0 | return Status::InvalidArgument("too few arguments for function {}", name); |
2562 | 0 | } |
2563 | 0 | if (arguments.size() > 3) { |
2564 | 0 | return Status::NotSupported("escape and path params are not support now"); |
2565 | 0 | } |
2566 | | |
2567 | 0 | CheckNullFun json_null_check = always_not_null; |
2568 | 0 | GetJsonStringRefFun get_json_fun; |
2569 | | // prepare jsonb data column |
2570 | 0 | auto&& [col_json, json_is_const] = |
2571 | 0 | unpack_if_const(block.get_by_position(arguments[0]).column); |
2572 | 0 | const auto* col_json_string = check_and_get_column<ColumnString>(col_json.get()); |
2573 | 0 | if (const auto* nullable = check_and_get_column<ColumnNullable>(col_json.get())) { |
2574 | 0 | col_json_string = |
2575 | 0 | check_and_get_column<ColumnString>(nullable->get_nested_column_ptr().get()); |
2576 | 0 | } |
2577 | |
|
2578 | 0 | if (!col_json_string) { |
2579 | 0 | return Status::RuntimeError("Illegal arg json {} should be ColumnString", |
2580 | 0 | col_json->get_name()); |
2581 | 0 | } |
2582 | | |
2583 | 0 | auto create_all_null_result = [&]() { |
2584 | 0 | auto res_str = ColumnString::create(); |
2585 | 0 | res_str->insert_default(); |
2586 | 0 | auto res = ColumnNullable::create(std::move(res_str), ColumnUInt8::create(1, 1)); |
2587 | 0 | if (input_rows_count > 1) { |
2588 | 0 | block.get_by_position(result).column = |
2589 | 0 | ColumnConst::create(std::move(res), input_rows_count); |
2590 | 0 | } else { |
2591 | 0 | block.get_by_position(result).column = std::move(res); |
2592 | 0 | } |
2593 | 0 | return Status::OK(); |
2594 | 0 | }; |
2595 | |
|
2596 | 0 | if (json_is_const) { |
2597 | 0 | if (col_json->is_null_at(0)) { |
2598 | 0 | return create_all_null_result(); |
2599 | 0 | } else { |
2600 | 0 | const auto& json_str = col_json_string->get_data_at(0); |
2601 | 0 | get_json_fun = [json_str](size_t i) { return json_str; }; |
2602 | 0 | } |
2603 | 0 | } else { |
2604 | 0 | json_null_check = [col_json](size_t i) { return col_json->is_null_at(i); }; |
2605 | 0 | get_json_fun = [col_json_string](size_t i) { return col_json_string->get_data_at(i); }; |
2606 | 0 | } |
2607 | | |
2608 | | // one_or_all |
2609 | 0 | CheckNullFun one_null_check = always_not_null; |
2610 | 0 | OneFun one_check = always_one; |
2611 | 0 | auto&& [col_one, one_is_const] = |
2612 | 0 | unpack_if_const(block.get_by_position(arguments[1]).column); |
2613 | 0 | one_is_const |= input_rows_count == 1; |
2614 | 0 | const auto* col_one_string = check_and_get_column<ColumnString>(col_one.get()); |
2615 | 0 | if (const auto* nullable = check_and_get_column<ColumnNullable>(col_one.get())) { |
2616 | 0 | col_one_string = check_and_get_column<ColumnString>(*nullable->get_nested_column_ptr()); |
2617 | 0 | } |
2618 | 0 | if (!col_one_string) { |
2619 | 0 | return Status::RuntimeError("Illegal arg one {} should be ColumnString", |
2620 | 0 | col_one->get_name()); |
2621 | 0 | } |
2622 | 0 | if (one_is_const) { |
2623 | 0 | if (col_one->is_null_at(0)) { |
2624 | 0 | return create_all_null_result(); |
2625 | 0 | } else { |
2626 | 0 | const auto& one_or_all = col_one_string->get_data_at(0); |
2627 | 0 | std::string one_or_all_str = one_or_all.to_string(); |
2628 | 0 | if (strcasecmp(one_or_all_str.c_str(), all) == 0) { |
2629 | 0 | one_check = always_all; |
2630 | 0 | } else if (strcasecmp(one_or_all_str.c_str(), one) == 0) { |
2631 | | // nothing |
2632 | 0 | } else { |
2633 | | // an error occurs if the one_or_all argument is not 'one' nor 'all'. |
2634 | 0 | return Status::InvalidArgument( |
2635 | 0 | "the one_or_all argument {} is not 'one' not 'all'", one_or_all_str); |
2636 | 0 | } |
2637 | 0 | } |
2638 | 0 | } else { |
2639 | 0 | one_null_check = [col_one](size_t i) { return col_one->is_null_at(i); }; |
2640 | 0 | one_check = [col_one_string](size_t i, bool* is_one) { |
2641 | 0 | const auto& one_or_all = col_one_string->get_data_at(i); |
2642 | 0 | std::string one_or_all_str = one_or_all.to_string(); |
2643 | 0 | if (strcasecmp(one_or_all_str.c_str(), all) == 0) { |
2644 | 0 | *is_one = false; |
2645 | 0 | } else if (strcasecmp(one_or_all_str.c_str(), one) == 0) { |
2646 | 0 | *is_one = true; |
2647 | 0 | } else { |
2648 | | // an error occurs if the one_or_all argument is not 'one' nor 'all'. |
2649 | 0 | return Status::InvalidArgument( |
2650 | 0 | "the one_or_all argument {} is not 'one' not 'all'", one_or_all_str); |
2651 | 0 | } |
2652 | 0 | return Status::OK(); |
2653 | 0 | }; |
2654 | 0 | } |
2655 | | |
2656 | | // search_str |
2657 | 0 | auto&& [col_search, search_is_const] = |
2658 | 0 | unpack_if_const(block.get_by_position(arguments[2]).column); |
2659 | |
|
2660 | 0 | const auto* col_search_string = check_and_get_column<ColumnString>(col_search.get()); |
2661 | 0 | if (const auto* nullable = check_and_get_column<ColumnNullable>(col_search.get())) { |
2662 | 0 | col_search_string = |
2663 | 0 | check_and_get_column<ColumnString>(*nullable->get_nested_column_ptr()); |
2664 | 0 | } |
2665 | 0 | if (!col_search_string) { |
2666 | 0 | return Status::RuntimeError("Illegal arg pattern {} should be ColumnString", |
2667 | 0 | col_search->get_name()); |
2668 | 0 | } |
2669 | 0 | if (search_is_const) { |
2670 | 0 | CheckNullFun search_null_check = always_not_null; |
2671 | 0 | if (col_search->is_null_at(0)) { |
2672 | 0 | return create_all_null_result(); |
2673 | 0 | } |
2674 | 0 | RETURN_IF_ERROR(execute_vector<true>( |
2675 | 0 | block, input_rows_count, json_null_check, get_json_fun, one_null_check, |
2676 | 0 | one_check, search_null_check, col_search_string, context, result)); |
2677 | 0 | } else { |
2678 | 0 | CheckNullFun search_null_check = [col_search](size_t i) { |
2679 | 0 | return col_search->is_null_at(i); |
2680 | 0 | }; |
2681 | 0 | RETURN_IF_ERROR(execute_vector<false>( |
2682 | 0 | block, input_rows_count, json_null_check, get_json_fun, one_null_check, |
2683 | 0 | one_check, search_null_check, col_search_string, context, result)); |
2684 | 0 | } |
2685 | 0 | return Status::OK(); |
2686 | 0 | } |
2687 | | }; |
2688 | | |
2689 | | struct DocumentBuffer { |
2690 | | std::unique_ptr<char[]> ptr; |
2691 | | size_t size = 0; |
2692 | | size_t capacity = 0; |
2693 | | }; |
2694 | | |
2695 | | class FunctionJsonbRemove : public IFunction { |
2696 | | public: |
2697 | | static constexpr auto name = "jsonb_remove"; |
2698 | | static constexpr auto alias = "json_remove"; |
2699 | | |
2700 | 2 | static FunctionPtr create() { return std::make_shared<FunctionJsonbRemove>(); } |
2701 | | |
2702 | 0 | String get_name() const override { return name; } |
2703 | | |
2704 | 0 | size_t get_number_of_arguments() const override { return 0; } |
2705 | 1 | bool is_variadic() const override { return true; } |
2706 | | |
2707 | 0 | bool use_default_implementation_for_nulls() const override { return false; } |
2708 | | |
2709 | 0 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
2710 | 0 | return make_nullable(std::make_shared<DataTypeJsonb>()); |
2711 | 0 | } |
2712 | | |
2713 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
2714 | 0 | uint32_t result, size_t input_rows_count) const override { |
2715 | 0 | DORIS_CHECK_GE(arguments.size(), 2); |
2716 | | |
2717 | | // Check if arguments count is valid (json_doc + at least one path) |
2718 | 0 | if (arguments.size() < 2) { |
2719 | 0 | return Status::InvalidArgument("json_remove requires at least 2 arguments"); |
2720 | 0 | } |
2721 | | |
2722 | 0 | auto return_data_type = make_nullable(std::make_shared<DataTypeJsonb>()); |
2723 | 0 | auto result_column = return_data_type->create_column(); |
2724 | 0 | auto& nullable_column = assert_cast<ColumnNullable&>(*result_column); |
2725 | 0 | auto& res_chars = |
2726 | 0 | assert_cast<ColumnString&>(nullable_column.get_nested_column()).get_chars(); |
2727 | 0 | auto& res_offsets = |
2728 | 0 | assert_cast<ColumnString&>(nullable_column.get_nested_column()).get_offsets(); |
2729 | 0 | auto& null_map = nullable_column.get_null_map_data(); |
2730 | |
|
2731 | 0 | res_chars.reserve(input_rows_count * 64); |
2732 | 0 | res_offsets.resize(input_rows_count); |
2733 | 0 | null_map.resize_fill(input_rows_count, 0); |
2734 | | |
2735 | | // Get JSON document column |
2736 | 0 | auto [json_column, json_const] = |
2737 | 0 | unpack_if_const(block.get_by_position(arguments[0]).column); |
2738 | 0 | const auto* json_nullable = check_and_get_column<ColumnNullable>(json_column.get()); |
2739 | 0 | const ColumnString* json_data_column = nullptr; |
2740 | 0 | const NullMap* json_null_map = nullptr; |
2741 | |
|
2742 | 0 | if (json_nullable) { |
2743 | 0 | json_null_map = &json_nullable->get_null_map_data(); |
2744 | 0 | json_data_column = |
2745 | 0 | check_and_get_column<ColumnString>(&json_nullable->get_nested_column()); |
2746 | 0 | } else { |
2747 | 0 | json_data_column = check_and_get_column<ColumnString>(json_column.get()); |
2748 | 0 | } |
2749 | |
|
2750 | 0 | if (!json_data_column) { |
2751 | 0 | return Status::InvalidArgument("First argument must be a JSON document"); |
2752 | 0 | } |
2753 | | |
2754 | | // Parse paths |
2755 | 0 | std::vector<const ColumnString*> path_columns; |
2756 | 0 | std::vector<const NullMap*> path_null_maps; |
2757 | 0 | std::vector<bool> path_constants; |
2758 | |
|
2759 | 0 | for (size_t i = 1; i < arguments.size(); ++i) { |
2760 | 0 | auto [path_column, path_const] = |
2761 | 0 | unpack_if_const(block.get_by_position(arguments[i]).column); |
2762 | 0 | const auto* path_nullable = check_and_get_column<ColumnNullable>(path_column.get()); |
2763 | |
|
2764 | 0 | if (path_nullable) { |
2765 | 0 | path_null_maps.push_back(&path_nullable->get_null_map_data()); |
2766 | 0 | path_columns.push_back( |
2767 | 0 | check_and_get_column<ColumnString>(&path_nullable->get_nested_column())); |
2768 | 0 | } else { |
2769 | 0 | path_null_maps.push_back(nullptr); |
2770 | 0 | path_columns.push_back(check_and_get_column<ColumnString>(path_column.get())); |
2771 | 0 | } |
2772 | |
|
2773 | 0 | if (!path_columns.back()) { |
2774 | 0 | return Status::InvalidArgument( |
2775 | 0 | fmt::format("Argument {} must be a string path", i + 1)); |
2776 | 0 | } |
2777 | | |
2778 | 0 | path_constants.push_back(path_const); |
2779 | 0 | } |
2780 | | |
2781 | | // Reusable JsonbWriter for performance |
2782 | 0 | JsonbWriter writer; |
2783 | |
|
2784 | 0 | for (size_t row_idx = 0; row_idx < input_rows_count; ++row_idx) { |
2785 | 0 | size_t json_idx = index_check_const(row_idx, json_const); |
2786 | | |
2787 | | // Check if JSON document is null |
2788 | 0 | if (json_null_map && (*json_null_map)[json_idx]) { |
2789 | 0 | null_map[row_idx] = 1; |
2790 | 0 | res_offsets[row_idx] = static_cast<uint32_t>(res_chars.size()); |
2791 | 0 | continue; |
2792 | 0 | } |
2793 | | |
2794 | | // Parse JSON document |
2795 | 0 | const auto& json_data = json_data_column->get_data_at(json_idx); |
2796 | 0 | const JsonbDocument* json_doc = nullptr; |
2797 | 0 | Status parse_status = JsonbDocument::checkAndCreateDocument(json_data.data, |
2798 | 0 | json_data.size, &json_doc); |
2799 | |
|
2800 | 0 | if (!parse_status.ok() || !json_doc) { |
2801 | 0 | null_map[row_idx] = 1; |
2802 | 0 | res_offsets[row_idx] = static_cast<uint32_t>(res_chars.size()); |
2803 | 0 | continue; |
2804 | 0 | } |
2805 | | |
2806 | | // Check if any path is null |
2807 | 0 | bool has_null_path = false; |
2808 | 0 | for (size_t path_idx = 0; path_idx < path_columns.size(); ++path_idx) { |
2809 | 0 | size_t idx = index_check_const(row_idx, path_constants[path_idx]); |
2810 | 0 | if (path_null_maps[path_idx] && (*path_null_maps[path_idx])[idx]) { |
2811 | 0 | has_null_path = true; |
2812 | 0 | break; |
2813 | 0 | } |
2814 | 0 | } |
2815 | |
|
2816 | 0 | if (has_null_path) { |
2817 | 0 | null_map[row_idx] = 1; |
2818 | 0 | res_offsets[row_idx] = static_cast<uint32_t>(res_chars.size()); |
2819 | 0 | continue; |
2820 | 0 | } |
2821 | | |
2822 | 0 | std::vector<JsonbPath> paths; |
2823 | 0 | std::vector<bool> path_constants_vec; |
2824 | |
|
2825 | 0 | for (size_t path_idx = 0; path_idx < path_columns.size(); ++path_idx) { |
2826 | 0 | size_t idx = index_check_const(row_idx, path_constants[path_idx]); |
2827 | 0 | const auto& path_data = path_columns[path_idx]->get_data_at(idx); |
2828 | |
|
2829 | 0 | JsonbPath path; |
2830 | 0 | if (!path.seek(path_data.data, path_data.size)) { |
2831 | 0 | return Status::InvalidArgument( |
2832 | 0 | "Json path error: Invalid Json Path for value: {} at row: {}", |
2833 | 0 | std::string_view(path_data.data, path_data.size), row_idx); |
2834 | 0 | } |
2835 | | |
2836 | 0 | if (path.is_wildcard() || path.is_supper_wildcard()) { |
2837 | 0 | return Status::InvalidArgument( |
2838 | 0 | "In this situation, path expressions may not contain the * and ** " |
2839 | 0 | "tokens or an array range, argument index: {}, row index: {}", |
2840 | 0 | path_idx + 1, row_idx); |
2841 | 0 | } |
2842 | | |
2843 | 0 | paths.push_back(std::move(path)); |
2844 | 0 | path_constants_vec.push_back(path_constants[path_idx]); |
2845 | 0 | } |
2846 | | |
2847 | 0 | const JsonbValue* current_value = json_doc->getValue(); |
2848 | |
|
2849 | 0 | DocumentBuffer tmp_buffer; |
2850 | |
|
2851 | 0 | for (size_t path_idx = 0; path_idx < paths.size(); ++path_idx) { |
2852 | 0 | writer.reset(); |
2853 | |
|
2854 | 0 | auto find_result = current_value->findValue(paths[path_idx]); |
2855 | |
|
2856 | 0 | if (find_result.is_wildcard) { |
2857 | 0 | continue; |
2858 | 0 | } |
2859 | | |
2860 | 0 | if (find_result.value) { |
2861 | 0 | RETURN_IF_ERROR(clone_without_path(current_value, paths[path_idx], writer)); |
2862 | | |
2863 | 0 | auto* writer_output = writer.getOutput(); |
2864 | 0 | if (writer_output->getSize() > tmp_buffer.capacity) { |
2865 | 0 | tmp_buffer.capacity = |
2866 | 0 | ((size_t(writer_output->getSize()) + 1024 - 1) / 1024) * 1024; |
2867 | 0 | tmp_buffer.ptr = std::make_unique<char[]>(tmp_buffer.capacity); |
2868 | 0 | DCHECK_LE(writer_output->getSize(), tmp_buffer.capacity); |
2869 | 0 | } |
2870 | |
|
2871 | 0 | memcpy(tmp_buffer.ptr.get(), writer_output->getBuffer(), |
2872 | 0 | writer_output->getSize()); |
2873 | 0 | tmp_buffer.size = writer_output->getSize(); |
2874 | |
|
2875 | 0 | const JsonbDocument* new_doc = nullptr; |
2876 | 0 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument( |
2877 | 0 | tmp_buffer.ptr.get(), tmp_buffer.size, &new_doc)); |
2878 | | |
2879 | 0 | current_value = new_doc->getValue(); |
2880 | 0 | } |
2881 | 0 | } |
2882 | | |
2883 | 0 | const JsonbDocument* modified_doc = nullptr; |
2884 | 0 | if (current_value != json_doc->getValue()) { |
2885 | 0 | RETURN_IF_ERROR(JsonbDocument::checkAndCreateDocument( |
2886 | 0 | tmp_buffer.ptr.get(), tmp_buffer.size, &modified_doc)); |
2887 | 0 | } else { |
2888 | 0 | modified_doc = json_doc; |
2889 | 0 | } |
2890 | | |
2891 | | // Write the final result |
2892 | 0 | const auto size = modified_doc->numPackedBytes(); |
2893 | 0 | res_chars.insert(reinterpret_cast<const char*>(modified_doc), |
2894 | 0 | reinterpret_cast<const char*>(modified_doc) + size); |
2895 | 0 | res_offsets[row_idx] = static_cast<uint32_t>(res_chars.size()); |
2896 | 0 | } |
2897 | | |
2898 | 0 | block.get_by_position(result).column = std::move(result_column); |
2899 | 0 | return Status::OK(); |
2900 | 0 | } |
2901 | | |
2902 | | private: |
2903 | | Status clone_without_path(const JsonbValue* root, const JsonbPath& path, |
2904 | 0 | JsonbWriter& writer) const { |
2905 | | // Start writing at the root level |
2906 | 0 | if (root->isObject()) { |
2907 | 0 | writer.writeStartObject(); |
2908 | 0 | RETURN_IF_ERROR(clone_object_without_path(root, path, 0, writer)); |
2909 | 0 | writer.writeEndObject(); |
2910 | 0 | } else if (root->isArray()) { |
2911 | 0 | writer.writeStartArray(); |
2912 | 0 | RETURN_IF_ERROR(clone_array_without_path(root, path, 0, writer)); |
2913 | 0 | writer.writeEndArray(); |
2914 | 0 | } else { |
2915 | | // Primitive value - can't remove anything from it |
2916 | 0 | writer.writeValue(root); |
2917 | 0 | } |
2918 | 0 | return Status::OK(); |
2919 | 0 | } |
2920 | | |
2921 | | Status clone_object_without_path(const JsonbValue* obj_value, const JsonbPath& path, |
2922 | 0 | size_t depth, JsonbWriter& writer) const { |
2923 | 0 | const auto* obj = obj_value->unpack<ObjectVal>(); |
2924 | |
|
2925 | 0 | for (const auto& kv : *obj) { |
2926 | 0 | std::string key(kv.getKeyStr(), kv.klen()); |
2927 | |
|
2928 | 0 | if (depth < path.get_leg_vector_size()) { |
2929 | 0 | const auto* leg = path.get_leg_from_leg_vector(depth); |
2930 | 0 | if (leg->type == MEMBER_CODE) { |
2931 | 0 | std::string target_key(leg->leg_ptr, leg->leg_len); |
2932 | |
|
2933 | 0 | if (key == target_key) { |
2934 | 0 | if (depth == path.get_leg_vector_size() - 1) { |
2935 | 0 | continue; |
2936 | 0 | } else { |
2937 | 0 | writer.writeKey(kv.getKeyStr(), kv.klen()); |
2938 | 0 | if (kv.value()->isObject()) { |
2939 | 0 | writer.writeStartObject(); |
2940 | 0 | RETURN_IF_ERROR(clone_object_without_path(kv.value(), path, |
2941 | 0 | depth + 1, writer)); |
2942 | 0 | writer.writeEndObject(); |
2943 | 0 | } else if (kv.value()->isArray()) { |
2944 | 0 | writer.writeStartArray(); |
2945 | 0 | RETURN_IF_ERROR(clone_array_without_path(kv.value(), path, |
2946 | 0 | depth + 1, writer)); |
2947 | 0 | writer.writeEndArray(); |
2948 | 0 | } else { |
2949 | 0 | writer.writeValue(kv.value()); |
2950 | 0 | } |
2951 | 0 | } |
2952 | 0 | } else { |
2953 | 0 | writer.writeKey(kv.getKeyStr(), kv.klen()); |
2954 | 0 | writer.writeValue(kv.value()); |
2955 | 0 | } |
2956 | 0 | } else { |
2957 | 0 | writer.writeKey(kv.getKeyStr(), kv.klen()); |
2958 | 0 | writer.writeValue(kv.value()); |
2959 | 0 | } |
2960 | 0 | } else { |
2961 | 0 | writer.writeKey(kv.getKeyStr(), kv.klen()); |
2962 | 0 | writer.writeValue(kv.value()); |
2963 | 0 | } |
2964 | 0 | } |
2965 | | |
2966 | 0 | return Status::OK(); |
2967 | 0 | } |
2968 | | |
2969 | | Status clone_array_without_path(const JsonbValue* arr_value, const JsonbPath& path, |
2970 | 0 | size_t depth, JsonbWriter& writer) const { |
2971 | 0 | const auto* arr = arr_value->unpack<ArrayVal>(); |
2972 | |
|
2973 | 0 | int index = 0; |
2974 | 0 | for (const auto& element : *arr) { |
2975 | 0 | if (depth < path.get_leg_vector_size()) { |
2976 | 0 | const auto* leg = path.get_leg_from_leg_vector(depth); |
2977 | 0 | if (leg->type == ARRAY_CODE) { |
2978 | 0 | int target_index = leg->array_index; |
2979 | |
|
2980 | 0 | if (index == target_index) { |
2981 | 0 | if (depth == path.get_leg_vector_size() - 1) { |
2982 | | // This is the target element to remove - skip it |
2983 | 0 | } else { |
2984 | 0 | if (element.isObject()) { |
2985 | 0 | writer.writeStartObject(); |
2986 | 0 | RETURN_IF_ERROR(clone_object_without_path(&element, path, depth + 1, |
2987 | 0 | writer)); |
2988 | 0 | writer.writeEndObject(); |
2989 | 0 | } else if (element.isArray()) { |
2990 | 0 | writer.writeStartArray(); |
2991 | 0 | RETURN_IF_ERROR(clone_array_without_path(&element, path, depth + 1, |
2992 | 0 | writer)); |
2993 | 0 | writer.writeEndArray(); |
2994 | 0 | } else { |
2995 | 0 | writer.writeValue(&element); |
2996 | 0 | } |
2997 | 0 | } |
2998 | 0 | } else { |
2999 | 0 | writer.writeValue(&element); |
3000 | 0 | } |
3001 | 0 | } else { |
3002 | 0 | writer.writeValue(&element); |
3003 | 0 | } |
3004 | 0 | } else { |
3005 | 0 | writer.writeValue(&element); |
3006 | 0 | } |
3007 | 0 | index++; |
3008 | 0 | } |
3009 | | |
3010 | 0 | return Status::OK(); |
3011 | 0 | } |
3012 | | }; |
3013 | | |
3014 | | class FunctionStripNullValue : public IFunction { |
3015 | | public: |
3016 | | static constexpr auto name = "strip_null_value"; |
3017 | 2 | static FunctionPtr create() { return std::make_shared<FunctionStripNullValue>(); } |
3018 | | |
3019 | 1 | String get_name() const override { return name; } |
3020 | 1 | bool is_variadic() const override { return false; } |
3021 | 0 | size_t get_number_of_arguments() const override { return 1; } |
3022 | | |
3023 | 0 | bool use_default_implementation_for_nulls() const override { return false; } |
3024 | | |
3025 | 0 | DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { |
3026 | 0 | return make_nullable(std::make_shared<DataTypeJsonb>()); |
3027 | 0 | } |
3028 | | |
3029 | | Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, |
3030 | 0 | uint32_t result, size_t input_rows_count) const override { |
3031 | 0 | const auto arg_column = |
3032 | 0 | block.get_by_position(arguments[0]).column->convert_to_full_column_if_const(); |
3033 | 0 | const ColumnString* json_column = nullptr; |
3034 | 0 | const NullMap* json_null_map = nullptr; |
3035 | 0 | if (const auto* nullable_col = check_and_get_column<ColumnNullable>(arg_column.get())) { |
3036 | 0 | json_column = assert_cast<const ColumnString*>(&nullable_col->get_nested_column()); |
3037 | 0 | json_null_map = &nullable_col->get_null_map_data(); |
3038 | 0 | } else { |
3039 | 0 | json_column = assert_cast<const ColumnString*>(arg_column.get()); |
3040 | 0 | } |
3041 | |
|
3042 | 0 | auto return_data_type = make_nullable(std::make_shared<DataTypeJsonb>()); |
3043 | 0 | auto result_column = return_data_type->create_column(); |
3044 | |
|
3045 | 0 | auto& result_nullmap = assert_cast<ColumnNullable&>(*result_column).get_null_map_data(); |
3046 | 0 | auto& result_data_col = assert_cast<ColumnString&>( |
3047 | 0 | assert_cast<ColumnNullable&>(*result_column).get_nested_column()); |
3048 | |
|
3049 | 0 | result_nullmap.resize_fill(input_rows_count, 0); |
3050 | 0 | for (size_t i = 0; i != input_rows_count; ++i) { |
3051 | 0 | if (json_null_map && (*json_null_map)[i]) { |
3052 | 0 | result_nullmap[i] = 1; |
3053 | 0 | result_data_col.insert_default(); |
3054 | 0 | continue; |
3055 | 0 | } |
3056 | 0 | const JsonbDocument* json_doc = nullptr; |
3057 | 0 | const auto& json_str = json_column->get_data_at(i); |
3058 | 0 | RETURN_IF_ERROR( |
3059 | 0 | JsonbDocument::checkAndCreateDocument(json_str.data, json_str.size, &json_doc)); |
3060 | 0 | if (json_doc) [[likely]] { |
3061 | 0 | if (json_doc->getValue()->isNull()) { |
3062 | 0 | result_nullmap[i] = 1; |
3063 | 0 | result_data_col.insert_default(); |
3064 | 0 | } else { |
3065 | 0 | result_nullmap[i] = 0; |
3066 | 0 | result_data_col.insert_data(json_str.data, json_str.size); |
3067 | 0 | } |
3068 | 0 | } else { |
3069 | 0 | result_nullmap[i] = 1; |
3070 | 0 | result_data_col.insert_default(); |
3071 | 0 | } |
3072 | 0 | } |
3073 | | |
3074 | 0 | block.get_by_position(result).column = std::move(result_column); |
3075 | 0 | return Status::OK(); |
3076 | 0 | } |
3077 | | }; |
3078 | | |
3079 | 1 | void register_function_jsonb(SimpleFunctionFactory& factory) { |
3080 | 1 | factory.register_function<FunctionJsonbParse>(FunctionJsonbParse::name); |
3081 | 1 | factory.register_alias(FunctionJsonbParse::name, FunctionJsonbParse::alias); |
3082 | 1 | factory.register_function<FunctionJsonbParseErrorNull>("json_parse_error_to_null"); |
3083 | 1 | factory.register_alias("json_parse_error_to_null", "jsonb_parse_error_to_null"); |
3084 | 1 | factory.register_function<FunctionJsonbParseErrorValue>("json_parse_error_to_value"); |
3085 | 1 | factory.register_alias("json_parse_error_to_value", "jsonb_parse_error_to_value"); |
3086 | | |
3087 | 1 | factory.register_function<FunctionJsonbExists>(); |
3088 | 1 | factory.register_alias(FunctionJsonbExists::name, FunctionJsonbExists::alias); |
3089 | 1 | factory.register_function<FunctionJsonbType>(); |
3090 | 1 | factory.register_alias(FunctionJsonbType::name, FunctionJsonbType::alias); |
3091 | | |
3092 | 1 | factory.register_function<FunctionJsonbKeys>(); |
3093 | 1 | factory.register_alias(FunctionJsonbKeys::name, FunctionJsonbKeys::alias); |
3094 | | |
3095 | 1 | factory.register_function<FunctionJsonbExtractIsnull>(); |
3096 | 1 | factory.register_alias(FunctionJsonbExtractIsnull::name, FunctionJsonbExtractIsnull::alias); |
3097 | | |
3098 | 1 | factory.register_function<FunctionJsonbExtractJsonb>(); |
3099 | 1 | factory.register_alias(FunctionJsonbExtractJsonb::name, FunctionJsonbExtractJsonb::alias); |
3100 | 1 | factory.register_function<FunctionJsonbExtractJsonbNoQuotes>(); |
3101 | 1 | factory.register_alias(FunctionJsonbExtractJsonbNoQuotes::name, |
3102 | 1 | FunctionJsonbExtractJsonbNoQuotes::alias); |
3103 | | |
3104 | 1 | factory.register_function<FunctionJsonbLength<JsonbLengthAndPathImpl>>(); |
3105 | 1 | factory.register_function<FunctionJsonbContains<JsonbContainsAndPathImpl>>(); |
3106 | | |
3107 | 1 | factory.register_function<FunctionJsonSearch>(); |
3108 | | |
3109 | 1 | factory.register_function<FunctionJsonbArray<false>>(); |
3110 | 1 | factory.register_alias(FunctionJsonbArray<false>::name, FunctionJsonbArray<false>::alias); |
3111 | | |
3112 | 1 | factory.register_function<FunctionJsonbArray<true>>("json_array_ignore_null"); |
3113 | 1 | factory.register_alias("json_array_ignore_null", "jsonb_array_ignore_null"); |
3114 | | |
3115 | 1 | factory.register_function<FunctionJsonbObject>(); |
3116 | 1 | factory.register_alias(FunctionJsonbObject::name, FunctionJsonbObject::alias); |
3117 | | |
3118 | 1 | factory.register_function<FunctionJsonbModify<JsonbModifyType::Insert>>(); |
3119 | 1 | factory.register_alias(FunctionJsonbModify<JsonbModifyType::Insert>::name, |
3120 | 1 | FunctionJsonbModify<JsonbModifyType::Insert>::alias); |
3121 | 1 | factory.register_function<FunctionJsonbModify<JsonbModifyType::Set>>(); |
3122 | 1 | factory.register_alias(FunctionJsonbModify<JsonbModifyType::Set>::name, |
3123 | 1 | FunctionJsonbModify<JsonbModifyType::Set>::alias); |
3124 | 1 | factory.register_function<FunctionJsonbModify<JsonbModifyType::Replace>>(); |
3125 | 1 | factory.register_alias(FunctionJsonbModify<JsonbModifyType::Replace>::name, |
3126 | 1 | FunctionJsonbModify<JsonbModifyType::Replace>::alias); |
3127 | | |
3128 | 1 | factory.register_function<FunctionJsonbRemove>(); |
3129 | 1 | factory.register_alias(FunctionJsonbRemove::name, FunctionJsonbRemove::alias); |
3130 | | |
3131 | 1 | factory.register_function<FunctionStripNullValue>(); |
3132 | 1 | } |
3133 | | |
3134 | | } // namespace doris |