1616
1717#include " column/array_column.h"
1818#include " column/column_builder.h"
19- #include " column/column_viewer.h"
2019#include " column/column_visitor_adapter.h"
2120#include " column/json_column.h"
2221#include " column/map_column.h"
@@ -37,11 +36,16 @@ constexpr bool is_type_complete_v<T, std::void_t<decltype(sizeof(T))>> = true;
3736// NOTE: cast in rowwise is not efficent but intuitive
3837class CastColumnItemVisitor final : public ColumnVisitorAdapter<CastColumnItemVisitor> {
3938public:
40- CastColumnItemVisitor (int row, const std::string& field_name, vpack::Builder* builder)
41- : ColumnVisitorAdapter(this ), _row(row), _field_name(field_name), _builder(builder) {}
42-
43- static Status cast_datum_to_json (const ColumnPtr& col, int row, const std::string& name, vpack::Builder* builder) {
44- CastColumnItemVisitor visitor (row, name, builder);
39+ CastColumnItemVisitor (int row, const std::string& field_name, vpack::Builder* builder, bool unindexed_struct)
40+ : ColumnVisitorAdapter(this ),
41+ _row (row),
42+ _field_name(field_name),
43+ _builder(builder),
44+ _unindexed_struct(unindexed_struct) {}
45+
46+ static Status cast_datum_to_json (const ColumnPtr& col, int row, const std::string& name, vpack::Builder* builder,
47+ bool unindexed_struct = false ) {
48+ CastColumnItemVisitor visitor (row, name, builder, unindexed_struct);
4549 try {
4650 return col->accept (&visitor);
4751 } catch (const arangodb::velocypack::Exception& e) {
@@ -111,17 +115,19 @@ class CastColumnItemVisitor final : public ColumnVisitorAdapter<CastColumnItemVi
111115 }
112116
113117 Status do_visit (const StructColumn& col) {
118+ // Use indexed or unindexed object based on _unindexed_struct flag
119+ // unindexed=true preserves field insertion order (crucial for default values)
114120 if (_field_name.empty ()) {
115- _builder->openObject ();
121+ _builder->openObject (_unindexed_struct );
116122 } else {
117- _builder->add (_field_name, vpack::Value (vpack::ValueType::Object));
123+ _builder->add (_field_name, vpack::Value (vpack::ValueType::Object, _unindexed_struct ));
118124 }
119125 const auto & names = col.field_names ();
120126 const auto columns = col.fields ();
121127 for (int i = 0 ; i < columns.size (); i++) {
122128 auto name = names.size () > i ? names[i] : fmt::format (" k{}" , i);
123129 auto & field_column = columns[i];
124- RETURN_IF_ERROR (cast_datum_to_json (field_column, _row, name, _builder));
130+ RETURN_IF_ERROR (cast_datum_to_json (field_column, _row, name, _builder, _unindexed_struct ));
125131 }
126132 if (!_builder->isClosed ()) {
127133 _builder->close ();
@@ -132,9 +138,9 @@ class CastColumnItemVisitor final : public ColumnVisitorAdapter<CastColumnItemVi
132138
133139 Status do_visit (const MapColumn& col) {
134140 if (_field_name.empty ()) {
135- _builder->openObject ();
141+ _builder->openObject (_unindexed_struct );
136142 } else {
137- _builder->add (_field_name, vpack::Value (vpack::ValueType::Object));
143+ _builder->add (_field_name, vpack::Value (vpack::ValueType::Object, _unindexed_struct ));
138144 }
139145 auto [map_start, map_size] = col.get_map_offset_size (_row);
140146 const auto & val_col = col.values_column ();
@@ -165,7 +171,7 @@ class CastColumnItemVisitor final : public ColumnVisitorAdapter<CastColumnItemVi
165171 continue ;
166172 }
167173 // VLOG(2) << "map key " << i << ": " << key_col->debug_item(i) << " , name=" << name;
168- RETURN_IF_ERROR (cast_datum_to_json (val_col, i, name, _builder));
174+ RETURN_IF_ERROR (cast_datum_to_json (val_col, i, name, _builder, _unindexed_struct ));
169175 }
170176
171177 if (!_builder->isClosed ()) {
@@ -184,7 +190,7 @@ class CastColumnItemVisitor final : public ColumnVisitorAdapter<CastColumnItemVi
184190 auto [offset, size] = col.get_element_offset_size (_row);
185191 const auto & elements = col.elements_column ();
186192 for (int i = offset; i < offset + size; i++) {
187- RETURN_IF_ERROR (cast_datum_to_json (elements, i, " " , _builder));
193+ RETURN_IF_ERROR (cast_datum_to_json (elements, i, " " , _builder, _unindexed_struct ));
188194 }
189195
190196 if (!_builder->isClosed ()) {
@@ -198,7 +204,7 @@ class CastColumnItemVisitor final : public ColumnVisitorAdapter<CastColumnItemVi
198204 if (col.is_null (_row)) {
199205 _add_element (vpack::ValueType::Null);
200206 } else {
201- RETURN_IF_ERROR (cast_datum_to_json (col.data_column (), _row, _field_name, _builder));
207+ RETURN_IF_ERROR (cast_datum_to_json (col.data_column (), _row, _field_name, _builder, _unindexed_struct ));
202208 }
203209 return {};
204210 }
@@ -219,6 +225,7 @@ class CastColumnItemVisitor final : public ColumnVisitorAdapter<CastColumnItemVi
219225 int _row;
220226 const std::string& _field_name;
221227 vpack::Builder* _builder;
228+ bool _unindexed_struct;
222229};
223230
224231// Cast nested type(including struct/map/* to json)
@@ -258,13 +265,15 @@ StatusOr<ColumnPtr> cast_nested_to_json(const ColumnPtr& column, bool allow_thro
258265 return column_builder.build (false );
259266}
260267
261- StatusOr<std::string> cast_type_to_json_str (const ColumnPtr& column, int idx) {
268+ StatusOr<std::string> cast_type_to_json_str (const ColumnPtr& column, int idx, bool unindexed_struct ) {
262269 vpack::Builder json_builder;
263270 json_builder.clear ();
264- RETURN_IF_ERROR (CastColumnItemVisitor::cast_datum_to_json (column, idx, " " , &json_builder));
265- JsonValue json (json_builder.slice ());
271+ RETURN_IF_ERROR (CastColumnItemVisitor::cast_datum_to_json (column, idx, " " , &json_builder, unindexed_struct));
266272
267- return json.to_string ();
273+ auto slice = json_builder.slice ();
274+ JsonValue json (slice);
275+ auto result = json.to_string ();
276+ return result;
268277}
269278
270- } // namespace starrocks
279+ } // namespace starrocks
0 commit comments