Repository: ClickHouse/ClickHouse
File: src/Functions/FunctionsJSON.cpp (C++)

Code before:
                else
                {
                    throw Exception(
                        ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
                        "Function {} with JSON type input supports only constant string path arguments",
                        String(TName::name));
                }

                if (!path.empty())
                    path += '.';
                path += key;
            }

            auto insertManyDefaults = [&]()
            {
                MutableColumnPtr to{result_type->createColumn()};
                to->insertManyDefaults(input_rows_count);
                return to;
            };

            /// Expand ColumnConst to full column if needed.
            ColumnPtr object_column = col_const ? col_const->convertToFullColumn() : first_column.column;

            /// Root case (no path specified) return defaults for most functions.
            if (path.empty())
                insertManyDefaults();

            /// Extract literal subcolumn (json.path returns the scalar value at that path).
            auto literal_type = data_type_object.tryGetSubcolumnType(path);
            ColumnPtr literal_subcolumn;
            if (literal_type)
                literal_subcolumn = data_type_object.getSubcolumn(path, object_column);

            /// Extract subobject subcolumn (json.^`path` returns nested object at that path).
            String sub_object_name = "^`" + path + "`";
            auto sub_object_type = data_type_object.tryGetSubcolumnType(sub_object_name);
            ColumnPtr sub_object_subcolumn;
            if (sub_object_type)
                sub_object_subcolumn = data_type_object.getSubcolumn(sub_object_name, object_column);

            /// If neither subcolumn exists, the path is absent thus return defaults.
            if (!literal_subcolumn && !sub_object_subcolumn)
                insertManyDefaults();

            /// Merge literal and subobject subcolumns (same logic as `getObjectElement' in tupleElement.cpp):
            /// For each row: prefer literal (scalar) value, if absent, use subobject (nested JSON).
            ColumnPtr merged;
            DataTypePtr merged_type;

            if (!sub_object_subcolumn
                || sub_object_subcolumn->getNumberOfDefaultRows() == sub_object_subcolumn->size())

Review comment (suggestion):
I believe it should be `return insertManyDefaults();`. 

Also we can avoid using a lambda here and use
```c++
return result_type->createColumnConstWithDefaultValue(input_rows_count)->convertToFullColumnIfConst();
```

Code after:
                    key = (*arg.column)[0].safeGet<String>();
                }
                else
                {
                    throw Exception(
                        ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
                        "Function {} with JSON type input supports only constant string path arguments",
                        String(TName::name));
                }

                if (!path.empty())
                    path += '.';
                path += key;
            }

            /// Expand ColumnConst to full column if needed.
            ColumnPtr object_column = col_const ? col_const->convertToFullColumn() : first_column.column;

            /// Root case (no path specified) return defaults for most functions.
            if (path.empty())
                return result_type->createColumnConstWithDefaultValue(input_rows_count)->convertToFullColumnIfConst();

            /// Extract literal subcolumn (json.path returns the scalar value at that path).
            auto literal_type = data_type_object.getSubcolumnType(path);
            auto literal_subcolumn = data_type_object.getSubcolumn(path, object_column);

            ColumnPtr merged;
            DataTypePtr merged_type;

            /// When the path has a type hint (literal_type is not Dynamic), the subobject may not be convertible to that type.
            /// For typed paths we skip the subobject merge and use only the literal subcolumn.
            if (literal_type && !isDynamic(literal_type))
            {
                merged = literal_subcolumn;
                merged_type = literal_type;
            }
            else
            {
                /// Extract subobject subcolumn (json.^`path` returns nested object at that path).
                String sub_object_name = "^`" + path + "`";
                auto sub_object_type = data_type_object.getSubcolumnType(sub_object_name);
                ColumnPtr sub_object_subcolumn = data_type_object.getSubcolumn(sub_object_name, object_column);

                /// Merge literal and subobject subcolumns (same logic as `getObjectElement' in tupleElement.cpp):
                /// For each row: prefer literal (scalar) value, if absent, use subobject (nested JSON).
                if (sub_object_subcolumn->getNumberOfDefaultRows() == sub_object_subcolumn->size())
                {
                    /// No nested subobject at this path (only literal exists).
                    merged = literal_subcolumn;
                    merged_type = literal_type;
                }