Skip to content

Commit

Permalink
[Enhancement] to_json return null when unsupported
Browse files Browse the repository at this point in the history
Signed-off-by: Seaven <[email protected]>
  • Loading branch information
Seaven committed Aug 6, 2024
1 parent 3a39e5d commit 3f0e9d9
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 14 deletions.
2 changes: 1 addition & 1 deletion be/src/exprs/cast_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,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 @@ -174,6 +174,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});

0 comments on commit 3f0e9d9

Please sign in to comment.