Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enhancement] to_json return null when unsupported (backport #45607) #50157

Merged
merged 1 commit into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion be/src/exprs/cast_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ struct CastToString {
}
};

StatusOr<ColumnPtr> cast_nested_to_json(const ColumnPtr& column);
StatusOr<ColumnPtr> cast_nested_to_json(const ColumnPtr& column, bool allow_throw_exception);

// cast column[idx] to coresponding json type.
StatusOr<std::string> cast_type_to_json_str(const ColumnPtr& column, int idx);
Expand Down
38 changes: 28 additions & 10 deletions be/src/exprs/cast_expr_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ class CastColumnItemVisitor final : public ColumnVisitorAdapter<CastColumnItemVi
auto val_col = col.values_column();

if (key_col->has_null()) {
return Status::NotSupported("key of Map should not be nullable");
return Status::NotSupported("key of Map should not be null");
}
if (key_col->is_nullable()) {
key_col = ColumnHelper::as_column<NullableColumn>(key_col)->data_column();
Expand Down Expand Up @@ -216,20 +216,38 @@ class CastColumnItemVisitor final : public ColumnVisitorAdapter<CastColumnItemVi

// Cast nested type(including struct/map/* to json)
// TODO(murphy): optimize the performance with columnwise-casting
StatusOr<ColumnPtr> cast_nested_to_json(const ColumnPtr& column) {
StatusOr<ColumnPtr> cast_nested_to_json(const ColumnPtr& column, bool allow_throw_exception) {
ColumnBuilder<TYPE_JSON> column_builder(column->size());
vpack::Builder json_builder;
for (int row = 0; row < column->size(); row++) {
if (column->is_null(row)) {
column_builder.append_null();
continue;
if (allow_throw_exception) {
for (int row = 0; row < column->size(); row++) {
if (column->is_null(row)) {
column_builder.append_null();
continue;
}
json_builder.clear();
RETURN_IF_ERROR(CastColumnItemVisitor::cast_datum_to_json(column, row, "", &json_builder));
JsonValue json(json_builder.slice());
column_builder.append(std::move(json));
}
json_builder.clear();
RETURN_IF_ERROR(CastColumnItemVisitor::cast_datum_to_json(column, row, "", &json_builder));
} else {
for (int row = 0; row < column->size(); row++) {
if (column->is_null(row)) {
column_builder.append_null();
continue;
}
json_builder.clear();
auto st = CastColumnItemVisitor::cast_datum_to_json(column, row, "", &json_builder);
if (!st.ok()) {
column_builder.append_null();
continue;
}

JsonValue json(json_builder.slice());
column_builder.append(std::move(json));
JsonValue json(json_builder.slice());
column_builder.append(std::move(json));
}
}

return column_builder.build(false);
}

Expand Down
4 changes: 4 additions & 0 deletions be/src/exprs/function_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ bool FunctionContext::error_if_overflow() const {
return _state != nullptr && _state->error_if_overflow();
}

bool FunctionContext::allow_throw_exception() const {
return _state != nullptr && _state->query_options().allow_throw_exception;
}

void FunctionContext::set_function_state(FunctionStateScope scope, void* ptr) {
switch (scope) {
case THREAD_LOCAL:
Expand Down
2 changes: 2 additions & 0 deletions be/src/exprs/function_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ class FunctionContext {

bool error_if_overflow() const;

bool allow_throw_exception() const;

std::unique_ptr<NgramBloomFilterState>& get_ngram_state() { return _ngramState; }

private:
Expand Down
2 changes: 1 addition & 1 deletion be/src/exprs/json_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1085,7 +1085,7 @@ StatusOr<ColumnPtr> JsonFunctions::_json_keys_without_path(FunctionContext* cont

StatusOr<ColumnPtr> JsonFunctions::to_json(FunctionContext* context, const Columns& columns) {
RETURN_IF_COLUMNS_ONLY_NULL(columns);
return cast_nested_to_json(columns[0]);
return cast_nested_to_json(columns[0], context->allow_throw_exception());
}

} // namespace starrocks
10 changes: 9 additions & 1 deletion test/sql/test_json/R/to_json
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,12 @@ SELECT to_json(row(1, 1));
SELECT to_json(NULL);
-- result:
None
-- !result
-- !result
select /*+SET_VAR(sql_mode='ONLY_FULL_GROUP_BY,ALLOW_THROW_EXCEPTION')*/ to_json(map{null:null});
-- result:
E: (1064, 'key of Map should not be null')
-- !result
select /*+SET_VAR(sql_mode='ONLY_FULL_GROUP_BY')*/ to_json(map{null:null});
-- result:
None
-- !result
5 changes: 4 additions & 1 deletion test/sql/test_json/T/to_json
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ INSERT INTO t0 VALUES (2, row(1, 1));
select to_json(c1) from t0 order by c0;

SELECT to_json(row(1, 1));
SELECT to_json(NULL);
SELECT to_json(NULL);

select /*+SET_VAR(sql_mode='ONLY_FULL_GROUP_BY,ALLOW_THROW_EXCEPTION')*/ to_json(map{null:null});
select /*+SET_VAR(sql_mode='ONLY_FULL_GROUP_BY')*/ to_json(map{null:null});
Loading